57 #if defined(__NetBSD__) || defined(__FreeBSD__)
60 #include <sys/sysmacros.h>
76 #error "Upgrade your libpri"
82 #if !defined(LIBSS7_ABI_COMPATIBILITY)
83 #error "Upgrade your libss7"
84 #elif LIBSS7_ABI_COMPATIBILITY != 2
85 #error "Your installed libss7 is not compatible"
89 #if defined(HAVE_OPENR2)
91 #define SIG_MFCR2_MAX_CHANNELS 672
124 #include "asterisk/features_config.h"
126 #include "asterisk/stasis_channels.h"
603 #define SMDI_MD_WAIT_TIMEOUT 1500
605 static const char *
const lbostr[] = {
606 "0 db (CSU)/0-133 feet (DSX-1)",
607 "133-266 feet (DSX-1)",
608 "266-399 feet (DSX-1)",
609 "399-533 feet (DSX-1)",
610 "533-655 feet (DSX-1)",
622 .resync_threshold = 1000,
640 #define DEFAULT_CIDRINGS 1
642 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
646 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
648 static const char tdesc[] =
"DAHDI Telephony"
649 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
651 #if defined(HAVE_PRI)
654 #if defined(HAVE_SS7)
655 #if defined(HAVE_PRI)
660 #if defined(HAVE_OPENR2)
661 #if defined(HAVE_PRI) || defined(HAVE_SS7)
669 static const char config[] =
"chan_dahdi.conf";
672 #define NUM_SPANS DAHDI_MAX_SPANS
677 #define CHAN_PSEUDO -2
679 #define CALLPROGRESS_PROGRESS 1
680 #define CALLPROGRESS_FAX_OUTGOING 2
681 #define CALLPROGRESS_FAX_INCOMING 4
682 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
684 #define NUM_CADENCE_MAX 25
685 static int num_cadence = 4;
686 static int user_has_defined_cadences = 0;
688 static int has_pseudo;
690 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
691 { { 125, 125, 2000, 4000 } },
692 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
693 { { 125, 125, 125, 125, 125, 4000 } },
694 { { 1000, 500, 2500, 5000 } },
709 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
711 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
712 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
714 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
715 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
717 static char defaultcic[64] =
"";
718 static char defaultozz[64] =
"";
722 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
723 static int mwisend_rpas = 0;
726 static char progzone[10] =
"";
728 static int usedistinctiveringdetection = 0;
729 static int distinctiveringaftercid = 0;
731 static int numbufs = 4;
733 static int mwilevel = 512;
734 static int dtmfcid_level = 256;
736 #define REPORT_CHANNEL_ALARMS 1
737 #define REPORT_SPAN_ALARMS 2
738 static int report_alarms = REPORT_CHANNEL_ALARMS;
741 static int pridebugfd = -1;
742 static char pridebugfilename[1024] =
"";
749 static int ifcount = 0;
752 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
762 static ast_cond_t ss_thread_complete;
763 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
764 AST_MUTEX_DEFINE_STATIC(restart_lock);
765 static int ss_thread_count = 0;
766 static int num_restart_pending = 0;
768 static int restart_monitor(
void);
770 static int dahdi_sendtext(
struct ast_channel *c,
const char *text);
776 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
785 i = DAHDI_IOMUX_SIGEVENT;
786 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
788 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
794 #define READ_SIZE 160
796 #define MASK_AVAIL (1 << 0)
797 #define MASK_INUSE (1 << 1)
799 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
800 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
801 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
802 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
803 #define MIN_MS_SINCE_FLASH ((2000) )
804 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
805 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE)
813 #if defined(HAVE_SS7)
819 static struct dahdi_ss7 linksets[NUM_SPANS];
821 static int cur_ss7type = -1;
822 static int cur_slc = -1;
823 static int cur_linkset = -1;
824 static int cur_pointcode = -1;
825 static int cur_cicbeginswith = -1;
826 static int cur_adjpointcode = -1;
827 static int cur_networkindicator = -1;
828 static int cur_defaultdpc = -1;
832 struct dahdi_mfcr2_conf {
833 openr2_variant_t variant;
835 int metering_pulse_timeout;
838 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
843 int dtmf_end_timeout;
845 signed int get_ani_first:2;
846 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
847 signed int skip_category_request:2;
849 unsigned int call_files:1;
850 unsigned int allow_collect_calls:1;
851 unsigned int charge_calls:1;
852 unsigned int accept_on_offer:1;
853 unsigned int forced_release:1;
854 unsigned int double_answer:1;
855 signed int immediate_accept:2;
856 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
857 signed int dtmf_dialing:2;
858 signed int dtmf_detection:2;
860 char logdir[OR2_MAX_PATH];
861 char r2proto_file[OR2_MAX_PATH];
862 openr2_log_level_t loglevel;
863 openr2_calling_party_category_t category;
870 openr2_context_t *protocol_context;
871 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
875 struct dahdi_mfcr2_conf
conf;
878 struct r2link_entry {
879 struct dahdi_mfcr2 mfcr2;
887 static
int r2links_count = 0;
902 #if defined(HAVE_PRI_CCSS)
913 #define POLARITY_IDLE 0
914 #define POLARITY_REV 1
916 const char *
const subnames[] = {
925 #if defined(HAVE_PRI)
939 } dahdi_pseudo_parms;
958 #if defined(HAVE_SS7)
959 struct dahdi_ss7 ss7;
963 struct dahdi_mfcr2_conf mfcr2;
965 struct dahdi_params timing;
974 char smdi_port[SMDI_MAX_FILENAME_LEN];
999 .switchtype = PRI_SWITCH_NI2,
1000 .dialplan = PRI_UNKNOWN + 1,
1001 .localdialplan = PRI_NATIONAL_ISDN + 1,
1002 .nodetype = PRI_CPE,
1003 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
1005 #if defined(HAVE_PRI_CCSS)
1006 .cc_ptmp_recall_mode = 1,
1007 .cc_qsig_signaling_link_req = 1,
1008 .cc_qsig_signaling_link_rsp = 1,
1014 .internationalprefix =
"",
1015 .nationalprefix =
"",
1017 .privateprefix =
"",
1018 .unknownprefix =
"",
1020 .resetinterval = -1,
1023 #if defined(HAVE_SS7)
1025 .called_nai = SS7_NAI_NATIONAL,
1026 .calling_nai = SS7_NAI_NATIONAL,
1027 .internationalprefix =
"",
1028 .nationalprefix =
"",
1029 .subscriberprefix =
"",
1030 .unknownprefix =
"",
1031 .networkroutedprefix =
""
1036 .variant = OR2_VAR_ITU,
1037 .mfback_timeout = -1,
1038 .metering_pulse_timeout = -1,
1041 .get_ani_first = -1,
1042 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
1043 .skip_category_request = -1,
1046 .allow_collect_calls = 0,
1048 .accept_on_offer = 1,
1049 .forced_release = 0,
1051 .immediate_accept = -1,
1052 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
1054 .dtmf_detection = -1,
1055 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
1056 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
1058 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
1059 .dtmf_end_timeout = -1,
1063 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
1064 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
1068 .context =
"default",
1073 .mohinterpret =
"default",
1076 .transfertobusy = 1,
1079 .ani_info_digits = 2,
1080 .ani_wink_time = 1000,
1081 .ani_timeout = 10000,
1083 .cid_signalling = CID_SIG_BELL,
1084 .cid_start = CID_START_RING,
1085 .dahditrcallerid = 0,
1094 .echocancel.head.tap_length = 1,
1102 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
1105 .polarityonanswerdelay = 600,
1109 .buf_policy = DAHDI_POLICY_IMMEDIATE,
1128 .ignore_failed_channels = 1,
1129 .smdi_port =
"/dev/ttyS0",
1138 const char *
data,
int *cause);
1139 static int dahdi_digit_begin(
struct ast_channel *ast,
char digit);
1140 static int dahdi_digit_end(
struct ast_channel *ast,
char digit,
unsigned int duration);
1141 static int dahdi_sendtext(
struct ast_channel *c,
const char *text);
1142 static int dahdi_call(
struct ast_channel *ast,
const char *rdest,
int timeout);
1152 static int dahdi_func_read(
struct ast_channel *chan,
const char *
function,
char *
data,
char *buf,
size_t len);
1153 static int dahdi_func_write(
struct ast_channel *chan,
const char *
function,
char *
data,
const char *value);
1154 static int dahdi_devicestate(
const char *
data);
1159 .description = tdesc,
1160 .requester = dahdi_request,
1161 .send_digit_begin = dahdi_digit_begin,
1162 .send_digit_end = dahdi_digit_end,
1163 .send_text = dahdi_sendtext,
1165 .hangup = dahdi_hangup,
1168 .write = dahdi_write,
1169 .exception = dahdi_exception,
1170 .indicate = dahdi_indicate,
1171 .fixup = dahdi_fixup,
1173 .queryoption = dahdi_queryoption,
1174 .func_channel_read = dahdi_func_read,
1175 .func_channel_write = dahdi_func_write,
1176 .devicestate = dahdi_devicestate,
1180 #define GET_CHANNEL(p) ((p)->channel)
1182 static enum analog_sigtype dahdisig_to_analogsig(
int sig)
1186 return ANALOG_SIG_FXOLS;
1188 return ANALOG_SIG_FXOGS;
1190 return ANALOG_SIG_FXOKS;
1192 return ANALOG_SIG_FXSLS;
1194 return ANALOG_SIG_FXSGS;
1196 return ANALOG_SIG_FXSKS;
1198 return ANALOG_SIG_EMWINK;
1200 return ANALOG_SIG_EM;
1202 return ANALOG_SIG_EM_E1;
1204 return ANALOG_SIG_FEATD;
1206 return ANALOG_SIG_FEATDMF;
1210 return ANALOG_SIG_FGC_CAMA;
1211 case SIG_FGC_CAMAMF:
1212 return ANALOG_SIG_FGC_CAMAMF;
1214 return ANALOG_SIG_FEATB;
1216 return ANALOG_SIG_SFWINK;
1218 return ANALOG_SIG_SF;
1220 return ANALOG_SIG_SF_FEATD;
1221 case SIG_SF_FEATDMF:
1222 return ANALOG_SIG_SF_FEATDMF;
1223 case SIG_FEATDMF_TA:
1224 return ANALOG_SIG_FEATDMF_TA;
1226 return ANALOG_SIG_FEATB;
1233 static int analog_tone_to_dahditone(
enum analog_tone tone)
1236 case ANALOG_TONE_RINGTONE:
1237 return DAHDI_TONE_RINGTONE;
1238 case ANALOG_TONE_STUTTER:
1239 return DAHDI_TONE_STUTTER;
1240 case ANALOG_TONE_CONGESTION:
1241 return DAHDI_TONE_CONGESTION;
1242 case ANALOG_TONE_DIALTONE:
1243 return DAHDI_TONE_DIALTONE;
1244 case ANALOG_TONE_DIALRECALL:
1245 return DAHDI_TONE_DIALRECALL;
1246 case ANALOG_TONE_INFO:
1247 return DAHDI_TONE_INFO;
1253 static int analogsub_to_dahdisub(
enum analog_sub analogsub)
1257 switch (analogsub) {
1268 ast_log(LOG_ERROR,
"Unidentified sub!\n");
1283 static void release_doomed_pris(
void)
1292 ast_debug(4,
"Destroying span %d from doomed queue.\n",
1294 pri_destroy_span(entry->pri);
1319 if (entry->pri == pri) {
1327 ast_log(LOG_WARNING,
"Failed allocating memory for a doomed_pri.\n");
1332 ast_debug(4,
"Queue span %d for destruction.\n", pri->
span);
1350 static int dahdi_dial_str(
struct dahdi_pvt *pvt,
int operation,
const char *dial_str)
1355 struct dahdi_dialoperation zo = {
1361 for (offset = 0; offset <
sizeof(zo.dialstr) - 1; ++offset) {
1368 if (offset >=
sizeof(zo.dialstr) - 3) {
1372 zo.dialstr[offset] =
'w';
1374 zo.dialstr[offset] =
'w';
1377 zo.dialstr[offset] = *pos++;
1381 ast_debug(1,
"Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1382 pvt->
channel, dial_str, zo.dialstr);
1385 ast_log(LOG_WARNING,
"Channel %d: Couldn't dial '%s': %s\n",
1386 pvt->
channel, dial_str, strerror(errno));
1392 static enum analog_event dahdievent_to_analogevent(
int event);
1393 static int bump_gains(
struct dahdi_pvt *p);
1394 static int dahdi_setlinear(
int dfd,
int linear);
1396 static int my_start_cid_detect(
void *pvt,
int cid_signalling)
1402 ast_log(LOG_ERROR,
"Unable to alloc callerid\n");
1406 dahdi_setlinear(p->
subs[index].dfd, 0);
1411 static int restore_gains(
struct dahdi_pvt *p);
1413 static int my_stop_cid_detect(
void *pvt)
1423 dahdi_setlinear(p->
subs[index].dfd, p->
subs[index].linear);
1429 static int my_get_callerid(
void *pvt,
char *namebuf,
char *numbuf,
enum analog_event *ev,
size_t timeout)
1433 struct pollfd poller;
1437 unsigned char buf[256];
1442 poller.events = POLLPRI | POLLIN;
1445 res = poll(&poller, 1, timeout);
1447 if (poller.revents & POLLPRI) {
1452 if (poller.revents & POLLIN) {
1458 res = read(p->
subs[index].dfd, buf,
sizeof(buf));
1460 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
1464 if (analog_p->ringt > 0) {
1465 if (!(--analog_p->ringt)) {
1481 ast_log(LOG_WARNING,
"Failed to decode CallerID\n");
1493 if (flags & (CID_PRIVATE_NUMBER | CID_UNKNOWN_NUMBER)) {
1498 caller.id.name.presentation = caller.id.number.presentation = (flags & CID_PRIVATE_NUMBER) ?
1499 AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED : AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED;
1507 ast_channel_redirecting(chan)->
reason.
code = redirecting;
1510 if (flags & CID_QUALIFIER) {
1520 *ev = ANALOG_EVENT_NONE;
1524 static const char *event2str(
int event);
1526 static int my_distinctive_ring(
struct ast_channel *chan,
void *pvt,
int idx,
int *ringdata)
1528 unsigned char buf[256];
1530 int curRingData[RING_PATTERNS];
1536 int checkaftercid = 0;
1537 const char *matched_context;
1541 if (ringdata == NULL) {
1542 ringdata = curRingData;
1548 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1550 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1551 ringdata[receivedRingT] = 0;
1554 if (checkaftercid && distinctiveringaftercid) {
1555 ast_verb(3,
"Detecting post-CID distinctive ring\n");
1559 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1560 res = ioctl(p->
subs[idx].dfd, DAHDI_IOMUX, &i);
1562 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
1566 if (i & DAHDI_IOMUX_SIGEVENT) {
1568 ast_debug(3,
"Got event %d (%s)...\n", res, event2str(res));
1569 if (res == DAHDI_EVENT_NOALARM) {
1571 analog_p->inalarm = 0;
1572 }
else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1574 ringdata[receivedRingT] = analog_p->ringt;
1576 if (analog_p->ringt < analog_p->ringt_base / 2) {
1581 if (++receivedRingT == RING_PATTERNS) {
1585 }
else if (i & DAHDI_IOMUX_READ) {
1586 res = read(p->
subs[idx].dfd, buf,
sizeof(buf));
1588 if (errno != ELAST) {
1589 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
1595 if (analog_p->ringt > 0) {
1596 if (!(--analog_p->ringt)) {
1605 ast_verb(3,
"Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1607 for (counter = 0; counter < 3; counter++) {
1608 int range = p->
drings.ringnum[counter].range;
1611 ast_verb(3,
"Checking %d,%d,%d with +/- %d range\n",
1612 p->
drings.ringnum[counter].ring[0],
1613 p->
drings.ringnum[counter].ring[1],
1614 p->
drings.ringnum[counter].ring[2],
1616 for (counter1 = 0; counter1 < 3; counter1++) {
1617 int ring = p->
drings.ringnum[counter].ring[counter1];
1620 ast_verb(3,
"Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1621 ringdata[counter1]);
1623 }
else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1624 ast_verb(3,
"Ring pattern %d is in range: %d to %d\n",
1625 ringdata[counter1], ring - range, ring + range);
1633 if (distMatches == 3) {
1636 ast_verb(3,
"Matched Distinctive Ring context %s\n", matched_context);
1642 if (strcmp(p->
context, matched_context) != 0) {
1644 ast_channel_context_set(chan, matched_context);
1650 static int my_stop_callwait(
void *pvt)
1660 static int send_callerid(
struct dahdi_pvt *p);
1661 static int save_conference(
struct dahdi_pvt *p);
1662 static int restore_conference(
struct dahdi_pvt *p);
1664 static int my_callwait(
void *pvt)
1670 ast_log(LOG_WARNING,
"Spill already exists?!?\n");
1698 static int my_send_callerid(
void *pvt,
int cwcid,
struct ast_party_caller *caller)
1706 ast_log(LOG_WARNING,
"cidspill already exists??\n");
1730 ast_verb(3,
"CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1751 static int my_dsp_reset_and_flush_digits(
void *pvt)
1760 static int my_dsp_set_digitmode(
void *pvt,
enum analog_dsp_digitmode mode)
1764 if (p->
channel == CHAN_PSEUDO)
1765 ast_log(LOG_ERROR,
"You have assumed incorrectly sir!\n");
1767 if (mode == ANALOG_DIGITMODE_DTMF) {
1771 ast_dsp_free(p->
dsp);
1780 ast_log(LOG_ERROR,
"Unable to allocate DSP\n");
1786 }
else if (mode == ANALOG_DIGITMODE_MF) {
1790 ast_log(LOG_ERROR,
"Unable to allocate DSP\n");
1799 static int dahdi_wink(
struct dahdi_pvt *p,
int index);
1801 static int my_wink(
void *pvt,
enum analog_sub sub)
1804 int index = analogsub_to_dahdisub(sub);
1806 ast_log(LOG_ERROR,
"We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1808 return dahdi_wink(p, index);
1811 static void wakeup_sub(
struct dahdi_pvt *p,
int a);
1813 static int reset_conf(
struct dahdi_pvt *p);
1815 static inline int dahdi_confmute(
struct dahdi_pvt *p,
int muted);
1821 int idx = analogsub_to_dahdisub(analog_index);
1823 ast_debug(1,
"%s DTMF digit: 0x%02X '%c' on %s\n",
1833 struct dahdi_bufferinfo bi = {
1840 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1841 ast_log(LOG_WARNING,
"Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1850 ast_debug(1,
"Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1852 if (strcmp(ast_channel_exten(ast),
"fax")) {
1853 const char *target_context = ast_channel_context(ast);
1863 ast_mutex_unlock(&p->
lock);
1864 ast_channel_unlock(ast);
1866 S_COR(ast_channel_caller(ast)->
id.
number.valid, ast_channel_caller(ast)->
id.
number.str, NULL))) {
1867 ast_verb(3,
"Redirecting %s to fax extension\n", ast_channel_name(ast));
1871 ast_log(LOG_WARNING,
"Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1873 ast_log(LOG_NOTICE,
"Fax detected, but no fax extension\n");
1875 ast_channel_lock(ast);
1876 ast_mutex_lock(&p->
lock);
1878 ast_debug(1,
"Already in a fax extension, not redirecting\n");
1883 dahdi_confmute(p, 0);
1887 *dest = &p->
subs[idx].
f;
1891 static void my_lock_private(
void *pvt)
1894 ast_mutex_lock(&p->
lock);
1897 static void my_unlock_private(
void *pvt)
1900 ast_mutex_unlock(&p->
lock);
1903 static void my_deadlock_avoidance_private(
void *pvt)
1907 DEADLOCK_AVOIDANCE(&p->
lock);
1917 if (!channel_string) {
1927 "DAHDIGroup: %llu\r\n"
1929 "DAHDIChannel: %s\r\n",
1937 .to_ami = dahdichannel_to_ami,
1945 ast_assert(dahdi_channel != NULL);
1950 "channel", dahdi_channel);
1955 ast_channel_lock(chan);
1957 ast_channel_unlock(chan);
1972 if (p->
channel < CHAN_PSEUDO) {
1974 snprintf(ch_name,
sizeof(ch_name),
"no-media (%d)", p->
channel);
1975 }
else if (p->
channel == CHAN_PSEUDO) {
1977 strcpy(ch_name,
"pseudo");
1980 snprintf(ch_name,
sizeof(ch_name),
"%d", p->
channel);
1994 static void my_ami_channel_event(
void *pvt,
struct ast_channel *chan)
1998 dahdi_ami_channel_event(p, chan);
2005 static int my_set_linear_mode(
void *pvt,
enum analog_sub sub,
int linear_mode)
2009 int idx = analogsub_to_dahdisub(sub);
2011 dahdi_setlinear(p->
subs[idx].dfd, linear_mode);
2012 oldval = p->
subs[idx].linear;
2013 p->
subs[idx].linear = linear_mode ? 1 : 0;
2017 static void my_set_inthreeway(
void *pvt,
enum analog_sub sub,
int inthreeway)
2020 int idx = analogsub_to_dahdisub(sub);
2022 p->
subs[idx].inthreeway = inthreeway;
2026 static void handle_alarms(
struct dahdi_pvt *p,
int alms);
2027 static void my_get_and_handle_alarms(
void *pvt)
2033 handle_alarms(p, res);
2036 static void *my_get_sigpvt_bridged_channel(
struct ast_channel *chan)
2041 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
2050 static int my_get_sub_fd(
void *pvt,
enum analog_sub sub)
2053 int dahdi_sub = analogsub_to_dahdisub(sub);
2054 return p->
subs[dahdi_sub].dfd;
2057 static void my_set_cadence(
void *pvt,
int *cid_rings,
struct ast_channel *ast)
2064 ast_log(LOG_WARNING,
"Unable to set distinctive ring cadence %d on '%s': %s\n", p->
distinctivering, ast_channel_name(ast), strerror(errno));
2068 ast_log(LOG_WARNING,
"Cadence %d is not defined, falling back to default ring cadence\n", p->
distinctivering);
2070 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
2071 ast_log(LOG_WARNING,
"Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
2076 static void my_set_alarm(
void *pvt,
int in_alarm)
2083 static void my_set_dialing(
void *pvt,
int is_dialing)
2090 static void my_set_outgoing(
void *pvt,
int is_outgoing)
2097 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2098 static void my_set_digital(
void *pvt,
int is_digital)
2106 #if defined(HAVE_SS7)
2107 static void my_set_inservice(
void *pvt,
int is_inservice)
2115 #if defined(HAVE_SS7)
2116 static void my_set_locallyblocked(
void *pvt,
int is_blocked)
2124 #if defined(HAVE_SS7)
2125 static void my_set_remotelyblocked(
void *pvt,
int is_blocked)
2133 static void my_set_ringtimeout(
void *pvt,
int ringt)
2139 static void my_set_waitingfordt(
void *pvt,
struct ast_channel *ast)
2167 ast_log(LOG_ERROR,
"Unable to allocate DSP\n");
2179 static int my_check_waitingfordt(
void *pvt)
2190 static void my_set_confirmanswer(
void *pvt,
int flag)
2196 static int my_check_confirmanswer(
void *pvt)
2206 static void my_set_callwaiting(
void *pvt,
int callwaiting_enable)
2213 static void my_cancel_cidspill(
void *pvt)
2219 restore_conference(p);
2222 static int my_confmute(
void *pvt,
int mute)
2225 return dahdi_confmute(p, mute);
2228 static void my_set_pulsedial(
void *pvt,
int flag)
2234 static void my_set_new_owner(
void *pvt,
struct ast_channel *new_owner)
2238 p->
owner = new_owner;
2241 static const char *my_get_orig_dialstring(
void *pvt)
2245 return p->dialstring;
2248 static void my_increase_ss_count(
void)
2250 ast_mutex_lock(&ss_thread_lock);
2252 ast_mutex_unlock(&ss_thread_lock);
2255 static void my_decrease_ss_count(
void)
2257 ast_mutex_lock(&ss_thread_lock);
2259 ast_cond_signal(&ss_thread_complete);
2260 ast_mutex_unlock(&ss_thread_lock);
2263 static void my_all_subchannels_hungup(
void *pvt)
2272 ast_dsp_free(p->
dsp);
2278 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETLAW, &law);
2280 ast_log(LOG_WARNING,
"Unable to set law on channel %d to default: %s\n", p->
channel, strerror(errno));
2289 for (i = 0; i < 3; i++) {
2290 p->
subs[i].owner = NULL;
2296 if (num_restart_pending == 0) {
2303 static int my_conf_del(
void *pvt,
enum analog_sub sub)
2306 int x = analogsub_to_dahdisub(sub);
2308 return conf_del(p, &p->
subs[x], x);
2313 static int my_conf_add(
void *pvt,
enum analog_sub sub)
2316 int x = analogsub_to_dahdisub(sub);
2318 return conf_add(p, &p->
subs[x], x, 0);
2323 static int my_complete_conference_update(
void *pvt,
int needconference)
2326 int needconf = needconference;
2331 useslavenative = isslavenative(p, &slave);
2335 for (x = 0; x < MAX_SLAVES; x++) {
2340 conf_add(p, &p->
slaves[x]->
subs[SUB_REAL], SUB_REAL, 0);
2356 if (isslavenative(p->
master, NULL)) {
2371 static int check_for_conference(
struct dahdi_pvt *p);
2373 static int my_check_for_conference(
void *pvt)
2376 return check_for_conference(p);
2386 da = analogsub_to_dahdisub(a);
2387 db = analogsub_to_dahdisub(b);
2389 tchan = p->
subs[da].chan;
2390 p->
subs[da].chan = p->
subs[db].chan;
2391 p->
subs[db].chan = tchan;
2393 tinthreeway = p->
subs[da].inthreeway;
2394 p->
subs[da].inthreeway = p->
subs[db].inthreeway;
2395 p->
subs[db].inthreeway = tinthreeway;
2397 p->
subs[da].owner = ast_a;
2398 p->
subs[db].owner = ast_b;
2428 int dsub = analogsub_to_dahdisub(sub);
2430 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2433 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2434 static int dahdi_setlaw(
int dfd,
int law)
2437 res = ioctl(dfd, DAHDI_SETLAW, &law);
2444 #if defined(HAVE_PRI)
2452 ast_callid callid = 0;
2456 case SIG_PRI_LIB_HANDLE_CASES:
2457 if (((
struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2465 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2466 ast_log(LOG_WARNING,
"Unable to set audio mode on channel %d to %d: %s\n",
2467 p->
channel, audio, strerror(errno));
2472 if (law != SIG_PRI_DEFLAW) {
2473 dahdi_setlaw(p->
subs[
SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2479 case SIG_PRI_DEFLAW:
2483 newlaw = DAHDI_LAW_ALAW;
2486 newlaw = DAHDI_LAW_MULAW;
2490 return dahdi_new_callid_clean(p, state, 0,
SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2494 static int set_actual_gain(
int fd,
float rxgain,
float txgain,
float rxdrc,
float txdrc,
int law);
2496 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2504 static void my_pri_ss7_open_media(
void *p)
2515 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2517 ast_log(LOG_WARNING,
"Unable to enable audio mode on channel %d (%s)\n",
2518 pvt->
channel, strerror(errno));
2522 res = dahdi_setlaw(dfd, pvt->
law);
2524 ast_log(LOG_WARNING,
"Unable to set law on channel %d\n", pvt->
channel);
2529 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->
txdrc, pvt->
law);
2535 ast_log(LOG_WARNING,
"Unable to set gains on channel %d\n", pvt->
channel);
2544 #if defined(HAVE_PRI)
2555 static void my_pri_dial_digits(
void *p,
const char *dial_string)
2557 char dial_str[DAHDI_MAX_DTMF_BUF];
2561 snprintf(dial_str,
sizeof(dial_str),
"T%s", dial_string);
2562 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2569 static int unalloc_sub(
struct dahdi_pvt *p,
int x);
2571 static int my_unallocate_sub(
void *pvt,
enum analog_sub analogsub)
2575 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2578 static int alloc_sub(
struct dahdi_pvt *p,
int x);
2580 static int my_allocate_sub(
void *pvt,
enum analog_sub analogsub)
2584 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2589 static int my_has_voicemail(
void *pvt)
2596 static int my_play_tone(
void *pvt,
enum analog_sub sub,
enum analog_tone tone)
2601 index = analogsub_to_dahdisub(sub);
2603 return tone_zone_play_tone(p->
subs[index].dfd, analog_tone_to_dahditone(tone));
2606 static enum analog_event dahdievent_to_analogevent(
int event)
2608 enum analog_event res;
2611 case DAHDI_EVENT_ONHOOK:
2612 res = ANALOG_EVENT_ONHOOK;
2614 case DAHDI_EVENT_RINGOFFHOOK:
2615 res = ANALOG_EVENT_RINGOFFHOOK;
2617 case DAHDI_EVENT_WINKFLASH:
2618 res = ANALOG_EVENT_WINKFLASH;
2620 case DAHDI_EVENT_ALARM:
2621 res = ANALOG_EVENT_ALARM;
2623 case DAHDI_EVENT_NOALARM:
2624 res = ANALOG_EVENT_NOALARM;
2626 case DAHDI_EVENT_DIALCOMPLETE:
2627 res = ANALOG_EVENT_DIALCOMPLETE;
2629 case DAHDI_EVENT_RINGERON:
2630 res = ANALOG_EVENT_RINGERON;
2632 case DAHDI_EVENT_RINGEROFF:
2633 res = ANALOG_EVENT_RINGEROFF;
2635 case DAHDI_EVENT_HOOKCOMPLETE:
2636 res = ANALOG_EVENT_HOOKCOMPLETE;
2638 case DAHDI_EVENT_PULSE_START:
2639 res = ANALOG_EVENT_PULSE_START;
2641 case DAHDI_EVENT_POLARITY:
2642 res = ANALOG_EVENT_POLARITY;
2644 case DAHDI_EVENT_RINGBEGIN:
2645 res = ANALOG_EVENT_RINGBEGIN;
2647 case DAHDI_EVENT_EC_DISABLED:
2648 res = ANALOG_EVENT_EC_DISABLED;
2650 case DAHDI_EVENT_REMOVED:
2651 res = ANALOG_EVENT_REMOVED;
2653 case DAHDI_EVENT_NEONMWI_ACTIVE:
2654 res = ANALOG_EVENT_NEONMWI_ACTIVE;
2656 case DAHDI_EVENT_NEONMWI_INACTIVE:
2657 res = ANALOG_EVENT_NEONMWI_INACTIVE;
2659 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2660 case DAHDI_EVENT_TX_CED_DETECTED:
2661 res = ANALOG_EVENT_TX_CED_DETECTED;
2663 case DAHDI_EVENT_RX_CED_DETECTED:
2664 res = ANALOG_EVENT_RX_CED_DETECTED;
2666 case DAHDI_EVENT_EC_NLP_DISABLED:
2667 res = ANALOG_EVENT_EC_NLP_DISABLED;
2669 case DAHDI_EVENT_EC_NLP_ENABLED:
2670 res = ANALOG_EVENT_EC_NLP_ENABLED;
2673 case DAHDI_EVENT_PULSEDIGIT:
2674 res = ANALOG_EVENT_PULSEDIGIT;
2676 case DAHDI_EVENT_DTMFDOWN:
2677 res = ANALOG_EVENT_DTMFDOWN;
2679 case DAHDI_EVENT_DTMFUP:
2680 res = ANALOG_EVENT_DTMFUP;
2683 switch(event & 0xFFFF0000) {
2684 case DAHDI_EVENT_PULSEDIGIT:
2685 case DAHDI_EVENT_DTMFDOWN:
2686 case DAHDI_EVENT_DTMFUP:
2694 res = ANALOG_EVENT_ERROR;
2703 static int my_wait_event(
void *pvt)
2710 static int my_get_event(
void *pvt)
2721 return dahdievent_to_analogevent(res);
2724 static int my_is_off_hook(
void *pvt)
2728 struct dahdi_params par;
2730 memset(&par, 0,
sizeof(par));
2733 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2737 par.rxisoffhook = 0;
2740 ast_log(LOG_WARNING,
"Unable to check hook state on channel %d: %s\n", p->
channel, strerror(errno));
2743 if ((p->
sig == SIG_FXSKS) || (p->
sig == SIG_FXSGS)) {
2747 return (par.rxbits > -1) || par.rxisoffhook;
2750 return par.rxisoffhook;
2753 static int my_set_echocanceller(
void *pvt,
int enable)
2760 dahdi_ec_disable(p);
2765 static int dahdi_ring_phone(
struct dahdi_pvt *p);
2767 static int my_ring(
void *pvt)
2771 return dahdi_ring_phone(p);
2774 static int my_flash(
void *pvt)
2777 int func = DAHDI_FLASH;
2778 return ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_HOOK, &func);
2781 static inline int dahdi_set_hook(
int fd,
int hs);
2783 static int my_off_hook(
void *pvt)
2786 return dahdi_set_hook(p->
subs[
SUB_REAL].dfd, DAHDI_OFFHOOK);
2789 static void my_set_needringing(
void *pvt,
int value)
2795 static void my_set_polarity(
void *pvt,
int value)
2799 if (p->
channel == CHAN_PSEUDO) {
2803 ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2806 static void my_start_polarityswitch(
void *pvt)
2811 my_set_polarity(pvt, 0);
2815 static void my_answer_polarityswitch(
void *pvt)
2823 my_set_polarity(pvt, 1);
2826 static void my_hangup_polarityswitch(
void *pvt)
2835 my_set_polarity(pvt, 0);
2837 my_set_polarity(pvt, 1);
2845 struct dahdi_params dahdip;
2849 ast_log(LOG_WARNING,
"%s is not a DAHDI channel\n", ast_channel_name(chan));
2853 memset(&dahdip, 0,
sizeof(dahdip));
2854 res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip);
2857 ast_log(LOG_WARNING,
"Unable to get parameters of %s: %s\n", ast_channel_name(chan), strerror(errno));
2860 if (!(dahdip.sigtype & __DAHDI_SIG_FXO)) {
2861 ast_log(LOG_WARNING,
"%s is not FXO signalled\n", ast_channel_name(chan));
2865 pvt = ast_channel_tech_pvt(chan);
2866 if (!dahdi_analog_lib_handles(pvt->
sig, 0, 0)) {
2867 ast_log(LOG_WARNING,
"Channel signalling is not analog");
2874 static int polarity_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buffer,
size_t buflen)
2883 snprintf(buffer, buflen,
"%d", pvt->
polarity);
2888 static int polarity_write(
struct ast_channel *chan,
const char *cmd,
char *data,
const char *value)
2898 if (!strcasecmp(value,
"idle")) {
2900 }
else if (!strcasecmp(value,
"reverse")) {
2901 polarity = POLARITY_REV;
2903 polarity = atoi(value);
2906 if (polarity !=
POLARITY_IDLE && polarity != POLARITY_REV) {
2907 ast_log(LOG_WARNING,
"Invalid polarity: '%s'\n", value);
2911 my_set_polarity(pvt, polarity);
2917 .write = polarity_write,
2918 .read = polarity_read,
2921 static int my_start(
void *pvt)
2924 int x = DAHDI_START;
2933 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2934 ast_log(LOG_ERROR,
"Fix the dial_digits callback!\n");
2939 ast_log(LOG_ERROR,
"Trying to dial_digits '%s' on channel %d subchannel %u\n",
2940 dop->dialstr, p->
channel, sub);
2944 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2947 static void dahdi_train_ec(
struct dahdi_pvt *p);
2949 static int my_train_echocanceller(
void *pvt)
2958 static int my_is_dialing(
void *pvt,
enum analog_sub sub)
2964 index = analogsub_to_dahdisub(sub);
2966 if (ioctl(p->
subs[index].dfd, DAHDI_DIALING, &x)) {
2967 ast_debug(1,
"DAHDI_DIALING ioctl failed!\n");
2974 static int my_on_hook(
void *pvt)
2980 #if defined(HAVE_PRI)
2981 static void my_pri_fixup_chans(
void *chan_old,
void *chan_new)
2987 old_chan->
owner = NULL;
2988 if (new_chan->
owner) {
2989 ast_channel_tech_pvt_set(new_chan->
owner, new_chan);
2995 new_chan->
dsp = old_chan->
dsp;
2997 old_chan->
dsp = NULL;
3009 new_chan->
law = old_chan->
law;
3010 strcpy(new_chan->dialstring, old_chan->dialstring);
3014 #if defined(HAVE_PRI)
3015 static int sig_pri_tone_to_dahditone(
enum sig_pri_tone tone)
3018 case SIG_PRI_TONE_RINGTONE:
3019 return DAHDI_TONE_RINGTONE;
3020 case SIG_PRI_TONE_STUTTER:
3021 return DAHDI_TONE_STUTTER;
3022 case SIG_PRI_TONE_CONGESTION:
3023 return DAHDI_TONE_CONGESTION;
3024 case SIG_PRI_TONE_DIALTONE:
3025 return DAHDI_TONE_DIALTONE;
3026 case SIG_PRI_TONE_DIALRECALL:
3027 return DAHDI_TONE_DIALRECALL;
3028 case SIG_PRI_TONE_INFO:
3029 return DAHDI_TONE_INFO;
3030 case SIG_PRI_TONE_BUSY:
3031 return DAHDI_TONE_BUSY;
3038 #if defined(HAVE_PRI)
3039 static void my_handle_dchan_exception(
struct sig_pri_span *pri,
int index)
3043 ioctl(pri->
fds[index], DAHDI_GETEVENT, &x);
3045 case DAHDI_EVENT_NONE:
3047 case DAHDI_EVENT_ALARM:
3048 case DAHDI_EVENT_NOALARM:
3054 ast_log(LOG_NOTICE,
"Got DAHDI event: %s (%d) on D-channel of span %d\n",
3055 event2str(x), x, pri->
span);
3060 case DAHDI_EVENT_ALARM:
3061 pri_event_alarm(pri, index, 0);
3063 case DAHDI_EVENT_NOALARM:
3064 pri_event_noalarm(pri, index, 0);
3066 case DAHDI_EVENT_REMOVED:
3075 #if defined(HAVE_PRI)
3076 static int my_pri_play_tone(
void *pvt,
enum sig_pri_tone tone)
3080 return tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
3084 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3093 static void my_set_callerid(
void *pvt,
const struct ast_party_caller *caller)
3108 if (caller->
id.
tag) {
3118 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3127 static void my_set_dnid(
void *pvt,
const char *
dnid)
3135 #if defined(HAVE_PRI)
3144 static void my_set_rdnis(
void *pvt,
const char *
rdnis)
3152 #if defined(HAVE_PRI)
3179 static void my_pri_make_cc_dialstring(
void *priv,
char *buf,
size_t buf_size)
3200 snprintf(buf, buf_size,
"%s/i%d-", args.tech, pvt->pri->span);
3203 if (isdigit(args.group[0]) || args.group[0] ==
'i' || strchr(args.group,
'!')) {
3210 snprintf(buf, buf_size,
"%s/i%d-%s", args.tech, pvt->pri->span, args.group);
3214 #if defined(HAVE_PRI)
3224 static void dahdi_pri_update_span_devstate(
struct sig_pri_span *pri)
3227 unsigned num_b_chans;
3236 for (idx = pri->
numchans; idx--;) {
3243 if (!pri->
pvts[idx]->inalarm) {
3260 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
3264 }
else if (!in_use) {
3266 }
else if (!pri->user_busy_threshold) {
3272 if (pri->threshold_devstate != new_state) {
3273 pri->threshold_devstate = new_state;
3280 #if defined(HAVE_PRI)
3286 static void my_module_ref(
void)
3292 #if defined(HAVE_PRI)
3298 static void my_module_unref(
void)
3304 #if defined(HAVE_PRI)
3305 #if defined(HAVE_PRI_CALL_WAITING)
3306 static void my_pri_init_config(
void *priv,
struct sig_pri_span *pri);
3308 static int dahdi_new_pri_nobch_channel(
struct sig_pri_span *pri);
3312 .handle_dchan_exception = my_handle_dchan_exception,
3313 .play_tone = my_pri_play_tone,
3314 .set_echocanceller = my_set_echocanceller,
3315 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3316 .lock_private = my_lock_private,
3317 .unlock_private = my_unlock_private,
3318 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3319 .new_ast_channel = my_new_pri_ast_channel,
3320 .fixup_chans = my_pri_fixup_chans,
3321 .set_alarm = my_set_alarm,
3322 .set_dialing = my_set_dialing,
3323 .set_outgoing = my_set_outgoing,
3324 .set_digital = my_set_digital,
3325 .set_callerid = my_set_callerid,
3326 .set_dnid = my_set_dnid,
3327 .set_rdnis = my_set_rdnis,
3328 .new_nobch_intf = dahdi_new_pri_nobch_channel,
3329 #if defined(HAVE_PRI_CALL_WAITING)
3330 .init_config = my_pri_init_config,
3332 .get_orig_dialstring = my_get_orig_dialstring,
3333 .make_cc_dialstring = my_pri_make_cc_dialstring,
3334 .update_span_devstate = dahdi_pri_update_span_devstate,
3335 .module_ref = my_module_ref,
3336 .module_unref = my_module_unref,
3337 .dial_digits = my_pri_dial_digits,
3338 .open_media = my_pri_ss7_open_media,
3339 .ami_channel_event = my_ami_channel_event,
3344 #if defined(HAVE_SS7)
3353 static void my_handle_link_exception(
struct sig_ss7_linkset *linkset,
int which)
3357 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3358 ast_log(LOG_ERROR,
"SS7: Error in exception retrieval on span %d/%d!\n",
3359 linkset->
span, which);
3363 case DAHDI_EVENT_NONE:
3365 case DAHDI_EVENT_ALARM:
3366 ast_log(LOG_ERROR,
"SS7 got event: %s(%d) on span %d/%d\n",
3367 event2str(event), event, linkset->
span, which);
3368 sig_ss7_link_alarm(linkset, which);
3370 case DAHDI_EVENT_NOALARM:
3371 ast_log(LOG_ERROR,
"SS7 got event: %s(%d) on span %d/%d\n",
3372 event2str(event), event, linkset->
span, which);
3373 sig_ss7_link_noalarm(linkset, which);
3376 ast_log(LOG_NOTICE,
"SS7 got event: %s(%d) on span %d/%d\n",
3377 event2str(event), event, linkset->
span, which);
3383 #if defined(HAVE_SS7)
3384 static void my_ss7_set_loopback(
void *pvt,
int enable)
3388 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3389 ast_log(LOG_WARNING,
"Unable to set loopback on channel %d: %s\n", p->
channel,
3395 #if defined(HAVE_SS7)
3414 for (idx = 0; idx < NUM_SPANS; ++idx) {
3415 if (linksets[idx].ss7.ss7 == ss7) {
3416 return &linksets[idx].ss7;
3423 #if defined(HAVE_SS7)
3439 static struct ast_channel *my_new_ss7_ast_channel(
void *pvt,
int state,
enum sig_ss7_law law,
char *exten,
const struct ast_assigned_ids *assignedids,
const struct ast_channel *requestor)
3444 ast_callid callid = 0;
3449 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3450 ast_log(LOG_WARNING,
"Unable to set audio mode on channel %d to %d: %s\n",
3451 p->
channel, audio, strerror(errno));
3453 if (law != SIG_SS7_DEFLAW) {
3455 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3462 case SIG_SS7_DEFLAW:
3466 newlaw = DAHDI_LAW_ALAW;
3469 newlaw = DAHDI_LAW_MULAW;
3472 return dahdi_new_callid_clean(p, state, 0,
SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3476 #if defined(HAVE_SS7)
3477 static int sig_ss7_tone_to_dahditone(
enum sig_ss7_tone tone)
3480 case SIG_SS7_TONE_RINGTONE:
3481 return DAHDI_TONE_RINGTONE;
3482 case SIG_SS7_TONE_STUTTER:
3483 return DAHDI_TONE_STUTTER;
3484 case SIG_SS7_TONE_CONGESTION:
3485 return DAHDI_TONE_CONGESTION;
3486 case SIG_SS7_TONE_DIALTONE:
3487 return DAHDI_TONE_DIALTONE;
3488 case SIG_SS7_TONE_DIALRECALL:
3489 return DAHDI_TONE_DIALRECALL;
3490 case SIG_SS7_TONE_INFO:
3491 return DAHDI_TONE_INFO;
3492 case SIG_SS7_TONE_BUSY:
3493 return DAHDI_TONE_BUSY;
3500 #if defined(HAVE_SS7)
3501 static int my_ss7_play_tone(
void *pvt,
enum sig_ss7_tone tone)
3505 return tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3509 #if defined(HAVE_SS7)
3512 .lock_private = my_lock_private,
3513 .unlock_private = my_unlock_private,
3514 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3516 .set_echocanceller = my_set_echocanceller,
3517 .set_loopback = my_ss7_set_loopback,
3519 .new_ast_channel = my_new_ss7_ast_channel,
3520 .play_tone = my_ss7_play_tone,
3522 .handle_link_exception = my_handle_link_exception,
3523 .set_alarm = my_set_alarm,
3524 .set_dialing = my_set_dialing,
3525 .set_outgoing = my_set_outgoing,
3526 .set_digital = my_set_digital,
3527 .set_inservice = my_set_inservice,
3528 .set_locallyblocked = my_set_locallyblocked,
3529 .set_remotelyblocked = my_set_remotelyblocked,
3530 .set_callerid = my_set_callerid,
3531 .set_dnid = my_set_dnid,
3532 .open_media = my_pri_ss7_open_media,
3533 .find_linkset = my_ss7_find_linkset,
3557 if (ast_strlen_zero(mailbox)) {
3568 static void my_handle_notify_message(
struct ast_channel *chan,
void *pvt,
int cid_flags,
int neon_mwievent)
3575 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3576 ast_log(LOG_NOTICE,
"MWI: Channel %d message waiting, mailbox %s\n", p->
channel, p->
mailbox);
3578 }
else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3579 ast_log(LOG_NOTICE,
"MWI: Channel %d no message waiting, mailbox %s\n", p->
channel, p->
mailbox);
3590 static int my_have_progressdetect(
void *pvt)
3595 && CANPROGRESSDETECT(p) && p->
dsp && p->
outgoing) {
3603 #define gen_pvt_field_callback(type, field) \
3604 static type my_get_##field(void *pvt) \
3606 struct dahdi_pvt *p = pvt; \
3614 #undef gen_pvt_field_callback
3618 .play_tone = my_play_tone,
3619 .get_event = my_get_event,
3620 .wait_event = my_wait_event,
3621 .is_off_hook = my_is_off_hook,
3622 .set_echocanceller = my_set_echocanceller,
3625 .off_hook = my_off_hook,
3626 .dial_digits = my_dial_digits,
3627 .train_echocanceller = my_train_echocanceller,
3628 .on_hook = my_on_hook,
3629 .is_dialing = my_is_dialing,
3630 .allocate_sub = my_allocate_sub,
3631 .unallocate_sub = my_unallocate_sub,
3632 .swap_subs = my_swap_subchannels,
3633 .has_voicemail = my_has_voicemail,
3634 .check_for_conference = my_check_for_conference,
3635 .conf_add = my_conf_add,
3636 .conf_del = my_conf_del,
3637 .complete_conference_update = my_complete_conference_update,
3639 .all_subchannels_hungup = my_all_subchannels_hungup,
3640 .lock_private = my_lock_private,
3641 .unlock_private = my_unlock_private,
3642 .deadlock_avoidance_private = my_deadlock_avoidance_private,
3643 .handle_dtmf = my_handle_dtmf,
3645 .new_ast_channel = my_new_analog_ast_channel,
3646 .dsp_set_digitmode = my_dsp_set_digitmode,
3647 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3648 .send_callerid = my_send_callerid,
3649 .callwait = my_callwait,
3650 .stop_callwait = my_stop_callwait,
3651 .get_callerid = my_get_callerid,
3652 .start_cid_detect = my_start_cid_detect,
3653 .stop_cid_detect = my_stop_cid_detect,
3654 .handle_notify_message = my_handle_notify_message,
3655 .increase_ss_count = my_increase_ss_count,
3656 .decrease_ss_count = my_decrease_ss_count,
3657 .distinctive_ring = my_distinctive_ring,
3658 .set_linear_mode = my_set_linear_mode,
3659 .set_inthreeway = my_set_inthreeway,
3660 .get_and_handle_alarms = my_get_and_handle_alarms,
3661 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3662 .get_sub_fd = my_get_sub_fd,
3663 .set_cadence = my_set_cadence,
3664 .set_alarm = my_set_alarm,
3665 .set_dialing = my_set_dialing,
3666 .set_outgoing = my_set_outgoing,
3667 .set_ringtimeout = my_set_ringtimeout,
3668 .set_waitingfordt = my_set_waitingfordt,
3669 .check_waitingfordt = my_check_waitingfordt,
3670 .set_confirmanswer = my_set_confirmanswer,
3671 .check_confirmanswer = my_check_confirmanswer,
3672 .set_callwaiting = my_set_callwaiting,
3673 .cancel_cidspill = my_cancel_cidspill,
3674 .confmute = my_confmute,
3675 .set_pulsedial = my_set_pulsedial,
3676 .set_new_owner = my_set_new_owner,
3677 .get_orig_dialstring = my_get_orig_dialstring,
3678 .set_needringing = my_set_needringing,
3679 .set_polarity = my_set_polarity,
3680 .start_polarityswitch = my_start_polarityswitch,
3681 .answer_polarityswitch = my_answer_polarityswitch,
3682 .hangup_polarityswitch = my_hangup_polarityswitch,
3683 .have_progressdetect = my_have_progressdetect,
3684 .get_firstdigit_timeout = my_get_firstdigit_timeout,
3685 .get_matchdigit_timeout = my_get_matchdigit_timeout,
3686 .get_interdigit_timeout = my_get_interdigit_timeout,
3692 int _dahdi_get_index(
struct ast_channel *ast,
struct dahdi_pvt *p,
int nullok,
const char *fname,
unsigned long line)
3704 ast_log(LOG_WARNING,
3705 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3706 ast ? ast_channel_name(ast) :
"", p->
channel, fname, line);
3724 static void dahdi_lock_sub_owner(
struct dahdi_pvt *pvt,
int sub_idx)
3727 if (!pvt->
subs[sub_idx].owner) {
3731 if (!ast_channel_trylock(pvt->
subs[sub_idx].owner)) {
3736 DEADLOCK_AVOIDANCE(&pvt->
lock);
3740 static void wakeup_sub(
struct dahdi_pvt *p,
int a)
3742 dahdi_lock_sub_owner(p, a);
3743 if (p->
subs[a].owner) {
3745 ast_channel_unlock(p->
subs[a].owner);
3753 if (ast_channel_trylock(p->
owner)) {
3754 DEADLOCK_AVOIDANCE(&p->
lock);
3757 ast_channel_unlock(p->
owner);
3765 static void publish_channel_alarm_clear(
int channel)
3774 ast_log(LOG_NOTICE,
"Alarm cleared on channel DAHDI/%d\n", channel);
3783 static void publish_span_alarm_clear(
int span)
3787 ast_log(LOG_NOTICE,
"Alarm cleared on span %d\n", span);
3796 static void handle_clear_alarms(
struct dahdi_pvt *p)
3798 #if defined(HAVE_PRI)
3804 if (report_alarms & REPORT_CHANNEL_ALARMS) {
3805 publish_channel_alarm_clear(p->
channel);
3808 publish_span_alarm_clear(p->
span);
3813 static void mfcr2_queue_for_destruction(
const struct dahdi_pvt *p)
3815 const struct dahdi_mfcr2 *r2link = p->mfcr2;
3816 struct r2link_entry *cur;
3819 if (r2link == &cur->mfcr2) {
3829 static int dahdi_r2_answer(
struct dahdi_pvt *p)
3835 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3837 int wants_double_answer =
ast_true(double_answer) ? 1 : 0;
3838 if (!double_answer) {
3841 res = openr2_chan_answer_call(p->r2chan);
3842 }
else if (wants_double_answer) {
3843 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3845 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3848 res = openr2_chan_answer_call(p->r2chan);
3856 static openr2_calling_party_category_t dahdi_r2_get_channel_category(
struct ast_channel *c)
3858 openr2_calling_party_category_t cat;
3860 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3861 if (ast_strlen_zero(catstr)) {
3862 ast_debug(1,
"No MFC/R2 category specified for chan %s, using default %s\n",
3863 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3864 return p->mfcr2_category;
3866 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3867 ast_log(LOG_WARNING,
"Invalid category specified '%s' for chan %s, using default %s\n",
3868 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3869 return p->mfcr2_category;
3871 ast_debug(1,
"Using category %s\n", catstr);
3875 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3877 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3878 ast_mutex_lock(&p->
lock);
3880 ast_mutex_unlock(&p->
lock);
3886 ast_log(LOG_ERROR,
"Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3896 p->mfcr2_ani_index =
'\0';
3897 p->mfcr2_dnis_index =
'\0';
3898 p->mfcr2_dnis_matched = 0;
3899 p->mfcr2_answer_pending = 0;
3900 p->mfcr2_call_accepted = 0;
3901 ast_mutex_unlock(&p->
lock);
3902 ast_verbose(
"New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3905 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan,
int alarm)
3908 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3909 ast_mutex_lock(&p->
lock);
3913 if (res == DAHDI_ALARM_NOTOPEN) {
3914 mfcr2_queue_for_destruction(p);
3916 handle_alarms(p, res);
3918 handle_clear_alarms(p);
3920 ast_mutex_unlock(&p->
lock);
3923 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan,
int errorcode)
3925 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3927 ast_log(LOG_ERROR,
"OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3928 ast_mutex_lock(&p->
lock);
3930 if (errorcode == ENODEV) {
3931 struct dahdi_mfcr2 *r2link = p->mfcr2;
3937 ast_mutex_unlock(&p->
lock);
3940 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3942 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3943 ast_log(LOG_ERROR,
"MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3945 ast_channel_hangupcause_set(p->
owner, AST_CAUSE_PROTOCOL_ERROR);
3948 ast_mutex_lock(&p->
lock);
3950 ast_mutex_unlock(&p->
lock);
3953 static void dahdi_r2_disconnect_call(
struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3955 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3956 ast_log(LOG_NOTICE,
"Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3957 p->
channel, openr2_proto_get_disconnect_string(cause));
3959 openr2_chan_set_idle(p->r2chan);
3960 ast_mutex_lock(&p->
lock);
3962 ast_mutex_unlock(&p->
lock);
3966 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan,
const char *ani,
const char *dnis, openr2_calling_party_category_t category)
3970 ast_callid callid = 0;
3972 ast_verbose(
"MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3973 openr2_chan_get_number(r2chan), ani ? ani :
"(restricted)", dnis,
3974 openr2_proto_get_category_string(category));
3975 p = openr2_chan_get_client_data(r2chan);
3977 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3978 ast_log(LOG_NOTICE,
"Rejecting MFC/R2 collect call\n");
3979 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3980 goto dahdi_r2_on_call_offered_cleanup;
3982 ast_mutex_lock(&p->
lock);
3983 p->mfcr2_recvd_category = category;
3986 ast_debug(1,
"No CID allowed in configuration, CID is being cleared!\n");
3991 if (p->
immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3992 ast_debug(1,
"Setting exten => s because of immediate or 0 DNIS configured\n");
3996 ast_mutex_unlock(&p->
lock);
3998 ast_log(LOG_NOTICE,
"MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
4000 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
4001 goto dahdi_r2_on_call_offered_cleanup;
4003 if (!p->mfcr2_accept_on_offer) {
4010 goto dahdi_r2_on_call_offered_cleanup;
4012 ast_log(LOG_WARNING,
"Unable to create PBX channel in DAHDI channel %d\n", p->
channel);
4013 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4014 }
else if (p->mfcr2_charge_calls) {
4015 ast_debug(1,
"Accepting MFC/R2 call with charge on chan %d\n", p->
channel);
4016 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
4018 ast_debug(1,
"Accepting MFC/R2 call with no charge on chan %d\n", p->
channel);
4019 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
4022 dahdi_r2_on_call_offered_cleanup:
4026 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
4028 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4029 ast_verbose(
"MFC/R2 call end on channel %d\n", p->
channel);
4030 ast_mutex_lock(&p->
lock);
4032 ast_mutex_unlock(&p->
lock);
4035 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
4039 ast_callid callid = 0;
4041 p = openr2_chan_get_client_data(r2chan);
4043 p->mfcr2_call_accepted = 1;
4045 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
4046 ast_verbose(
"MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
4051 if (!p->mfcr2_accept_on_offer) {
4052 openr2_chan_disable_read(r2chan);
4053 if (p->mfcr2_answer_pending) {
4054 ast_debug(1,
"Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
4057 goto dahdi_r2_on_call_accepted_cleanup;
4063 openr2_chan_disable_read(r2chan);
4064 goto dahdi_r2_on_call_accepted_cleanup;
4066 ast_log(LOG_WARNING,
"Unable to create PBX channel in DAHDI channel %d\n", p->
channel);
4068 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
4069 goto dahdi_r2_on_call_accepted_cleanup;
4072 ast_verbose(
"MFC/R2 call has been accepted on forward channel %d\n", p->
channel);
4076 openr2_chan_disable_read(r2chan);
4078 dahdi_r2_on_call_accepted_cleanup:
4082 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
4084 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4085 ast_verbose(
"MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
4089 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan,
const unsigned char *buf,
int buflen)
4094 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
4097 case OR2_CAUSE_BUSY_NUMBER:
4098 return AST_CAUSE_BUSY;
4099 case OR2_CAUSE_NETWORK_CONGESTION:
4100 return AST_CAUSE_CONGESTION;
4101 case OR2_CAUSE_OUT_OF_ORDER:
4102 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
4103 case OR2_CAUSE_UNALLOCATED_NUMBER:
4104 return AST_CAUSE_UNREGISTERED;
4105 case OR2_CAUSE_NO_ANSWER:
4106 return AST_CAUSE_NO_ANSWER;
4107 case OR2_CAUSE_NORMAL_CLEARING:
4108 return AST_CAUSE_NORMAL_CLEARING;
4109 case OR2_CAUSE_UNSPECIFIED:
4111 return AST_CAUSE_NOTDEFINED;
4115 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
4117 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4120 int datalen =
sizeof(*cause_code);
4122 ast_verbose(
"MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
4123 ast_mutex_lock(&p->
lock);
4125 ast_mutex_unlock(&p->
lock);
4127 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
4131 snprintf(cause_str,
sizeof(cause_str),
"R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
4132 datalen += strlen(cause_str);
4134 memset(cause_code, 0, datalen);
4135 cause_code->
ast_cause = dahdi_r2_cause_to_ast_cause(cause);
4146 ast_mutex_unlock(&p->
lock);
4147 }
else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
4150 case OR2_CAUSE_BUSY_NUMBER:
4153 case OR2_CAUSE_NETWORK_CONGESTION:
4154 case OR2_CAUSE_OUT_OF_ORDER:
4155 case OR2_CAUSE_UNALLOCATED_NUMBER:
4156 case OR2_CAUSE_NO_ANSWER:
4157 case OR2_CAUSE_UNSPECIFIED:
4158 case OR2_CAUSE_NORMAL_CLEARING:
4164 ast_mutex_unlock(&p->
lock);
4166 ast_mutex_unlock(&p->
lock);
4173 static void dahdi_r2_write_log(openr2_log_level_t level,
char *logmessage)
4176 case OR2_LOG_NOTICE:
4177 ast_verbose(
"%s", logmessage);
4179 case OR2_LOG_WARNING:
4180 ast_log(LOG_WARNING,
"%s", logmessage);
4183 ast_log(LOG_ERROR,
"%s", logmessage);
4185 case OR2_LOG_STACK_TRACE:
4186 case OR2_LOG_MF_TRACE:
4187 case OR2_LOG_CAS_TRACE:
4189 case OR2_LOG_EX_DEBUG:
4193 ast_log(LOG_WARNING,
"We should handle logging level %d here.\n", level);
4199 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
4201 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4202 ast_mutex_lock(&p->
lock);
4204 ast_mutex_unlock(&p->
lock);
4205 ast_log(LOG_NOTICE,
"Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
4208 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
4210 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4211 ast_mutex_lock(&p->
lock);
4213 ast_mutex_unlock(&p->
lock);
4214 ast_log(LOG_NOTICE,
"Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
4217 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level,
const char *fmt, va_list ap)
4218 __attribute__((format (printf, 3, 0)));
4219 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level,
const char *fmt, va_list ap)
4221 #define CONTEXT_TAG "Context - "
4223 char completemsg[
sizeof(logmsg) * 2];
4224 vsnprintf(logmsg,
sizeof(logmsg), fmt, ap);
4225 snprintf(completemsg,
sizeof(completemsg), CONTEXT_TAG
"%s", logmsg);
4226 dahdi_r2_write_log(level, completemsg);
4230 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level,
const char *fmt, va_list ap)
4231 __attribute__((format (printf, 3, 0)));
4232 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level,
const char *fmt, va_list ap)
4234 #define CHAN_TAG "Chan "
4236 char completemsg[
sizeof(logmsg) * 2];
4237 vsnprintf(logmsg,
sizeof(logmsg), fmt, ap);
4238 snprintf(completemsg,
sizeof(completemsg), CHAN_TAG
"%d - %s", openr2_chan_get_number(r2chan), logmsg);
4239 dahdi_r2_write_log(level, completemsg);
4243 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan,
char digit)
4245 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4250 p->
exten[p->mfcr2_dnis_index] = digit;
4251 p->
rdnis[p->mfcr2_dnis_index] = digit;
4252 p->mfcr2_dnis_index++;
4253 p->
exten[p->mfcr2_dnis_index] = 0;
4254 p->
rdnis[p->mfcr2_dnis_index] = 0;
4256 if ((p->mfcr2_dnis_matched ||
4265 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan,
char digit)
4267 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4268 p->
cid_num[p->mfcr2_ani_index] = digit;
4269 p->
cid_name[p->mfcr2_ani_index] = digit;
4270 p->mfcr2_ani_index++;
4271 p->
cid_num[p->mfcr2_ani_index] = 0;
4272 p->
cid_name[p->mfcr2_ani_index] = 0;
4275 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4277 ast_verbose(
"MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4280 static openr2_event_interface_t dahdi_r2_event_iface = {
4281 .on_call_init = dahdi_r2_on_call_init,
4282 .on_call_offered = dahdi_r2_on_call_offered,
4283 .on_call_accepted = dahdi_r2_on_call_accepted,
4284 .on_call_answered = dahdi_r2_on_call_answered,
4285 .on_call_disconnect = dahdi_r2_on_call_disconnect,
4286 .on_call_end = dahdi_r2_on_call_end,
4287 .on_call_read = dahdi_r2_on_call_read,
4288 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4289 .on_os_error = dahdi_r2_on_os_error,
4290 .on_protocol_error = dahdi_r2_on_protocol_error,
4291 .on_line_blocked = dahdi_r2_on_line_blocked,
4292 .on_line_idle = dahdi_r2_on_line_idle,
4294 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4295 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4296 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4298 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4301 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4303 return AST_ALAW(sample);
4306 static inline uint8_t dahdi_r2_linear_to_alaw(
int sample)
4308 return AST_LIN2A(sample);
4311 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4312 dahdi_r2_alaw_to_linear,
4313 dahdi_r2_linear_to_alaw
4318 static void swap_subs(
struct dahdi_pvt *p,
int a,
int b)
4324 ast_debug(1,
"Swapping %d and %d\n", a, b);
4326 tchan = p->
subs[a].chan;
4327 towner = p->
subs[a].owner;
4328 tinthreeway = p->
subs[a].inthreeway;
4331 p->
subs[a].owner = p->
subs[b].owner;
4332 p->
subs[a].inthreeway = p->
subs[b].inthreeway;
4334 p->
subs[b].chan = tchan;
4335 p->
subs[b].owner = towner;
4336 p->
subs[b].inthreeway = tinthreeway;
4338 if (p->
subs[a].owner)
4340 if (p->
subs[b].owner)
4346 static int dahdi_open(
char *fn)
4354 for (x = 0; x < strlen(fn); x++) {
4355 if (!isdigit(fn[x])) {
4363 ast_log(LOG_WARNING,
"Invalid channel number '%s'\n", fn);
4366 fn =
"/dev/dahdi/channel";
4368 fd = open(fn, O_RDWR | O_NONBLOCK);
4370 ast_log(LOG_WARNING,
"Unable to open '%s': %s\n", fn, strerror(errno));
4374 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4378 ast_log(LOG_WARNING,
"Unable to specify channel %d: %s\n", chan, strerror(errno));
4383 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4384 ast_log(LOG_WARNING,
"Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4393 static void dahdi_close(
int fd)
4399 static void dahdi_close_sub(
struct dahdi_pvt *chan_pvt,
int sub_num)
4401 dahdi_close(chan_pvt->
subs[sub_num].dfd);
4402 chan_pvt->
subs[sub_num].dfd = -1;
4405 #if defined(HAVE_PRI)
4406 static void dahdi_close_pri_fd(
struct dahdi_pri *pri,
int fd_num)
4408 dahdi_close(pri->pri.
fds[fd_num]);
4409 pri->pri.
fds[fd_num] = -1;
4413 #if defined(HAVE_SS7)
4414 static void dahdi_close_ss7_fd(
struct dahdi_ss7 *ss7,
int fd_num)
4416 dahdi_close(ss7->ss7.fds[fd_num]);
4417 ss7->ss7.fds[fd_num] = -1;
4421 static int dahdi_setlinear(
int dfd,
int linear)
4423 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4427 static int alloc_sub(
struct dahdi_pvt *p,
int x)
4429 struct dahdi_bufferinfo bi;
4431 if (p->
subs[x].dfd >= 0) {
4432 ast_log(LOG_WARNING,
"%s subchannel of %d already in use\n", subnames[x], p->
channel);
4436 p->
subs[x].dfd = dahdi_open(
"/dev/dahdi/pseudo");
4437 if (p->
subs[x].dfd <= -1) {
4438 ast_log(LOG_WARNING,
"Unable to open pseudo channel: %s\n", strerror(errno));
4442 res = ioctl(p->
subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4447 res = ioctl(p->
subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4449 ast_log(LOG_WARNING,
"Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4452 ast_log(LOG_WARNING,
"Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4454 if (ioctl(p->
subs[x].dfd, DAHDI_CHANNO, &p->
subs[x].chan) == 1) {
4455 ast_log(LOG_WARNING,
"Unable to get channel number for pseudo channel on FD %d: %s\n", p->
subs[x].dfd, strerror(errno));
4456 dahdi_close_sub(p, x);
4457 p->
subs[x].dfd = -1;
4460 ast_debug(1,
"Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->
subs[x].dfd, p->
subs[x].chan);
4464 static int unalloc_sub(
struct dahdi_pvt *p,
int x)
4467 ast_log(LOG_WARNING,
"Trying to unalloc the real channel %d?!?\n", p->
channel);
4471 dahdi_close_sub(p, x);
4472 p->
subs[x].linear = 0;
4473 p->
subs[x].chan = 0;
4474 p->
subs[x].owner = NULL;
4475 p->
subs[x].inthreeway = 0;
4477 memset(&p->
subs[x].curconf, 0,
sizeof(p->
subs[x].curconf));
4481 static int digit_to_dtmfindex(
char digit)
4484 return DAHDI_TONE_DTMF_BASE + (digit -
'0');
4485 else if (digit >=
'A' && digit <=
'D')
4486 return DAHDI_TONE_DTMF_A + (digit -
'A');
4487 else if (digit >=
'a' && digit <=
'd')
4488 return DAHDI_TONE_DTMF_A + (digit -
'a');
4489 else if (digit ==
'*')
4490 return DAHDI_TONE_DTMF_s;
4491 else if (digit ==
'#')
4492 return DAHDI_TONE_DTMF_p;
4497 static int dahdi_digit_begin(
struct ast_channel *chan,
char digit)
4504 pvt = ast_channel_tech_pvt(chan);
4506 ast_mutex_lock(&pvt->
lock);
4508 idx = dahdi_get_index(chan, pvt, 0);
4515 case SIG_PRI_LIB_HANDLE_CASES:
4516 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4524 dtmf = digit_to_dtmfindex(digit);
4531 char dial_str[] = {
'T', digit,
'\0' };
4533 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4542 dtmf = DAHDI_FLUSH_WRITE;
4543 res = ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4545 ast_log(LOG_WARNING,
"Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4546 pvt->
channel, strerror(errno));
4549 ast_debug(1,
"Channel %s started VLDTMF digit '%c'\n",
4550 ast_channel_name(chan), digit);
4554 ast_mutex_unlock(&pvt->
lock);
4559 static int dahdi_digit_end(
struct ast_channel *chan,
char digit,
unsigned int duration)
4566 pvt = ast_channel_tech_pvt(chan);
4568 ast_mutex_lock(&pvt->
lock);
4570 idx = dahdi_get_index(chan, pvt, 0);
4577 if (dahdi_sig_pri_lib_handles(pvt->
sig) && !pvt->
begindigit) {
4584 ast_debug(1,
"Channel %s ending VLDTMF digit '%c'\n",
4585 ast_channel_name(chan), digit);
4586 res = ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4592 ast_mutex_unlock(&pvt->
lock);
4597 static const char *
const events[] = {
4610 "Hook Transition Complete",
4615 "Polarity Reversal",
4623 { DAHDI_ALARM_RED,
"Red Alarm" },
4624 { DAHDI_ALARM_YELLOW,
"Yellow Alarm" },
4625 { DAHDI_ALARM_BLUE,
"Blue Alarm" },
4626 { DAHDI_ALARM_RECOVER,
"Recovering" },
4627 { DAHDI_ALARM_LOOPBACK,
"Loopback" },
4628 { DAHDI_ALARM_NOTOPEN,
"Not Open" },
4629 { DAHDI_ALARM_NONE,
"None" },
4632 static char *alarm2str(
int alm)
4635 for (x = 0; x < ARRAY_LEN(alarms); x++) {
4636 if (alarms[x].alarm & alm)
4637 return alarms[x].name;
4639 return alm ?
"Unknown Alarm" :
"No Alarm";
4642 static const char *event2str(
int event)
4644 static char buf[256];
4645 if ((event > -1) && (event < (ARRAY_LEN(events))) )
4646 return events[event];
4647 sprintf(buf,
"Event %d", event);
4651 static char *dahdi_sig2str(
int sig)
4653 static char buf[256];
4656 return "E & M Immediate";
4658 return "E & M Wink";
4662 return "Feature Group D (DTMF)";
4664 return "Feature Group D (MF)";
4665 case SIG_FEATDMF_TA:
4666 return "Feature Group D (MF) Tandem Access";
4668 return "Feature Group B (MF)";
4672 return "FGC/CAMA (Dialpulse)";
4673 case SIG_FGC_CAMAMF:
4674 return "FGC/CAMA (MF)";
4676 return "FXS Loopstart";
4678 return "FXS Groundstart";
4680 return "FXS Kewlstart";
4682 return "FXO Loopstart";
4684 return "FXO Groundstart";
4686 return "FXO Kewlstart";
4690 return "ISDN BRI Point to Point";
4692 return "ISDN BRI Point to MultiPoint";
4698 return "SF (Tone) Immediate";
4700 return "SF (Tone) Wink";
4702 return "SF (Tone) with Feature Group D (DTMF)";
4703 case SIG_SF_FEATDMF:
4704 return "SF (Tone) with Feature Group D (MF)";
4706 return "SF (Tone) with Feature Group B (MF)";
4710 snprintf(buf,
sizeof(buf),
"Unknown signalling %d", sig);
4715 #define sig2str dahdi_sig2str
4721 struct dahdi_confinfo zi;
4723 memset(&zi, 0,
sizeof(zi));
4726 if (slavechannel > 0) {
4728 zi.confmode = DAHDI_CONF_DIGITALMON;
4729 zi.confno = slavechannel;
4733 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4734 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4736 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4739 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4743 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4744 ast_log(LOG_WARNING,
"Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4747 if (slavechannel < 1) {
4751 ast_debug(1,
"Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4758 if ((p->
channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4761 if ((p->
confno > 0) && (p->
confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4768 struct dahdi_confinfo zi;
4775 memset(&zi, 0,
sizeof(zi));
4776 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4777 ast_log(LOG_WARNING,
"Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4780 ast_debug(1,
"Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4781 memcpy(&c->curconf, &zi,
sizeof(c->curconf));
4793 for (x = 0; x < 3; x++) {
4796 if ((p->
subs[x].dfd > -1) && p->
subs[x].inthreeway)
4801 if (useslavenative) {
4802 for (x = 0; x < MAX_SLAVES; x++) {
4820 else if (slave->
law != p->
law) {
4826 return useslavenative;
4829 static int reset_conf(
struct dahdi_pvt *p)
4834 struct dahdi_confinfo zi;
4836 memset(&zi, 0,
sizeof(zi));
4838 ast_log(LOG_WARNING,
"Failed to reset conferencing on channel %d: %s\n", p->
channel, strerror(errno));
4843 void dahdi_conf_update(
struct dahdi_pvt *p)
4850 useslavenative = isslavenative(p, &slave);
4852 for (x = 0; x < 3; x++) {
4854 if ((p->
subs[x].dfd > -1) && p->
subs[x].inthreeway) {
4855 conf_add(p, &p->
subs[x], x, 0);
4858 conf_del(p, &p->
subs[x], x);
4863 for (x = 0; x < MAX_SLAVES; x++) {
4868 conf_add(p, &p->
slaves[x]->
subs[SUB_REAL], SUB_REAL, 0);
4884 if (isslavenative(p->
master, NULL)) {
4895 ast_debug(1,
"Updated conferencing on %d, with %d conference users\n", p->
channel, needconf);
4898 void dahdi_ec_enable(
struct dahdi_pvt *p)
4904 ast_debug(1,
"Echo cancellation already on\n");
4908 ast_debug(1,
"Echo cancellation isn't required on digital connection\n");
4912 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4914 #if defined(HAVE_PRI)
4915 case SIG_PRI_LIB_HANDLE_CASES:
4916 if (((
struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4925 #if defined(HAVE_SS7)
4931 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4933 ast_log(LOG_WARNING,
4934 "Unable to enable audio mode on channel %d (%s)\n",
4944 ast_log(LOG_WARNING,
"Unable to enable echo cancellation on channel %d (%s)\n", p->
channel, strerror(errno));
4950 ast_debug(1,
"No echo cancellation requested\n");
4953 static void dahdi_train_ec(
struct dahdi_pvt *p)
4960 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4962 ast_log(LOG_WARNING,
"Unable to request echo training on channel %d: %s\n", p->
channel, strerror(errno));
4966 ast_debug(1,
"No echo training requested\n");
4970 void dahdi_ec_disable(
struct dahdi_pvt *p)
4975 struct dahdi_echocanparams ecp = { .tap_length = 0 };
4977 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4980 ast_log(LOG_WARNING,
"Unable to disable echo cancellation on channel %d: %s\n", p->
channel, strerror(errno));
4988 static int set_hwgain(
int fd,
float gain,
int tx_direction)
4990 struct dahdi_hwgain hwgain;
4992 hwgain.newgain = gain * 10.0;
4993 hwgain.tx = tx_direction;
4994 return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4998 static int drc_sample(
int sample,
float drc)
5001 float shallow, steep;
5002 float max = SHRT_MAX;
5004 neg = (sample < 0 ? -1 : 1);
5006 shallow = neg*(max-max/drc)+(
float)sample/drc;
5007 if (fabsf(steep) < fabsf(shallow)) {
5018 static void fill_txgain(
struct dahdi_gains *g,
float gain,
float drc,
int law)
5023 float linear_gain = pow(10.0, gain / 20.0);
5026 case DAHDI_LAW_ALAW:
5027 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5031 k = drc_sample(k, drc);
5033 k = (float)k * linear_gain;
5036 }
else if (k < -32768) {
5039 g->txgain[j] = AST_LIN2A(k);
5045 case DAHDI_LAW_MULAW:
5046 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
5050 k = drc_sample(k, drc);
5052 k = (float)k * linear_gain;
5055 }
else if (k < -32768) {
5058 g->txgain[j] = AST_LIN2MU(k);
5068 static void fill_rxgain(
struct dahdi_gains *g,
float gain,
float drc,
int law)
5072 float linear_gain = pow(10.0, gain / 20.0);
5075 case DAHDI_LAW_ALAW:
5076 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5080 k = drc_sample(k, drc);
5082 k = (float)k * linear_gain;
5085 }
else if (k < -32768) {
5088 g->rxgain[j] = AST_LIN2A(k);
5094 case DAHDI_LAW_MULAW:
5095 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
5099 k = drc_sample(k, drc);
5101 k = (float)k * linear_gain;
5104 }
else if (k < -32768) {
5107 g->rxgain[j] = AST_LIN2MU(k);
5116 static int set_actual_txgain(
int fd,
float gain,
float drc,
int law)
5118 struct dahdi_gains g;
5121 memset(&g, 0,
sizeof(g));
5122 res = ioctl(fd, DAHDI_GETGAINS, &g);
5124 ast_debug(1,
"Failed to read gains: %s\n", strerror(errno));
5128 fill_txgain(&g, gain, drc, law);
5130 return ioctl(fd, DAHDI_SETGAINS, &g);
5133 static int set_actual_rxgain(
int fd,
float gain,
float drc,
int law)
5135 struct dahdi_gains g;
5138 memset(&g, 0,
sizeof(g));
5139 res = ioctl(fd, DAHDI_GETGAINS, &g);
5141 ast_debug(1,
"Failed to read gains: %s\n", strerror(errno));
5145 fill_rxgain(&g, gain, drc, law);
5147 return ioctl(fd, DAHDI_SETGAINS, &g);
5150 static int set_actual_gain(
int fd,
float rxgain,
float txgain,
float rxdrc,
float txdrc,
int law)
5152 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
5155 static int bump_gains(
struct dahdi_pvt *p)
5162 ast_log(LOG_WARNING,
"Unable to bump gain: %s\n", strerror(errno));
5169 static int restore_gains(
struct dahdi_pvt *p)
5175 ast_log(LOG_WARNING,
"Unable to restore gains: %s\n", strerror(errno));
5182 static inline int dahdi_set_hook(
int fd,
int hs)
5187 res = ioctl(fd, DAHDI_HOOK, &x);
5190 if (errno == EINPROGRESS)
5192 ast_log(LOG_WARNING,
"DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
5199 static inline int dahdi_confmute(
struct dahdi_pvt *p,
int muted)
5204 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5206 #if defined(HAVE_PRI)
5207 case SIG_PRI_LIB_HANDLE_CASES:
5208 if (((
struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
5214 #if defined(HAVE_SS7)
5220 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
5222 ast_log(LOG_WARNING,
"Unable to set audio mode on %d: %s\n",
5230 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
5232 ast_log(LOG_WARNING,
"DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->
channel, strerror(errno));
5236 static int save_conference(
struct dahdi_pvt *p)
5238 struct dahdi_confinfo c;
5241 ast_log(LOG_WARNING,
"Can't save conference -- already in use\n");
5247 ast_log(LOG_WARNING,
"Unable to get conference info: %s\n", strerror(errno));
5251 memset(&c, 0,
sizeof(c));
5252 c.confmode = DAHDI_CONF_NORMAL;
5255 ast_log(LOG_WARNING,
"Unable to set conference info: %s\n", strerror(errno));
5258 ast_debug(1,
"Disabled conferencing\n");
5262 static int restore_conference(
struct dahdi_pvt *p)
5269 ast_log(LOG_WARNING,
"Unable to restore conference info: %s\n", strerror(errno));
5272 ast_debug(1,
"Restored conferencing\n");
5277 static int send_cwcidspill(
struct dahdi_pvt *p)
5305 ast_debug(6,
"MWI manual override active on channel %d: pretending that it should be %s\n",
5323 static int send_callerid(
struct dahdi_pvt *p)
5336 if (errno == EAGAIN)
5339 ast_log(LOG_WARNING,
"write failed: %s\n", strerror(errno));
5355 restore_conference(p);
5359 static int dahdi_callwait(
struct ast_channel *ast)
5361 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5365 ast_log(LOG_WARNING,
"Spill already exists?!?\n");
5393 static int dahdi_call(
struct ast_channel *ast,
const char *rdest,
int timeout)
5395 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5405 ast_mutex_lock(&p->
lock);
5415 #if defined(HAVE_PRI)
5416 if (dahdi_sig_pri_lib_handles(p->
sig)) {
5422 subaddr = strchr(p->
exten,
':');
5434 ast_mutex_unlock(&p->
lock);
5438 ast_log(LOG_WARNING,
"dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5439 ast_mutex_unlock(&p->
lock);
5448 ast_mutex_unlock(&p->
lock);
5451 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5454 ast_log(LOG_WARNING,
"Unable to flush input on channel %d: %s\n", p->
channel, strerror(errno));
5457 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
5464 if (dahdi_sig_pri_lib_handles(p->
sig)) {
5466 (p->
law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5467 ast_mutex_unlock(&p->
lock);
5472 #if defined(HAVE_SS7)
5473 if (p->
sig == SIG_SS7) {
5474 res = sig_ss7_call(p->sig_pvt, ast, rdest);
5475 ast_mutex_unlock(&p->
lock);
5483 res = analog_call(p->sig_pvt, ast, rdest, timeout);
5484 ast_mutex_unlock(&p->
lock);
5498 ast_mutex_unlock(&p->
lock);
5504 openr2_calling_party_category_t chancat;
5518 ast_log(LOG_WARNING,
"Number '%s' is shorter than stripmsd (%d)\n", c, p->
stripmsd);
5519 ast_mutex_unlock(&p->
lock);
5523 chancat = dahdi_r2_get_channel_category(ast);
5524 callres = openr2_chan_make_call(p->r2chan, l, (c + p->
stripmsd), chancat);
5525 if (-1 == callres) {
5526 ast_mutex_unlock(&p->
lock);
5527 ast_log(LOG_ERROR,
"unable to make new MFC/R2 call!\n");
5530 p->mfcr2_call_accepted = 0;
5531 p->mfcr2_progress_sent = 0;
5535 ast_mutex_unlock(&p->
lock);
5552 static void dahdi_iflist_insert(
struct dahdi_pvt *pvt)
5559 for (cur = iflist; cur; cur = cur->
next) {
5600 static void dahdi_iflist_extract(
struct dahdi_pvt *pvt)
5605 }
else if (iflist == pvt) {
5613 }
else if (ifend == pvt) {
5624 #if defined(HAVE_PRI)
5677 #if defined(HAVE_PRI)
5715 #if defined(HAVE_PRI)
5723 static void dahdi_unlink_pri_pvt(
struct dahdi_pvt *pvt)
5733 ast_mutex_lock(&pri->
lock);
5734 for (idx = 0; idx < pri->
numchans; ++idx) {
5735 if (pri->
pvts[idx] == pvt->sig_pvt) {
5736 pri->
pvts[idx] = NULL;
5737 ast_mutex_unlock(&pri->
lock);
5741 ast_mutex_unlock(&pri->
lock);
5745 #if defined(HAVE_SS7)
5753 static void dahdi_unlink_ss7_pvt(
struct dahdi_pvt *pvt)
5763 ast_mutex_lock(&ss7->
lock);
5764 for (idx = 0; idx < ss7->numchans; ++idx) {
5765 if (ss7->
pvts[idx] == pvt->sig_pvt) {
5766 ss7->
pvts[idx] = NULL;
5767 ast_mutex_unlock(&ss7->
lock);
5771 ast_mutex_unlock(&ss7->
lock);
5775 #if defined(HAVE_OPENR2)
5782 static void dahdi_unlink_mfcr2_pvt(
struct dahdi_pvt *pvt)
5785 struct dahdi_mfcr2 *mfcr2;
5786 int should_destroy_link = 0;
5788 ast_mutex_lock(&pvt->
lock);
5791 openr2_chan_disable_read(pvt->r2chan);
5795 for (idx = 0; idx < mfcr2->numchans; ++idx) {
5796 if (mfcr2->pvts[idx] == pvt) {
5797 ast_debug(1,
"Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->
channel);
5798 mfcr2->pvts[idx] = NULL;
5799 mfcr2->live_chans--;
5803 if (!mfcr2->live_chans) {
5804 ast_debug(1,
"MFC/R2 link is now empty\n");
5805 should_destroy_link = 1;
5808 ast_mutex_unlock(&pvt->
lock);
5809 if (should_destroy_link) {
5810 ast_debug(1,
"MFC/R2 link is now empty\n");
5811 mfcr2_queue_for_destruction(pvt);
5827 static void destroy_dahdi_pvt(
struct dahdi_pvt *pvt)
5839 #if defined(HAVE_PRI)
5840 dahdi_unlink_pri_pvt(p);
5842 #if defined(HAVE_SS7)
5843 dahdi_unlink_ss7_pvt(p);
5845 #if defined(HAVE_OPENR2)
5846 dahdi_unlink_mfcr2_pvt(p);
5852 dahdi_iflist_extract(p);
5854 #if defined(HAVE_PRI)
5857 dahdi_nobch_extract(p->pri, p);
5864 if (dahdi_analog_lib_handles(p->
sig, 0, 0)) {
5868 #if defined(HAVE_PRI)
5869 case SIG_PRI_LIB_HANDLE_CASES:
5873 #if defined(HAVE_SS7)
5875 sig_ss7_chan_delete(p->sig_pvt);
5899 ast_mutex_destroy(&p->
lock);
5902 ast_channel_tech_pvt_set(p->
owner, NULL);
5907 static void destroy_channel(
struct dahdi_pvt *cur,
int now)
5916 for (i = 0; i < 3; i++) {
5917 if (cur->
subs[i].owner) {
5922 destroy_dahdi_pvt(cur);
5925 static void destroy_all_channels(
void)
5928 #if defined(HAVE_PRI)
5934 while (num_restart_pending) {
5944 #if defined(HAVE_PRI_SERVICE_MESSAGES)
5946 char db_chan_name[20];
5951 snprintf(db_chan_name,
sizeof(db_chan_name),
"%s/%d:%d",
dahdi_db, p->
span, chan);
5953 sscanf(db_answer,
"%1c:%30d", &state, &why);
5962 destroy_dahdi_pvt(p);
5963 ast_verb(3,
"Unregistered channel %d\n", chan);
5966 ast_mutex_unlock(&
iflock);
5968 #if defined(HAVE_PRI)
5970 for (span = 0; span < NUM_SPANS; ++
span) {
5971 if (!pris[span].dchannels[0]) {
5974 pri = &pris[
span].pri;
5975 ast_mutex_lock(&pri->
lock);
5980 destroy_dahdi_pvt(p);
5982 ast_mutex_unlock(&pri->
lock);
5987 #if defined(HAVE_PRI)
5988 static char *dahdi_send_keypad_facility_app =
"DAHDISendKeypadFacility";
5990 static int dahdi_send_keypad_facility_exec(
struct ast_channel *chan,
const char *digits)
5995 if (ast_strlen_zero(digits)) {
5996 ast_debug(1,
"No digit string sent to application!\n");
6000 p = (
struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6003 ast_debug(1,
"Unable to find technology private\n");
6007 pri_send_keypad_facility_exec(p->sig_pvt, digits);
6013 #if defined(HAVE_PRI)
6014 #if defined(HAVE_PRI_PROG_W_CAUSE)
6015 static char *dahdi_send_callrerouting_facility_app =
"DAHDISendCallreroutingFacility";
6017 static int dahdi_send_callrerouting_facility_exec(
struct ast_channel *chan,
const char *data)
6029 if (ast_strlen_zero(data)) {
6030 ast_debug(1,
"No data sent to application!\n");
6034 ast_debug(1,
"Only DAHDI technology accepted!\n");
6037 pvt = (
struct dahdi_pvt *) ast_channel_tech_pvt(chan);
6039 ast_debug(1,
"Unable to find technology private\n");
6043 case SIG_PRI_LIB_HANDLE_CASES:
6046 ast_debug(1,
"callrerouting attempted on non-ISDN channel %s\n",
6047 ast_channel_name(chan));
6054 if (ast_strlen_zero(args.destination)) {
6055 ast_log(LOG_WARNING,
"callrerouting facility requires at least destination number argument\n");
6059 if (ast_strlen_zero(args.original)) {
6060 ast_log(LOG_WARNING,
"Callrerouting Facility without original called number argument\n");
6061 args.original = NULL;
6064 if (ast_strlen_zero(args.reason)) {
6065 ast_log(LOG_NOTICE,
"Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
6069 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt,
ast_channel_state(chan),
6070 args.destination, args.original, args.reason);
6084 #if defined(HAVE_OPENR2)
6085 static const char *
const dahdi_accept_r2_call_app =
"DAHDIAcceptR2Call";
6087 static int dahdi_accept_r2_call_exec(
struct ast_channel *chan,
const char *data)
6090 openr2_call_mode_t accept_mode;
6091 int res, timeout, maxloops;
6099 if (ast_strlen_zero(data)) {
6100 ast_debug(1,
"No data sent to application!\n");
6105 ast_debug(1,
"Only DAHDI technology accepted!\n");
6109 p = (
struct dahdi_pvt *)ast_channel_tech_pvt(chan);
6111 ast_debug(1,
"Unable to find technology private!\n");
6118 if (ast_strlen_zero(args.charge)) {
6119 ast_log(LOG_WARNING,
"DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
6123 ast_mutex_lock(&p->
lock);
6124 if (!p->mfcr2 || !p->mfcr2call) {
6125 ast_mutex_unlock(&p->
lock);
6126 ast_debug(1,
"Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
6130 if (p->mfcr2_call_accepted) {
6131 ast_mutex_unlock(&p->
lock);
6132 ast_debug(1,
"MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
6135 accept_mode =
ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
6136 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
6137 ast_mutex_unlock(&p->
lock);
6138 ast_log(LOG_WARNING,
"Failed to accept MFC/R2 call!\n");
6141 ast_mutex_unlock(&p->
lock);
6147 while (maxloops > 0) {
6154 ast_debug(1,
"ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
6164 ast_debug(1,
"No frame read on channel %s, going out ...\n", ast_channel_name(chan));
6169 ast_debug(1,
"Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
6175 ast_mutex_lock(&p->
lock);
6176 if (p->mfcr2_call_accepted) {
6177 ast_mutex_unlock(&p->
lock);
6178 ast_debug(1,
"Accepted MFC/R2 call!\n");
6181 ast_mutex_unlock(&p->
lock);
6184 ast_log(LOG_WARNING,
"Failed to accept MFC/R2 call!\n");
6189 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(
int cause)
6191 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
6193 case AST_CAUSE_USER_BUSY:
6194 case AST_CAUSE_CALL_REJECTED:
6195 case AST_CAUSE_INTERWORKING:
6196 r2cause = OR2_CAUSE_BUSY_NUMBER;
6199 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
6200 case AST_CAUSE_SWITCH_CONGESTION:
6201 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
6204 case AST_CAUSE_UNALLOCATED:
6205 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
6208 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
6209 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
6210 r2cause = OR2_CAUSE_OUT_OF_ORDER;
6213 case AST_CAUSE_NO_ANSWER:
6214 case AST_CAUSE_NO_USER_RESPONSE:
6215 r2cause = OR2_CAUSE_NO_ANSWER;
6219 r2cause = OR2_CAUSE_NORMAL_CLEARING;
6222 ast_debug(1,
"ast cause %d resulted in openr2 cause %d/%s\n",
6223 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
6232 struct dahdi_bufferinfo bi = {
6240 if ((bpres = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6241 ast_log(LOG_WARNING,
"Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
6256 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6257 struct dahdi_params par;
6259 ast_debug(1,
"dahdi_hangup(%s)\n", ast_channel_name(ast));
6260 if (!ast_channel_tech_pvt(ast)) {
6261 ast_log(LOG_WARNING,
"Asked to hangup channel not connected\n");
6265 ast_mutex_lock(&p->
lock);
6268 if (dahdi_analog_lib_handles(p->
sig, p->
radio, 0)) {
6270 dahdi_confmute(p, 0);
6275 res = analog_hangup(p->sig_pvt, ast);
6276 revert_fax_buffers(p, ast);
6285 #if defined(HAVE_PRI)
6286 if (dahdi_sig_pri_lib_handles(p->
sig)) {
6290 dahdi_confmute(p, 0);
6294 ast_dsp_free(p->
dsp);
6314 revert_fax_buffers(p, ast);
6318 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETLAW, &law);
6320 ast_log(LOG_WARNING,
"Unable to set law on channel %d to default: %s\n",
6324 sig_pri_hangup(p->sig_pvt, ast);
6327 dahdi_ec_disable(p);
6334 dahdi_conf_update(p);
6341 if (num_restart_pending == 0) {
6348 #if defined(HAVE_SS7)
6349 if (p->
sig == SIG_SS7) {
6353 dahdi_confmute(p, 0);
6357 ast_dsp_free(p->
dsp);
6376 revert_fax_buffers(p, ast);
6380 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETLAW, &law);
6382 ast_log(LOG_WARNING,
"Unable to set law on channel %d to default: %s\n",
6386 sig_ss7_hangup(p->sig_pvt, ast);
6389 dahdi_ec_disable(p);
6395 dahdi_conf_update(p);
6402 if (num_restart_pending == 0) {
6409 idx = dahdi_get_index(ast, p, 1);
6411 dahdi_confmute(p, 0);
6427 ast_debug(1,
"Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6433 p->
subs[idx].owner = NULL;
6434 p->
subs[idx].needanswer = 0;
6435 p->
subs[idx].needflash = 0;
6436 p->
subs[idx].needringing = 0;
6437 p->
subs[idx].needbusy = 0;
6438 p->
subs[idx].needcongestion = 0;
6439 p->
subs[idx].linear = 0;
6441 dahdi_setlinear(p->
subs[idx].dfd, 0);
6444 ast_debug(1,
"Normal call hung up with both three way call and a call waiting call in place?\n");
6447 ast_debug(1,
"We were flipped over to the callwait, moving back and not owning.\n");
6454 ast_debug(1,
"We were in the threeway and have a callwait still. Ditching the threeway.\n");
6460 ast_debug(1,
"Call was complete, setting owner to former third call\n");
6464 ast_debug(1,
"Call was incomplete, setting owner to NULL\n");
6483 ast_debug(1,
"Call was complete, setting owner to former third call\n");
6487 ast_debug(1,
"Call was incomplete, setting owner to NULL\n");
6521 ast_log(LOG_WARNING,
"Index found but not any type of call?\n");
6535 ast_dsp_free(p->
dsp);
6539 revert_fax_buffers(p, ast);
6543 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SETLAW, &law);
6545 ast_log(LOG_WARNING,
"Unable to set law on channel %d to default: %s\n", p->
channel, strerror(errno));
6548 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6551 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6552 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6555 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6556 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6557 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6558 dahdi_r2_disconnect_call(p, r2cause);
6560 }
else if (p->mfcr2call) {
6572 case SIG_PRI_LIB_HANDLE_CASES:
6576 res = dahdi_set_hook(p->
subs[
SUB_REAL].dfd, DAHDI_ONHOOK);
6580 ast_log(LOG_WARNING,
"Unable to hangup line %s\n", ast_channel_name(ast));
6586 memset(&par, 0,
sizeof(par));
6587 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6591 ast_debug(1,
"Hanging up channel %d, offhook = %d\n", p->
channel, par.rxisoffhook);
6594 if ((par.rxisoffhook) && (!(p->
radio || (p->
oprmode < 0))))
6595 tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6598 analog_p->fxsoffhookstate = par.rxisoffhook;
6616 dahdi_ec_disable(p);
6627 dahdi_conf_update(p);
6631 case SIG_PRI_LIB_HANDLE_CASES:
6639 if (num_restart_pending == 0)
6648 ast_channel_tech_pvt_set(ast, NULL);
6655 if (my_is_off_hook(p) && !p->
owner) {
6666 if (!p->
owner && my_is_off_hook(p)) {
6677 ast_debug(1,
"Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->
channel);
6682 ast_mutex_unlock(&p->
lock);
6683 ast_verb(3,
"Hungup '%s'\n", ast_channel_name(ast));
6687 num_restart_pending--;
6691 destroy_channel(p, 0);
6693 ast_mutex_unlock(&
iflock);
6701 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6705 ast_mutex_lock(&p->
lock);
6706 idx = dahdi_get_index(ast, p, 0);
6711 ast_mutex_unlock(&p->
lock);
6716 res = analog_answer(p->sig_pvt, ast);
6717 ast_mutex_unlock(&p->
lock);
6722 #if defined(HAVE_PRI)
6723 case SIG_PRI_LIB_HANDLE_CASES:
6724 res = sig_pri_answer(p->sig_pvt, ast);
6727 #if defined(HAVE_SS7)
6729 res = sig_ss7_answer(p->sig_pvt, ast);
6734 if (!p->mfcr2_call_accepted) {
6737 p->mfcr2_answer_pending = 1;
6738 if (p->mfcr2_charge_calls) {
6739 ast_debug(1,
"Accepting MFC/R2 call with charge before answering on chan %d\n", p->
channel);
6740 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6742 ast_debug(1,
"Accepting MFC/R2 call with no charge before answering on chan %d\n", p->
channel);
6743 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6752 ast_mutex_unlock(&p->
lock);
6755 ast_log(LOG_WARNING,
"Don't know how to answer signalling %d (channel %d)\n", p->
sig, p->
channel);
6759 ast_mutex_unlock(&p->
lock);
6763 void dahdi_dtmf_detect_disable(
struct dahdi_pvt *p)
6777 void dahdi_dtmf_detect_enable(
struct dahdi_pvt *p)
6779 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6781 if (p->
channel == CHAN_PSEUDO)
6794 static int dahdi_queryoption(
struct ast_channel *chan,
int option,
void *data,
int *datalen)
6797 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6800 if (!p || !data || (*datalen < 1)) {
6811 *cp = p->
tdd ? 1 : 0;
6817 ast_debug(1,
"Reporting digit detection %sabled on %s\n", *cp ?
"en" :
"dis", ast_channel_name(chan));
6821 *cp = (p->
dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6822 ast_debug(1,
"Reporting fax tone detection %sabled on %s\n", *cp ?
"en" :
"dis", ast_channel_name(chan));
6825 #if defined(HAVE_PRI)
6826 #if defined(HAVE_PRI_CCSS)
6827 if (dahdi_sig_pri_lib_handles(p->
sig)) {
6849 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6854 if (!p || !data || (datalen < 1)) {
6861 scp = (
signed char *) data;
6862 idx = dahdi_get_index(chan, p, 0);
6864 ast_log(LOG_WARNING,
"No index in TXGAIN?\n");
6867 ast_debug(1,
"Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->
txgain + (
float) *scp);
6868 return set_actual_txgain(p->
subs[idx].dfd, p->
txgain + (
float) *scp, p->
txdrc, p->
law);
6870 scp = (
signed char *) data;
6871 idx = dahdi_get_index(chan, p, 0);
6873 ast_log(LOG_WARNING,
"No index in RXGAIN?\n");
6876 ast_debug(1,
"Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->
rxgain + (
float) *scp);
6877 return set_actual_rxgain(p->
subs[idx].dfd, p->
rxgain + (
float) *scp, p->rxdrc, p->
law);
6884 ast_debug(1,
"Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6888 ast_debug(1,
"Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6892 ast_debug(1,
"Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6902 ast_debug(1,
"Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6908 ast_debug(1,
"Set option TDD MODE, value: %s(%d) on %s\n",
6909 (*cp == 2) ?
"MATE" :
"ON", (
int) *cp, ast_channel_name(chan));
6910 dahdi_ec_disable(p);
6913 unsigned char mybuf[41000];
6915 int size, res, fd, len;
6916 struct pollfd fds[1];
6919 memset(buf, 0x7f,
sizeof(mybuf));
6922 idx = dahdi_get_index(chan, p, 0);
6924 ast_log(LOG_WARNING,
"No index in TDD?\n");
6927 fd = p->
subs[idx].dfd;
6935 fds[0].events = POLLPRI | POLLOUT;
6937 res = poll(fds, 1, -1);
6943 if (fds[0].revents & POLLPRI)
6945 if (!(fds[0].revents & POLLOUT)) {
6949 res = write(fd, buf, size);
6951 if (res == -1)
return -1;
6952 ast_debug(1,
"Write returned %d (%s) on channel %d\n", res, strerror(errno), p->
channel);
6975 ast_debug(1,
"Set option RELAX DTMF, value: %s(%d) on %s\n",
6976 *cp ?
"ON" :
"OFF", (
int) *cp, ast_channel_name(chan));
6980 #if defined(HAVE_PRI)
6981 if (dahdi_sig_pri_lib_handles(p->
sig)
6982 && ((
struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6990 ast_debug(1,
"Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6992 dahdi_ec_disable(p);
6994 ast_debug(1,
"Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6997 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6998 ast_log(LOG_WARNING,
"Unable to set audio mode on channel %d to %d: %s\n", p->
channel, x, strerror(errno));
7000 case AST_OPTION_OPRMODE:
7001 oprmode = (
struct oprmode *) data;
7004 ast_log(LOG_NOTICE,
"Operator mode not supported on %s to %s calls.\n",
7009 pp = ast_channel_tech_pvt(oprmode->peer);
7020 ast_debug(1,
"Set Operator Services mode, value: %d on %s/%s\n",
7021 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
7026 ast_debug(1,
"Enabling echo cancellation on %s\n", ast_channel_name(chan));
7029 ast_debug(1,
"Disabling echo cancellation on %s\n", ast_channel_name(chan));
7030 dahdi_ec_disable(p);
7035 ast_debug(1,
"%sabling digit detection on %s\n", *cp ?
"En" :
"Dis", ast_channel_name(chan));
7037 dahdi_dtmf_detect_enable(p);
7039 dahdi_dtmf_detect_disable(p);
7045 ast_debug(1,
"%sabling fax tone detection on %s\n", *cp ?
"En" :
"Dis", ast_channel_name(chan));
7062 static int dahdi_func_read(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t len)
7064 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7073 if (!strcasecmp(data,
"rxgain")) {
7074 ast_mutex_lock(&p->
lock);
7075 snprintf(buf, len,
"%f", p->
rxgain);
7076 ast_mutex_unlock(&p->
lock);
7077 }
else if (!strcasecmp(data,
"txgain")) {
7078 ast_mutex_lock(&p->
lock);
7079 snprintf(buf, len,
"%f", p->
txgain);
7080 ast_mutex_unlock(&p->
lock);
7081 }
else if (!strcasecmp(data,
"dahdi_channel")) {
7082 ast_mutex_lock(&p->
lock);
7083 snprintf(buf, len,
"%d", p->
channel);
7084 ast_mutex_unlock(&p->
lock);
7085 }
else if (!strcasecmp(data,
"dahdi_span")) {
7086 ast_mutex_lock(&p->
lock);
7087 snprintf(buf, len,
"%d", p->
span);
7088 ast_mutex_unlock(&p->
lock);
7089 }
else if (!strcasecmp(data,
"dahdi_group")) {
7090 ast_mutex_lock(&p->
lock);
7091 snprintf(buf, len,
"%llu", p->
group);
7092 ast_mutex_unlock(&p->
lock);
7093 }
else if (!strcasecmp(data,
"dahdi_type")) {
7094 ast_mutex_lock(&p->
lock);
7096 #if defined(HAVE_OPENR2)
7101 #if defined(HAVE_PRI)
7102 case SIG_PRI_LIB_HANDLE_CASES:
7109 #if defined(HAVE_SS7)
7119 ast_mutex_unlock(&p->
lock);
7120 #if defined(HAVE_PRI)
7121 #if defined(HAVE_PRI_REVERSE_CHARGE)
7122 }
else if (!strcasecmp(data,
"reversecharge")) {
7123 ast_mutex_lock(&p->
lock);
7125 case SIG_PRI_LIB_HANDLE_CASES:
7126 snprintf(buf, len,
"%d", ((
struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
7133 ast_mutex_unlock(&p->
lock);
7135 #if defined(HAVE_PRI_SETUP_KEYPAD)
7136 }
else if (!strcasecmp(data,
"keypad_digits")) {
7137 ast_mutex_lock(&p->
lock);
7139 case SIG_PRI_LIB_HANDLE_CASES:
7148 ast_mutex_unlock(&p->
lock);
7150 }
else if (!strcasecmp(data,
"no_media_path")) {
7151 ast_mutex_lock(&p->
lock);
7153 case SIG_PRI_LIB_HANDLE_CASES:
7158 snprintf(buf, len,
"%d", ((
struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
7165 ast_mutex_unlock(&p->
lock);
7167 }
else if (!strcasecmp(data,
"dialmode")) {
7169 ast_mutex_lock(&p->
lock);
7170 analog_p = p->sig_pvt;
7172 if (dahdi_analog_lib_handles(p->
sig, 0, 0) && analog_p) {
7174 case ANALOG_DIALMODE_BOTH:
7177 case ANALOG_DIALMODE_PULSE:
7180 case ANALOG_DIALMODE_DTMF:
7183 case ANALOG_DIALMODE_NONE:
7188 ast_log(LOG_WARNING,
"%s only supported on analog channels\n", data);
7192 ast_mutex_unlock(&p->
lock);
7202 static int parse_buffers_policy(
const char *parse,
int *num_buffers,
int *policy)
7205 char policy_str[21] =
"";
7207 if ((res = sscanf(parse,
"%30d,%20s", num_buffers, policy_str)) != 2) {
7208 ast_log(LOG_WARNING,
"Parsing buffer string '%s' failed.\n", parse);
7211 if (*num_buffers < 0) {
7212 ast_log(LOG_WARNING,
"Invalid buffer count given '%d'.\n", *num_buffers);
7215 if (!strcasecmp(policy_str,
"full")) {
7216 *policy = DAHDI_POLICY_WHEN_FULL;
7217 }
else if (!strcasecmp(policy_str,
"immediate")) {
7218 *policy = DAHDI_POLICY_IMMEDIATE;
7219 #if defined(HAVE_DAHDI_HALF_FULL)
7220 }
else if (!strcasecmp(policy_str,
"half")) {
7221 *policy = DAHDI_POLICY_HALF_FULL;
7224 ast_log(LOG_WARNING,
"Invalid policy name given '%s'.\n", policy_str);
7231 static int dahdi_func_write(
struct ast_channel *chan,
const char *
function,
char *data,
const char *value)
7233 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
7241 if (!strcasecmp(data,
"buffers")) {
7242 int num_bufs, policy;
7244 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
7245 struct dahdi_bufferinfo bi = {
7246 .txbufpolicy = policy,
7247 .rxbufpolicy = policy,
7249 .numbufs = num_bufs,
7253 if ((bpres = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7254 ast_log(LOG_WARNING,
"Channel '%d' unable to override buffer policy: %s\n", p->
channel, strerror(errno));
7261 }
else if (!strcasecmp(data,
"echocan_mode")) {
7262 if (!strcasecmp(value,
"on")) {
7263 ast_mutex_lock(&p->
lock);
7265 ast_mutex_unlock(&p->
lock);
7266 }
else if (!strcasecmp(value,
"off")) {
7267 ast_mutex_lock(&p->
lock);
7268 dahdi_ec_disable(p);
7269 ast_mutex_unlock(&p->
lock);
7270 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7271 }
else if (!strcasecmp(value,
"fax")) {
7274 ast_mutex_lock(&p->
lock);
7278 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7279 ast_log(LOG_WARNING,
"Unable to place echocan into fax mode on channel %d: %s\n", p->
channel, strerror(errno));
7281 ast_mutex_unlock(&p->
lock);
7282 }
else if (!strcasecmp(value,
"voice")) {
7285 ast_mutex_lock(&p->
lock);
7289 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
7290 ast_log(LOG_WARNING,
"Unable to place echocan into voice mode on channel %d: %s\n", p->
channel, strerror(errno));
7292 ast_mutex_unlock(&p->
lock);
7295 ast_log(LOG_WARNING,
"Unsupported value '%s' provided for '%s' item.\n", value, data);
7298 }
else if (!strcasecmp(data,
"dialmode")) {
7301 ast_mutex_lock(&p->
lock);
7302 analog_p = p->sig_pvt;
7303 if (!dahdi_analog_lib_handles(p->
sig, 0, 0) || !analog_p) {
7304 ast_log(LOG_WARNING,
"%s only supported on analog channels\n", data);
7305 ast_mutex_unlock(&p->
lock);
7309 if (!strcasecmp(value,
"pulse")) {
7311 }
else if (!strcasecmp(value,
"dtmf") || !strcasecmp(value,
"tone")) {
7313 }
else if (!strcasecmp(value,
"none")) {
7315 }
else if (!strcasecmp(value,
"both")) {
7318 ast_log(LOG_WARNING,
"'%s' is an invalid setting for %s\n", value, data);
7321 ast_mutex_unlock(&p->
lock);
7322 }
else if (!strcasecmp(data,
"waitfordialtone")) {
7323 if (ast_strlen_zero(value)) {
7324 ast_log(LOG_WARNING,
"waitfordialtone requires a duration in ms\n");
7328 ast_mutex_lock(&p->
lock);
7329 if (!CANPROGRESSDETECT(p)) {
7330 ast_log(LOG_WARNING,
"%s only supported on analog trunks\n", data);
7331 ast_mutex_unlock(&p->
lock);
7336 ast_mutex_unlock(&p->
lock);
7344 void dahdi_master_slave_unlink(
struct dahdi_pvt *slave,
struct dahdi_pvt *master,
int needlock)
7352 ast_mutex_lock(&master->
lock);
7354 while (ast_mutex_trylock(&slave->
lock)) {
7355 DEADLOCK_AVOIDANCE(&master->
lock);
7360 for (x = 0; x < MAX_SLAVES; x++) {
7362 if (!slave || (master->
slaves[x] == slave)) {
7368 master->
slaves[x] = NULL;
7381 for (x = 0; x < MAX_SLAVES; x++) {
7392 dahdi_conf_update(master);
7395 ast_mutex_unlock(&slave->
lock);
7396 ast_mutex_unlock(&master->
lock);
7403 if (!slave || !master) {
7404 ast_log(LOG_WARNING,
"Tried to link to/from NULL??\n");
7407 for (x = 0; x < MAX_SLAVES; x++) {
7408 if (!master->
slaves[x]) {
7409 master->
slaves[x] = slave;
7413 if (x >= MAX_SLAVES) {
7414 ast_log(LOG_WARNING,
"Replacing slave %d with new slave, %d\n", master->
slaves[MAX_SLAVES - 1]->
channel, slave->
channel);
7415 master->
slaves[MAX_SLAVES - 1] = slave;
7418 ast_log(LOG_WARNING,
"Replacing master %d with new master, %d\n", slave->
master->
channel, master->
channel);
7426 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7429 ast_mutex_lock(&p->
lock);
7431 ast_debug(1,
"New owner for channel %d is %s\n", p->
channel, ast_channel_name(newchan));
7432 if (p->
owner == oldchan) {
7435 for (x = 0; x < 3; x++) {
7436 if (p->
subs[x].owner == oldchan) {
7438 dahdi_master_slave_unlink(NULL, p, 0);
7440 p->
subs[x].owner = newchan;
7444 analog_fixup(oldchan, newchan, p->sig_pvt);
7445 #if defined(HAVE_PRI)
7446 }
else if (dahdi_sig_pri_lib_handles(p->
sig)) {
7447 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7449 #if defined(HAVE_SS7)
7450 }
else if (p->
sig == SIG_SS7) {
7451 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7454 dahdi_conf_update(p);
7456 ast_mutex_unlock(&p->
lock);
7464 static int dahdi_ring_phone(
struct dahdi_pvt *p)
7486 ast_log(LOG_WARNING,
"Couldn't ring the phone: %s\n", strerror(errno));
7494 static void *analog_ss_thread(
void *data);
7508 static int attempt_transfer(
struct dahdi_pvt *p)
7518 ast_verb(3,
"TRANSFERRING %s to %s\n",
7519 ast_channel_name(owner_3way), ast_channel_name(owner_real));
7521 ast_channel_unlock(owner_real);
7522 ast_channel_unlock(owner_3way);
7523 ast_mutex_unlock(&p->
lock);
7532 ast_channel_lock(owner_real);
7533 ast_mutex_lock(&p->
lock);
7541 static int check_for_conference(
struct dahdi_pvt *p)
7543 struct dahdi_confinfo ci;
7547 memset(&ci, 0,
sizeof(ci));
7548 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7549 ast_log(LOG_WARNING,
"Failed to get conference info on channel %d: %s\n", p->
channel, strerror(errno));
7556 ast_verb(3,
"Avoiding 3-way call when in an external conference\n");
7570 struct dahdi_spaninfo zi;
7571 struct dahdi_params params;
7573 memset(&zi, 0,
sizeof(zi));
7574 zi.spanno = p->
span;
7576 if ((res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7577 if (zi.alarms != DAHDI_ALARM_NONE)
7580 ast_log(LOG_WARNING,
"Unable to determine alarm on channel %d: %s\n", p->
channel, strerror(errno));
7585 memset(¶ms, 0,
sizeof(params));
7586 if ((res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
7587 return params.chan_alarms;
7589 ast_log(LOG_WARNING,
"Unable to determine alarm on channel %d\n", p->
channel);
7591 return DAHDI_ALARM_NONE;
7596 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7599 ast_debug(1,
"%s DTMF digit: 0x%02X '%c' on %s\n",
7605 ast_debug(1,
"Confirm answer on %s!\n", ast_channel_name(ast));
7616 *dest = &p->
subs[idx].
f;
7620 ast_debug(1,
"Got some DTMF, but it's for the CAS\n");
7629 *dest = &p->
subs[idx].
f;
7636 struct dahdi_bufferinfo bi = {
7643 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7644 ast_log(LOG_WARNING,
"Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7653 ast_debug(1,
"Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7655 if (strcmp(ast_channel_exten(ast),
"fax")) {
7656 const char *target_context = ast_channel_context(ast);
7666 ast_mutex_unlock(&p->
lock);
7667 ast_channel_unlock(ast);
7669 S_COR(ast_channel_caller(ast)->
id.
number.valid, ast_channel_caller(ast)->
id.
number.str, NULL))) {
7670 ast_verb(3,
"Redirecting %s to fax extension\n", ast_channel_name(ast));
7674 ast_log(LOG_WARNING,
"Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7676 ast_log(LOG_NOTICE,
"Fax detected, but no fax extension\n");
7678 ast_channel_lock(ast);
7679 ast_mutex_lock(&p->
lock);
7681 ast_debug(1,
"Already in a fax extension, not redirecting\n");
7686 dahdi_confmute(p, 0);
7690 *dest = &p->
subs[idx].
f;
7694 static void publish_span_alarm(
int span,
const char *alarm_txt)
7700 "Alarm", alarm_txt);
7708 static void publish_channel_alarm(
int channel,
const char *alarm_txt)
7719 "Alarm", alarm_txt);
7727 static void handle_alarms(
struct dahdi_pvt *p,
int alms)
7729 const char *alarm_str;
7731 #if defined(HAVE_PRI)
7737 alarm_str = alarm2str(alms);
7738 if (report_alarms & REPORT_CHANNEL_ALARMS) {
7739 ast_log(LOG_WARNING,
"Detected alarm on channel %d: %s\n", p->
channel, alarm_str);
7740 publish_channel_alarm(p->
channel, alarm_str);
7744 ast_log(LOG_WARNING,
"Detected alarm on span %d: %s\n", p->
span, alarm_str);
7745 publish_span_alarm(p->
span, alarm_str);
7754 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7759 idx = dahdi_get_index(ast, p, 0);
7772 p->
subs[idx].
f.
src =
"dahdi_handle_event";
7774 f = &p->
subs[idx].
f;
7782 ast_debug(1,
"Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->
channel, idx);
7784 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7785 p->
pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7787 #if defined(HAVE_PRI)
7788 if (dahdi_sig_pri_lib_handles(p->
sig)
7791 && (p->pri->
overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7797 dahdi_confmute(p, 0);
7800 dahdi_handle_dtmf(ast, idx, &f);
7805 if (res & DAHDI_EVENT_DTMFDOWN) {
7806 ast_debug(1,
"DTMF Down '%c'\n", res & 0xff);
7807 #if defined(HAVE_PRI)
7808 if (dahdi_sig_pri_lib_handles(p->
sig)
7811 && (p->pri->
overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7817 dahdi_confmute(p, 1);
7820 dahdi_handle_dtmf(ast, idx, &f);
7822 return &p->
subs[idx].
f;
7826 case DAHDI_EVENT_EC_DISABLED:
7827 ast_verb(3,
"Channel %d echo canceler disabled.\n", p->
channel);
7830 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7831 case DAHDI_EVENT_TX_CED_DETECTED:
7832 ast_verb(3,
"Channel %d detected a CED tone towards the network.\n", p->
channel);
7834 case DAHDI_EVENT_RX_CED_DETECTED:
7835 ast_verb(3,
"Channel %d detected a CED tone from the network.\n", p->
channel);
7837 case DAHDI_EVENT_EC_NLP_DISABLED:
7838 ast_verb(3,
"Channel %d echo canceler disabled its NLP.\n", p->
channel);
7840 case DAHDI_EVENT_EC_NLP_ENABLED:
7841 ast_verb(3,
"Channel %d echo canceler enabled its NLP.\n", p->
channel);
7844 case DAHDI_EVENT_BITSCHANGED:
7846 if (p->
sig != SIG_MFCR2) {
7847 ast_log(LOG_WARNING,
"Received bits changed on %s signalling?\n", sig2str(p->
sig));
7850 openr2_chan_handle_cas(p->r2chan);
7853 ast_log(LOG_WARNING,
"Received bits changed on %s signalling?\n", sig2str(p->
sig));
7856 case DAHDI_EVENT_PULSE_START:
7858 if (!ast_channel_pbx(ast))
7859 tone_zone_play_tone(p->
subs[idx].dfd, -1);
7861 case DAHDI_EVENT_DIALCOMPLETE:
7863 #if defined(HAVE_PRI)
7864 if (dahdi_sig_pri_lib_handles(p->
sig)) {
7868 if (ioctl(p->
subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7869 ast_debug(1,
"DAHDI_DIALING ioctl failed on %s: %s\n",
7870 ast_channel_name(ast), strerror(errno));
7894 if (ioctl(p->
subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7895 ast_debug(1,
"DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7903 p->
dop.op = DAHDI_DIAL_OP_REPLACE;
7904 res = dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr);
7908 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7922 ast_debug(1,
"Done dialing, but waiting for progress detection before doing more...\n");
7924 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7925 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7926 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7927 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7928 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7929 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7930 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7931 || (mysig == SIG_SF_FEATB)))) {
7947 case DAHDI_EVENT_ALARM:
7949 #if defined(HAVE_PRI)
7950 case SIG_PRI_LIB_HANDLE_CASES:
7954 #if defined(HAVE_SS7)
7956 sig_ss7_set_alarm(p->sig_pvt, 1);
7964 handle_alarms(p, res);
7966 if (!p->pri || !p->pri->
pri || pri_get_timer(p->pri->
pri, PRI_TIMER_T309) < 0) {
7972 #if defined(HAVE_SS7)
7973 if (p->
sig == SIG_SS7)
7977 if (p->
sig == SIG_MFCR2)
7980 case DAHDI_EVENT_ONHOOK:
7989 ast_verb(4,
"Operator mode enabled on channel %d, holding line for channel %d\n", p->
channel, p->
oprpeer->
channel);
7993 if ((p->
sig == SIG_FXOLS) || (p->
sig == SIG_FXOKS) || (p->
sig == SIG_FXOGS))
8000 ast_verb(4,
"Operator recall, channel %d ringing back channel %d\n", p->
oprpeer->
channel, p->
channel);
8014 ast_verb(3,
"Channel %d still has (callwait) call, ringing phone\n", p->
channel);
8017 p->
subs[idx].needanswer = 0;
8018 p->
subs[idx].needringing = 0;
8027 dahdi_ring_phone(p);
8029 unsigned int mssinceflash;
8034 DLA_UNLOCK(&p->
lock);
8035 CHANNEL_DEADLOCK_AVOIDANCE(ast);
8040 if (p->
owner != ast) {
8041 ast_log(LOG_WARNING,
"This isn't good...\n");
8046 ast_log(LOG_NOTICE,
"Whoa, threeway disappeared kinda randomly.\n");
8050 ast_debug(1,
"Last flash was %u ms ago\n", mssinceflash);
8057 ast_debug(1,
"Looks like a bounced flash, hanging up both calls on %d\n", p->
channel);
8071 dahdi_ring_phone(p);
8072 }
else if (!attempt_transfer(p)) {
8091 dahdi_ring_phone(p);
8095 ast_log(LOG_WARNING,
"Got a hangup and my index is %d?\n", idx);
8099 dahdi_ec_disable(p);
8103 case DAHDI_EVENT_RINGOFFHOOK:
8107 if ((p->
sig == SIG_FXOLS) || (p->
sig == SIG_FXOKS) || (p->
sig == SIG_FXOGS))
8112 restore_conference(p->
oprpeer);
8133 int numchars = snprintf(p->
dop.dialstr,
sizeof(p->
dop.dialstr),
"M*0%s#", c);
8134 if (numchars >=
sizeof(p->
dop.dialstr)) {
8135 ast_log(LOG_WARNING,
"Dial string '%s' truncated\n", c);
8141 if (strlen(p->
dop.dialstr) > 4) {
8146 p->
dop.dialstr[strlen(p->
dop.dialstr)-2] =
'\0';
8149 if (dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr)) {
8155 return &p->
subs[idx].
f;
8169 dahdi_set_hook(p->
subs[idx].dfd, DAHDI_OFFHOOK);
8175 restore_conference(p);
8183 }
else if (!ast_strlen_zero(p->
dop.dialstr)) {
8185 res = dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr);
8187 p->
dop.dialstr[0] =
'\0';
8190 ast_debug(1,
"Sent FXO deferred digit string: %s\n", p->
dop.dialstr);
8195 p->
dop.dialstr[0] =
'\0';
8199 return &p->
subs[idx].
f;
8202 ast_channel_rings_set(ast, 1);
8206 return &p->
subs[idx].
f;
8209 dahdi_set_hook(p->
subs[idx].dfd, DAHDI_OFFHOOK);
8212 p->
subs[idx].needunhold = 1;
8217 res = tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_STUTTER);
8219 res = tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
8222 ast_log(LOG_WARNING,
"FXO phone off hook in weird state %u??\n",
ast_channel_state(ast));
8234 ast_debug(1,
"Setting IDLE polarity due "
8235 "to ring. Old polarity was %d\n",
8245 case SIG_FEATDMF_TA:
8248 case SIG_FGC_CAMAMF:
8253 case SIG_SF_FEATDMF:
8275 ast_log(LOG_WARNING,
"Don't know how to handle ring/off hook for signalling %d\n", p->
sig);
8278 case DAHDI_EVENT_RINGBEGIN:
8289 case DAHDI_EVENT_RINGERON:
8291 case DAHDI_EVENT_NOALARM:
8293 #if defined(HAVE_PRI)
8294 case SIG_PRI_LIB_HANDLE_CASES:
8298 #if defined(HAVE_SS7)
8300 sig_ss7_set_alarm(p->sig_pvt, 0);
8307 handle_clear_alarms(p);
8309 case DAHDI_EVENT_WINKFLASH:
8311 if (p->
radio)
break;
8315 struct dahdi_params par;
8317 memset(&par, 0,
sizeof(par));
8320 if (!par.rxisoffhook)
8326 tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
8327 ast_verb(4,
"Operator flash recall, channel %d ringing back channel %d\n", p->
oprpeer->
channel, p->
channel);
8338 ast_debug(1,
"Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
8344 restore_conference(p);
8348 ast_log(LOG_WARNING,
"Got flash hook with index %d on channel %d?!?\n", idx, p->
channel);
8357 ast_debug(1,
"Making %s the new owner\n", ast_channel_name(p->
owner));
8377 }
else if (!check_for_conference(p)) {
8378 ast_callid callid = 0;
8399 if (!((ast_channel_pbx(ast)) ||
8402 ast_debug(1,
"Flash when call not up or ringing\n");
8406 ast_log(LOG_WARNING,
"Unable to allocate three-way subchannel\n");
8416 ast_mutex_unlock(&p->
lock);
8417 ast_channel_unlock(ast);
8419 ast_channel_lock(ast);
8420 ast_mutex_lock(&p->
lock);
8432 dahdi_ec_disable(p);
8433 res = tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8435 ast_log(LOG_WARNING,
"Unable to start dial recall tone on channel %d\n", p->
channel);
8438 ast_log(LOG_WARNING,
"Cannot allocate new structure on channel %d\n", p->
channel);
8439 }
else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8440 ast_log(LOG_WARNING,
"Unable to start simple switch on channel %d\n", p->
channel);
8441 res = tone_zone_play_tone(p->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8445 ast_verb(3,
"Started three way call on channel %d\n", p->
channel);
8457 ast_debug(1,
"Got flash with three way call up, dropping last call on %d\n", p->
channel);
8465 ast_verb(3,
"Dropping three-way call on %s\n", ast_channel_name(p->
subs[
SUB_THREEWAY].owner));
8475 ast_verb(3,
"Building conference call with %s and %s\n",
8485 if (p->
subs[otherindex].owner) {
8488 p->
subs[otherindex].needunhold = 1;
8491 ast_verb(3,
"Dumping incomplete call on %s\n", ast_channel_name(p->
subs[
SUB_THREEWAY].owner));
8504 dahdi_conf_update(p);
8519 case SIG_FEATDMF_TA:
8522 ast_debug(1,
"ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->
owner)->
ani2,
8525 snprintf(p->
dop.dialstr,
sizeof(p->
dop.dialstr),
"M*%d%s#",
8534 ast_log(LOG_WARNING,
"Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8541 case SIG_FGC_CAMAMF:
8544 case SIG_SF_FEATDMF:
8548 if (!ast_strlen_zero(p->
dop.dialstr)) {
8549 res = dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr);
8551 p->
dop.dialstr[0] =
'\0';
8554 ast_debug(1,
"Sent deferred digit string: %s\n", p->
dop.dialstr);
8556 p->
dop.dialstr[0] =
'\0';
8559 ast_log(LOG_WARNING,
"Don't know how to handle ring/off hook for signalling %d\n", p->
sig);
8562 case DAHDI_EVENT_HOOKCOMPLETE:
8577 if (!ast_strlen_zero(p->
dop.dialstr)) {
8578 res = dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr);
8580 p->
dop.dialstr[0] =
'\0';
8583 ast_debug(1,
"Sent deferred digit string: %s\n", p->
dop.dialstr);
8585 p->
dop.dialstr[0] =
'\0';
8586 p->
dop.op = DAHDI_DIAL_OP_REPLACE;
8589 case SIG_FEATDMF_TA:
8592 case SIG_FGC_CAMAMF:
8594 case SIG_SF_FEATDMF:
8596 ast_debug(1,
"Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->
channel);
8602 case DAHDI_EVENT_POLARITY:
8614 ast_debug(1,
"Answering on polarity switch!\n");
8629 ast_debug(1,
"Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64
"\n", p->
channel,
ast_channel_state(ast), p->
polarity, p->
answeronpolarityswitch, p->
hanguponpolarityswitch, p->
polarityonanswerdelay,
ast_tvdiff_ms(
ast_tvnow(), p->
polaritydelaytv) );
8632 ast_debug(1,
"Polarity Reversal detected and now Hanging up on channel %d\n", p->
channel);
8643 ast_debug(1,
"Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64
"\n", p->
channel,
ast_channel_state(ast), p->
polarity, p->
answeronpolarityswitch, p->
hanguponpolarityswitch, p->
polarityonanswerdelay,
ast_tvdiff_ms(
ast_tvnow(), p->
polaritydelaytv) );
8646 ast_debug(1,
"Dunno what to do with event %d on channel %d\n", res, p->
channel);
8648 return &p->
subs[idx].
f;
8657 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8659 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8670 p->
subs[idx].
f.
src =
"dahdi_exception";
8686 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8687 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8688 ast_debug(1,
"Restoring owner of channel %d on event %d\n", p->
channel, res);
8696 case DAHDI_EVENT_ONHOOK:
8697 dahdi_ec_disable(p);
8699 ast_verb(3,
"Channel %s still has call, ringing phone\n", ast_channel_name(p->
owner));
8700 dahdi_ring_phone(p);
8705 ast_log(LOG_WARNING,
"Absorbed on hook, but nobody is left!?!?\n");
8706 dahdi_conf_update(p);
8708 case DAHDI_EVENT_RINGOFFHOOK:
8716 case DAHDI_EVENT_HOOKCOMPLETE:
8717 case DAHDI_EVENT_RINGERON:
8718 case DAHDI_EVENT_RINGEROFF:
8721 case DAHDI_EVENT_WINKFLASH:
8724 ast_verb(3,
"Channel %d flashed to other channel %s\n", p->
channel, ast_channel_name(p->
owner));
8727 usedindex = dahdi_get_index(p->
owner, p, 0);
8728 if (usedindex > -1) {
8729 p->
subs[usedindex].needanswer = 1;
8739 ast_log(LOG_WARNING,
"Absorbed on hook, but nobody is left!?!?\n");
8740 dahdi_conf_update(p);
8743 ast_log(LOG_WARNING,
"Don't know how to absorb event %s\n", event2str(res));
8745 f = &p->
subs[idx].
f;
8749 ast_debug(1,
"Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->
channel);
8751 if (ast != p->
owner) {
8753 ast_log(LOG_WARNING,
"We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->
owner));
8755 f = &p->
subs[idx].
f;
8759 f = dahdi_handle_event(ast);
8761 const char *name =
ast_strdupa(ast_channel_name(ast));
8764 ast_mutex_unlock(&p->
lock);
8765 ast_channel_unlock(ast);
8767 ast_channel_lock(ast);
8768 ast_mutex_lock(&p->
lock);
8775 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8777 ast_mutex_lock(&p->
lock);
8780 f = analog_exception(analog_p, ast);
8782 f = __dahdi_exception(ast);
8784 ast_mutex_unlock(&p->
lock);
8801 p = ast_channel_tech_pvt(ast);
8802 while (ast_mutex_trylock(&p->
lock)) {
8803 CHANNEL_DEADLOCK_AVOIDANCE(ast);
8816 if (ast_channel_tech_pvt(ast) != p) {
8822 idx = dahdi_get_index(ast, p, 0);
8826 ast_log(LOG_WARNING,
"We don't exist?\n");
8827 ast_mutex_unlock(&p->
lock);
8832 ast_mutex_unlock(&p->
lock);
8849 struct dahdi_params ps;
8851 memset(&ps, 0,
sizeof(ps));
8852 if (ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8853 ast_mutex_unlock(&p->
lock);
8866 ast_mutex_unlock(&p->
lock);
8867 return &p->
subs[idx].
f;
8870 if (!(--p->
ringt)) {
8871 ast_mutex_unlock(&p->
lock);
8878 openr2_chan_process_event(p->r2chan);
8879 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8883 if (p->mfcr2_call_accepted &&
8884 !p->mfcr2_progress_sent &&
8886 ast_debug(1,
"Enqueuing progress frame after R2 accept in chan %d\n", p->
channel);
8888 p->mfcr2_progress_sent = 1;
8894 if (p->
subs[idx].needringing) {
8896 p->
subs[idx].needringing = 0;
8900 ast_mutex_unlock(&p->
lock);
8901 return &p->
subs[idx].
f;
8904 if (p->
subs[idx].needbusy) {
8906 p->
subs[idx].needbusy = 0;
8909 ast_mutex_unlock(&p->
lock);
8910 return &p->
subs[idx].
f;
8913 if (p->
subs[idx].needcongestion) {
8915 p->
subs[idx].needcongestion = 0;
8918 ast_mutex_unlock(&p->
lock);
8919 return &p->
subs[idx].
f;
8922 if (p->
subs[idx].needanswer) {
8924 p->
subs[idx].needanswer = 0;
8927 ast_mutex_unlock(&p->
lock);
8928 return &p->
subs[idx].
f;
8931 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8936 ast_mutex_unlock(&p->
lock);
8941 if (p->
subs[idx].needflash) {
8943 p->
subs[idx].needflash = 0;
8946 ast_mutex_unlock(&p->
lock);
8947 return &p->
subs[idx].
f;
8950 if (p->
subs[idx].needhold) {
8952 p->
subs[idx].needhold = 0;
8955 ast_mutex_unlock(&p->
lock);
8956 ast_debug(1,
"Sending hold on '%s'\n", ast_channel_name(ast));
8957 return &p->
subs[idx].
f;
8960 if (p->
subs[idx].needunhold) {
8962 p->
subs[idx].needunhold = 0;
8965 ast_mutex_unlock(&p->
lock);
8966 ast_debug(1,
"Sending unhold on '%s'\n", ast_channel_name(ast));
8967 return &p->
subs[idx].
f;
8978 f = analog_exception(analog_p, ast);
8980 f = __dahdi_exception(ast);
8982 ast_mutex_unlock(&p->
lock);
8987 if (!p->
subs[idx].linear) {
8988 p->
subs[idx].linear = 1;
8989 res = dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
8991 ast_log(LOG_WARNING,
"Unable to set channel %d (index %d) to linear mode.\n", p->
channel, idx);
8994 if (p->
subs[idx].linear) {
8995 p->
subs[idx].linear = 0;
8996 res = dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
8998 ast_log(LOG_WARNING,
"Unable to set channel %d (index %d) to companded mode.\n", p->
channel, idx);
9009 if (errno == EAGAIN) {
9011 ast_mutex_unlock(&p->
lock);
9012 return &p->
subs[idx].
f;
9013 }
else if (errno == ELAST) {
9016 f = analog_exception(analog_p, ast);
9018 f = __dahdi_exception(ast);
9021 ast_log(LOG_WARNING,
"dahdi_rec: %s\n", strerror(errno));
9023 ast_mutex_unlock(&p->
lock);
9027 ast_debug(1,
"Short read (%d/%d), must be an event...\n", res, p->
subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
9030 f = analog_exception(analog_p, ast);
9032 f = __dahdi_exception(ast);
9034 ast_mutex_unlock(&p->
lock);
9043 ast_mutex_unlock(&p->
lock);
9053 *((
char *) p->
subs[idx].
f.
data.ptr) = c;
9054 ast_mutex_unlock(&p->
lock);
9055 return &p->
subs[idx].
f;
9063 ast_verb(3,
"CPE does not support Call Waiting Caller*ID.\n");
9064 restore_conference(p);
9074 dahdi_callwait(ast);
9078 if (p->
subs[idx].linear) {
9120 ast_debug(1,
"Channel driver fax CNG detection timeout on %s\n",
9121 ast_channel_name(ast));
9130 dahdi_confmute(p, mute);
9159 if (dahdi_sig_pri_lib_handles(p->
sig)
9165 ast_debug(1,
"Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
9178 ast_log(LOG_NOTICE,
"Never saw dialtone on channel %d\n", p->
channel);
9188 ast_debug(1,
"Got 10 samples of dialtone!\n");
9189 if (!ast_strlen_zero(p->
dop.dialstr)) {
9190 res = dahdi_dial_str(p, p->
dop.op, p->
dop.dialstr);
9192 p->
dop.dialstr[0] =
'\0';
9193 ast_mutex_unlock(&p->
lock);
9197 ast_debug(1,
"Sent deferred digit string: %s\n", p->
dop.dialstr);
9199 p->
dop.dialstr[0] =
'\0';
9200 p->
dop.op = DAHDI_DIAL_OP_REPLACE;
9209 f = &p->
subs[idx].
f;
9216 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
9218 dahdi_handle_dtmf(ast, idx, &f);
9220 if (!(p->
dialmode == ANALOG_DIALMODE_BOTH || p->
dialmode == ANALOG_DIALMODE_DTMF)) {
9245 ast_mutex_unlock(&p->
lock);
9249 static int my_dahdi_write(
struct dahdi_pvt *p,
unsigned char *buf,
int len,
int idx,
int linear)
9255 fd = p->
subs[idx].dfd;
9258 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
9259 size = (linear ? READ_SIZE * 2 :
READ_SIZE);
9260 res = write(fd, buf, size);
9262 ast_debug(1,
"Write returned %d (%s) on channel %d\n", res, strerror(errno), p->
channel);
9280 ast_log(LOG_WARNING,
"Don't know what to do with frame type '%u'\n",
9291 p = ast_channel_tech_pvt(ast);
9292 ast_mutex_lock(&p->
lock);
9294 idx = dahdi_get_index(ast, p, 0);
9296 ast_mutex_unlock(&p->
lock);
9297 ast_log(LOG_WARNING,
"%s doesn't really exist?\n", ast_channel_name(ast));
9302 ast_mutex_unlock(&p->
lock);
9303 ast_debug(5,
"Dropping frame since I'm still dialing on %s...\n",
9304 ast_channel_name(ast));
9308 ast_mutex_unlock(&p->
lock);
9309 ast_debug(5,
"Dropping frame since there is no active owner on %s...\n",
9310 ast_channel_name(ast));
9314 ast_mutex_unlock(&p->
lock);
9315 ast_debug(5,
"Dropping frame since I've still got a callerid spill on %s...\n",
9316 ast_channel_name(ast));
9321 if (!p->
subs[idx].linear) {
9322 p->
subs[idx].linear = 1;
9323 res = dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
9325 ast_log(LOG_WARNING,
"Unable to set linear mode on channel %d\n", p->
channel);
9327 res = my_dahdi_write(p, (
unsigned char *)frame->
data.ptr, frame->
datalen, idx, 1);
9331 if (p->
subs[idx].linear) {
9332 p->
subs[idx].linear = 0;
9333 res = dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
9335 ast_log(LOG_WARNING,
"Unable to set companded mode on channel %d\n", p->
channel);
9337 res = my_dahdi_write(p, (
unsigned char *)frame->
data.ptr, frame->
datalen, idx, 0);
9339 ast_mutex_unlock(&p->
lock);
9340 ast_log(LOG_WARNING,
"Cannot handle frames in %s format\n",
9344 ast_mutex_unlock(&p->
lock);
9346 ast_log(LOG_WARNING,
"write failed: %s\n", strerror(errno));
9352 static int dahdi_indicate(
struct ast_channel *chan,
int condition,
const void *data,
size_t datalen)
9354 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9357 int func = DAHDI_FLASH;
9359 ast_mutex_lock(&p->
lock);
9360 ast_debug(1,
"Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
9362 #if defined(HAVE_PRI)
9363 case SIG_PRI_LIB_HANDLE_CASES:
9364 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
9365 ast_mutex_unlock(&p->
lock);
9368 #if defined(HAVE_SS7)
9370 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
9371 ast_mutex_unlock(&p->
lock);
9378 if (p->mfcr2 && !p->mfcr2_call_accepted) {
9379 ast_mutex_unlock(&p->
lock);
9385 idx = dahdi_get_index(chan, p, 0);
9387 switch (condition) {
9389 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_BUSY);
9392 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_RINGTONE);
9396 ((p->
sig != SIG_FXSKS) &&
9397 (p->
sig != SIG_FXSLS) &&
9398 (p->
sig != SIG_FXSGS)))
9403 ast_debug(1,
"Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9408 ast_debug(1,
"Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9413 ast_debug(1,
"Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9419 switch (ast_channel_hangupcause(chan)) {
9420 case AST_CAUSE_USER_BUSY:
9421 case AST_CAUSE_NORMAL_CLEARING:
9424 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
9438 res = dahdi_set_hook(p->
subs[idx].dfd, DAHDI_OFFHOOK);
9443 res = dahdi_set_hook(p->
subs[idx].dfd, DAHDI_RINGOFF);
9448 if (ISTRUNK(p) && (p->
sig != SIG_PRI)) {
9450 p->
dop.dialstr[0] =
'\0';
9451 if ((ioctl(p->
subs[
SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9452 ast_log(LOG_WARNING,
"Unable to flash external trunk on channel %s: %s\n",
9453 ast_channel_name(chan), strerror(errno));
9463 res = tone_zone_play_tone(p->
subs[idx].dfd, -1);
9469 ast_mutex_unlock(&p->
lock);
9473 #if defined(HAVE_PRI)
9474 static struct ast_str *create_channel_name(
struct dahdi_pvt *i,
int is_outgoing,
char *address)
9486 if (i->
channel == CHAN_PSEUDO) {
9487 ast_str_set(&chan_name, 0,
"pseudo-%ld", ast_random());
9488 #if defined(HAVE_PRI)
9489 }
else if (i->pri) {
9490 ast_mutex_lock(&i->pri->
lock);
9493 ast_str_set(&chan_name, 0,
"i%d/%s-%x", i->pri->
span, address, (
unsigned)y);
9503 ast_mutex_unlock(&i->pri->
lock);
9509 for (x = 0; x < 3; ++x) {
9511 ast_channel_name(i->
subs[x].owner) + 6)) {
9521 static struct ast_channel *dahdi_new_callid_clean(
struct dahdi_pvt *i,
int state,
int startpbx,
int idx,
int law,
const struct ast_assigned_ids *assignedids,
const struct ast_channel *requestor, ast_callid callid,
int callid_created)
9523 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9542 if (i->
subs[idx].owner) {
9543 ast_log(LOG_WARNING,
"Channel %d already has a %s call\n", i->
channel,subnames[idx]);
9547 #if defined(HAVE_PRI)
9552 chan_name = create_channel_name(i, i->
outgoing, i->
dnid);
9554 chan_name = create_channel_name(i);
9562 ast_free(chan_name);
9566 tmp =
ast_channel_alloc(0, state, i->
cid_num, i->
cid_name, i->
accountcode, i->
exten, i->
context, assignedids, requestor, i->
amaflags,
"DAHDI/%s",
ast_str_buffer(chan_name));
9567 ast_free(chan_name);
9579 ast_channel_tech_set(tmp, &dahdi_tech);
9580 #if defined(HAVE_PRI)
9588 if (law == DAHDI_LAW_ALAW) {
9595 case SIG_PRI_LIB_HANDLE_CASES:
9598 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9612 ast_channel_nativeformats_set(tmp, caps);
9615 ast_channel_set_rawreadformat(tmp, deflaw);
9616 ast_channel_set_readformat(tmp, deflaw);
9617 ast_channel_set_rawwriteformat(tmp, deflaw);
9618 ast_channel_set_writeformat(tmp, deflaw);
9619 i->
subs[idx].linear = 0;
9620 dahdi_setlinear(i->
subs[idx].dfd, i->
subs[idx].linear);
9624 features |= DSP_FEATURE_BUSY_DETECT;
9625 if ((i->
callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
9626 features |= DSP_FEATURE_CALL_PROGRESS;
9631 features |= DSP_FEATURE_FAX_DETECT;
9633 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9634 if (ioctl(i->
subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9636 features |= DSP_FEATURE_DIGIT_DETECT;
9639 features |= DSP_FEATURE_DIGIT_DETECT;
9644 ast_debug(1,
"Already have a dsp on %s?\n", ast_channel_name(tmp));
9646 if (i->
channel != CHAN_PSEUDO)
9652 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9654 if (i->
outgoing && (dahdi_sig_pri_lib_handles(i->
sig) || (i->
sig == SIG_SS7))) {
9663 if (!ast_strlen_zero(progzone))
9676 ast_channel_rings_set(tmp, 1);
9677 ast_channel_tech_pvt_set(tmp, i);
9678 if ((i->
sig == SIG_FXOKS) || (i->
sig == SIG_FXOGS) || (i->
sig == SIG_FXOLS)) {
9686 ast_channel_parkinglot_set(tmp, i->
parkinglot);
9688 ast_channel_language_set(tmp, i->
language);
9695 i->
subs[idx].owner = tmp;
9696 ast_channel_context_set(tmp, i->
context);
9702 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
9703 if (!ast_strlen_zero(i->
exten))
9704 ast_channel_exten_set(tmp, i->
exten);
9705 if (!ast_strlen_zero(i->
rdnis)) {
9709 if (!ast_strlen_zero(i->
dnid)) {
9715 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9716 if (!ast_strlen_zero(i->
cid_ani)) {
9719 }
else if (!ast_strlen_zero(i->
cid_num)) {
9724 if (!ast_strlen_zero(i->
cid_num)) {
9737 dahdi_confmute(i, 0);
9743 ast_copy_string(device_name, ast_channel_name(tmp),
sizeof(device_name));
9744 dashptr = strrchr(device_name,
'-');
9751 for (v = i->
vars ; v ; v = v->
next)
9756 ast_channel_unlock(tmp);
9760 dahdi_ami_channel_event(i, tmp);
9768 ast_log(LOG_WARNING,
"Unable to start PBX on %s\n", ast_channel_name(tmp));
9777 static int my_getsigstr(
struct ast_channel *chan,
char *str,
const char *term,
int ms)
9791 if (strchr(term, c))
9796 static int dahdi_wink(
struct dahdi_pvt *p,
int idx)
9799 dahdi_set_hook(p->
subs[idx].dfd, DAHDI_WINK);
9803 j = DAHDI_IOMUX_SIGEVENT;
9805 if (ioctl(p->
subs[idx].dfd,DAHDI_IOMUX,&j) == -1)
return(-1);
9807 if (j & DAHDI_IOMUX_SIGEVENT)
break;
9810 if (ioctl(p->
subs[idx].dfd,DAHDI_GETEVENT,&j) == -1)
return(-1);
9814 static void publish_dnd_state(
int channel,
const char *status)
9845 if (dahdi_analog_lib_handles(dahdichan->
sig, dahdichan->
radio, dahdichan->
oprmode)) {
9846 return analog_dnd(dahdichan->sig_pvt, flag);
9850 return dahdichan->
dnd;
9854 dahdichan->
dnd = flag;
9855 ast_verb(3,
"%s DND on channel %d\n",
9856 flag?
"Enabled" :
"Disabled",
9858 publish_dnd_state(dahdichan->
channel, flag ?
"enabled" :
"disabled");
9862 static int canmatch_featurecode(
const char *pickupexten,
const char *exten)
9864 int extlen = strlen(exten);
9870 if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9874 if (exten[0] ==
'*' && extlen < 3) {
9889 static void *analog_ss_thread(
void *data)
9892 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9895 unsigned char buf[256];
9899 char *name = NULL, *
number = NULL;
9916 const char *pickupexten;
9918 ast_mutex_lock(&ss_thread_lock);
9920 ast_mutex_unlock(&ss_thread_lock);
9925 ast_log(LOG_WARNING,
"Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9929 ast_verb(3,
"Starting simple switch on '%s'\n", ast_channel_name(chan));
9930 idx = dahdi_get_index(chan, p, 1);
9932 ast_log(LOG_WARNING,
"Huh?\n");
9937 ast_channel_lock(chan);
9938 pickup_cfg = ast_get_chan_features_pickup_config(chan);
9940 ast_log(LOG_ERROR,
"Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9943 pickupexten =
ast_strdupa(pickup_cfg->pickupexten);
9945 ast_channel_unlock(chan);
9952 case SIG_FEATDMF_TA:
9954 case SIG_FGC_CAMAMF:
9958 case SIG_SF_FEATDMF:
9961 if (dahdi_wink(p, idx))
9968 res = tone_zone_play_tone(p->
subs[idx].dfd, -1);
9978 memset(dtmfbuf, 0,
sizeof(dtmfbuf));
9991 res = my_getsigstr(chan, dtmfbuf + 1,
"*", 3000);
9993 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf),
"*", 3000);
9996 case SIG_FEATDMF_TA:
9997 res = my_getsigstr(chan, dtmfbuf + 1,
"#", 3000);
9999 if (dahdi_wink(p, idx))
goto quit;
10003 if (res <= 0)
break;
10008 case SIG_FGC_CAMAMF:
10009 case SIG_SF_FEATDMF:
10010 res = my_getsigstr(chan, dtmfbuf + 1,
"#", 3000);
10012 if ((p->
sig == SIG_FEATDMF) && (dtmfbuf[1] !=
'0') && (strlen(dtmfbuf) != 14))
10014 if (dahdi_wink(p, idx))
goto quit;
10018 if (res <= 0)
break;
10020 res = my_getsigstr(chan, dtmfbuf + 1,
"#", 3000);
10024 if (p->
sig == SIG_E911)
10026 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf),
"#", 3000);
10032 res = my_getsigstr(chan, dtmfbuf + 1,
"#", 3000);
10041 res = my_getsigstr(chan, dtmfbuf + 1,
"*", 3000);
10043 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf),
"*", 3000);
10050 dtmfbuf[len] =
'\0';
10059 ast_debug(1,
"waitfordigit returned < 0...\n");
10063 dtmfbuf[len++] = res;
10064 dtmfbuf[len] =
'\0';
10073 ast_log(LOG_WARNING,
"getdtmf on channel %d: %s\n", p->
channel, strerror(errno));
10076 }
else if (res < 0) {
10077 ast_debug(1,
"Got hung up before digits finished\n");
10082 if (p->
sig == SIG_FGC_CAMA) {
10091 res = my_getsigstr(chan, anibuf,
"#", 10000);
10092 if ((res > 0) && (strlen(anibuf) > 2)) {
10093 if (anibuf[strlen(anibuf) - 1] ==
'#')
10094 anibuf[strlen(anibuf) - 1] = 0;
10101 if (ast_strlen_zero(exten))
10103 if (p->
sig == SIG_FEATD || p->
sig == SIG_EMWINK) {
10105 if (exten[0] ==
'*') {
10106 char *stringp=NULL;
10110 s1 = strsep(&stringp,
"*");
10111 s2 = strsep(&stringp,
"*");
10113 if (!ast_strlen_zero(p->
cid_num))
10120 }
else if (p->
sig == SIG_FEATD)
10121 ast_log(LOG_WARNING,
"Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->
channel);
10123 if ((p->
sig == SIG_FEATDMF) || (p->
sig == SIG_FEATDMF_TA)) {
10124 if (exten[0] ==
'*') {
10125 char *stringp=NULL;
10129 s1 = strsep(&stringp,
"#");
10130 s2 = strsep(&stringp,
"#");
10132 if (!ast_strlen_zero(p->
cid_num))
10141 ast_log(LOG_WARNING,
"Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->
channel);
10143 if ((p->
sig == SIG_E911) || (p->
sig == SIG_FGC_CAMAMF)) {
10144 if (exten[0] ==
'*') {
10145 char *stringp=NULL;
10149 s1 = strsep(&stringp,
"#");
10150 s2 = strsep(&stringp,
"#");
10151 if (s2 && (*(s2 + 1) ==
'0')) {
10158 ast_log(LOG_WARNING,
"Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->
channel);
10160 if (p->
sig == SIG_FEATB) {
10161 if (exten[0] ==
'*') {
10162 char *stringp=NULL;
10166 s1 = strsep(&stringp,
"#");
10169 ast_log(LOG_WARNING,
"Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->
channel);
10171 if ((p->
sig == SIG_FEATDMF) || (p->
sig == SIG_FEATDMF_TA)) {
10172 dahdi_wink(p, idx);
10181 dahdi_ec_enable(p);
10187 ast_dsp_free(p->
dsp);
10194 S_COR(ast_channel_caller(chan)->
id.number.valid, ast_channel_caller(chan)->
id.number.str, NULL))) {
10195 ast_channel_exten_set(chan, exten);
10199 ast_log(LOG_WARNING,
"PBX exited non-zero\n");
10200 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10204 ast_verb(2,
"Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10206 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_INFO);
10208 ast_log(LOG_WARNING,
"Unable to start special tone on %d\n", p->
channel);
10211 res =
ast_streamfile(chan,
"ss-noservice", ast_channel_language(chan));
10214 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10229 int is_exten_parking = 0;
10239 ast_debug(1,
"waitfordigit returned < 0...\n");
10240 res = tone_zone_play_tone(p->
subs[idx].dfd, -1);
10244 ast_debug(1,
"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10249 tone_zone_play_tone(p->
subs[idx].dfd, -1);
10251 tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALTONE);
10261 ast_verb(3,
"Setting call forward to '%s' on channel %d\n", p->
call_forward, p->
channel);
10262 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10266 res = tone_zone_play_tone(p->
subs[idx].dfd, -1);
10268 memset(exten, 0,
sizeof(exten));
10269 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALTONE);
10273 res = tone_zone_play_tone(p->
subs[idx].dfd, -1);
10274 ast_channel_lock(chan);
10275 ast_channel_exten_set(chan, exten);
10276 if (!ast_strlen_zero(p->
cid_num)) {
10282 if (!ast_strlen_zero(p->
cid_name)) {
10287 ast_channel_unlock(chan);
10288 dahdi_ec_enable(p);
10291 ast_log(LOG_WARNING,
"PBX exited non-zero\n");
10292 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10301 }
else if (res == 0) {
10302 ast_debug(1,
"not enough digits (and no ambiguous match)...\n");
10303 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10307 }
else if (p->
callwaiting && !strcmp(exten,
"*70")) {
10308 ast_verb(3,
"Disabling call waiting on %s\n", ast_channel_name(chan));
10311 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10313 ast_log(LOG_WARNING,
"Unable to do dial recall on channel %s: %s\n",
10314 ast_channel_name(chan), strerror(errno));
10317 ioctl(p->
subs[idx].dfd,DAHDI_CONFDIAG,&len);
10318 memset(exten, 0,
sizeof(exten));
10321 }
else if (!strcmp(exten, pickupexten)) {
10335 dahdi_ec_enable(p);
10337 ast_debug(1,
"No call pickup possible...\n");
10338 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10344 ast_log(LOG_WARNING,
"Huh? Got *8# on call not on real\n");
10349 }
else if (!p->
hidecallerid && !strcmp(exten,
"*67")) {
10350 ast_verb(3,
"Disabling Caller*ID on %s\n", ast_channel_name(chan));
10357 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10359 ast_log(LOG_WARNING,
"Unable to do dial recall on channel %s: %s\n",
10360 ast_channel_name(chan), strerror(errno));
10363 memset(exten, 0,
sizeof(exten));
10365 }
else if (p->
callreturn && !strcmp(exten,
"*69")) {
10366 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10368 }
else if (!strcmp(exten,
"*78")) {
10371 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10373 memset(exten, 0,
sizeof(exten));
10375 }
else if (!strcmp(exten,
"*79")) {
10378 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10380 memset(exten, 0,
sizeof(exten));
10383 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10385 memset(exten, 0,
sizeof(exten));
10388 ast_verb(3,
"Cancelling call forwarding on channel %d\n", p->
channel);
10389 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10392 memset(exten, 0,
sizeof(exten));
10405 if (bridge_channel) {
10411 ast_mutex_lock(&p->
lock);
10414 ast_mutex_unlock(&p->
lock);
10416 ast_verb(3,
"%s: Parked call\n", ast_channel_name(chan));
10424 }
else if (p->
hidecallerid && !strcmp(exten,
"*82")) {
10425 ast_verb(3,
"Enabling Caller*ID on %s\n", ast_channel_name(chan));
10429 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10431 ast_log(LOG_WARNING,
"Unable to do dial recall on channel %s: %s\n",
10432 ast_channel_name(chan), strerror(errno));
10435 memset(exten, 0,
sizeof(exten));
10437 }
else if (!strcmp(exten,
"*0")) {
10444 if (nbridge && bridged) {
10445 pbridge = ast_channel_tech_pvt(bridged);
10447 if (nbridge && pbridge &&
10450 ISTRUNK(pbridge)) {
10451 int func = DAHDI_FLASH;
10453 p->
dop.dialstr[0] =
'\0';
10455 if ((ioctl(pbridge->
subs[
SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10456 ast_log(LOG_WARNING,
"Unable to flash external trunk on channel %s: %s\n",
10457 ast_channel_name(nbridge), strerror(errno));
10466 tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
10468 tone_zone_play_tone(p->
subs[idx].dfd, -1);
10476 S_COR(ast_channel_caller(chan)->
id.number.valid, ast_channel_caller(chan)->
id.number.str, NULL))
10477 && !canmatch_featurecode(pickupexten, exten)) {
10478 ast_debug(1,
"Can't match %s from '%s' in context %s\n", exten,
10479 S_COR(ast_channel_caller(chan)->
id.number.valid, ast_channel_caller(chan)->
id.number.str,
"<Unknown Caller>"),
10480 ast_channel_context(chan));
10486 tone_zone_play_tone(p->
subs[idx].dfd, -1);
10496 if (smdi_msg != NULL) {
10497 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10499 if (smdi_msg->type ==
'B')
10501 else if (smdi_msg->type ==
'N')
10504 ast_debug(1,
"Received SMDI message on %s\n", ast_channel_name(chan));
10506 ast_log(LOG_WARNING,
"SMDI enabled but no SMDI message present\n");
10511 number = smdi_msg->calling_st;
10525 ast_debug(1,
"Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10526 dahdi_setlinear(p->
subs[idx].dfd, 0);
10533 ast_channel_lock(chan);
10535 ast_channel_unlock(chan);
10548 ast_log(LOG_WARNING,
"DTMFCID timed out waiting for ring. "
10549 "Exiting simple switch\n");
10557 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10568 ast_channel_lock(chan);
10570 ast_channel_unlock(chan);
10572 dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
10574 ast_debug(1,
"CID got string '%s'\n", dtmfbuf);
10576 ast_debug(1,
"CID is '%s', flags %d\n", dtmfcid, flags);
10578 if (!ast_strlen_zero(dtmfcid))
10587 struct timeval start;
10594 dahdi_setlinear(p->
subs[idx].dfd, 0);
10598 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10599 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_IOMUX, &i))) {
10600 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
10605 if (i & DAHDI_IOMUX_SIGEVENT) {
10607 ast_log(LOG_NOTICE,
"Got event %d (%s)...\n", res, event2str(res));
10608 if (res == DAHDI_EVENT_NOALARM) {
10613 if (res == DAHDI_EVENT_RINGBEGIN) {
10614 res = dahdi_set_hook(p->
subs[
SUB_REAL].dfd, DAHDI_OFFHOOK);
10621 }
else if (i & DAHDI_IOMUX_READ) {
10622 res = read(p->
subs[idx].dfd, buf,
sizeof(buf));
10624 if (errno != ELAST) {
10625 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
10644 ast_log(LOG_WARNING,
10645 "Failed to decode CallerID on channel '%s'\n",
10646 ast_channel_name(chan));
10650 else if (samples > (8000 * 10))
10656 ast_log(LOG_NOTICE,
"CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10660 res = dahdi_set_hook(p->
subs[
SUB_REAL].dfd, DAHDI_ONHOOK);
10673 ast_log(LOG_WARNING,
"CID timed out waiting for ring. "
10674 "Exiting simple switch\n");
10679 ast_log(LOG_WARNING,
"Hangup received waiting for ring. Exiting simple switch\n");
10695 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10696 curRingData[receivedRingT] = 0;
10703 ast_channel_context_set(chan, p->
defcontext);
10707 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10708 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_IOMUX, &i))) {
10709 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
10714 if (i & DAHDI_IOMUX_SIGEVENT) {
10716 ast_log(LOG_NOTICE,
"Got event %d (%s)...\n", res, event2str(res));
10717 if (res == DAHDI_EVENT_NOALARM) {
10723 curRingData[receivedRingT] = p->
ringt;
10729 if (++receivedRingT == ARRAY_LEN(curRingData))
10731 }
else if (i & DAHDI_IOMUX_READ) {
10732 res = read(p->
subs[idx].dfd, buf,
sizeof(buf));
10734 if (errno != ELAST) {
10735 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
10742 if (p->
ringt > 0) {
10743 if (!(--p->
ringt)) {
10751 ast_verb(3,
"Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10752 for (counter = 0; counter < 3; counter++) {
10756 for (counter1 = 0; counter1 < 3; counter1++) {
10757 ast_verb(3,
"Ring pattern check range: %d\n", p->
drings.ringnum[counter].range);
10758 if (p->
drings.ringnum[counter].ring[counter1] == -1) {
10759 ast_verb(3,
"Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10760 curRingData[counter1]);
10762 }
else if (curRingData[counter1] <= (p->
drings.ringnum[counter].ring[counter1] + p->
drings.ringnum[counter].range) &&
10763 curRingData[counter1] >= (p->
drings.ringnum[counter].ring[counter1] - p->
drings.ringnum[counter].range)) {
10764 ast_verb(3,
"Ring pattern matched in range: %d to %d\n",
10765 (p->
drings.ringnum[counter].ring[counter1] - p->
drings.ringnum[counter].range),
10766 (p->
drings.ringnum[counter].ring[counter1] + p->
drings.ringnum[counter].range));
10771 if (distMatches == 3) {
10774 ast_channel_context_set(chan,
S_OR(p->
drings.ringContext[counter].contextData, p->
defcontext));
10775 ast_verb(3,
"Distinctive Ring matched context %s\n",p->
context);
10781 dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
10786 ast_log(LOG_WARNING,
"Unable to get caller ID space\n");
10788 ast_log(LOG_WARNING,
"Channel %s in prering "
10789 "state, but I have nothing to do. "
10790 "Terminating simple switch, should be "
10791 "restarted by the actual ring.\n",
10792 ast_channel_name(chan));
10800 struct timeval start;
10803 dahdi_setlinear(p->
subs[idx].dfd, 0);
10812 ast_log(LOG_WARNING,
"DTMFCID timed out waiting for ring. "
10813 "Exiting simple switch\n");
10834 dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
10837 ast_debug(1,
"CID is '%s', flags %d\n",
10840 if (!ast_strlen_zero(dtmfcid))
10856 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10857 curRingData[receivedRingT] = 0;
10864 ast_channel_context_set(chan, p->
defcontext);
10868 dahdi_setlinear(p->
subs[idx].dfd, 0);
10870 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10871 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_IOMUX, &i))) {
10872 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
10877 if (i & DAHDI_IOMUX_SIGEVENT) {
10879 ast_log(LOG_NOTICE,
"Got event %d (%s)...\n", res, event2str(res));
10880 if (res == DAHDI_EVENT_NOALARM) {
10885 ast_debug(1,
"Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->
channel);
10894 curRingData[receivedRingT] = p->
ringt;
10900 if (++receivedRingT == ARRAY_LEN(curRingData))
10902 }
else if (i & DAHDI_IOMUX_READ) {
10903 res = read(p->
subs[idx].dfd, buf,
sizeof(buf));
10905 if (errno != ELAST) {
10906 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
10913 if (p->
ringt > 0) {
10914 if (!(--p->
ringt)) {
10926 ast_log(LOG_WARNING,
10927 "Failed to decode CallerID on channel '%s'\n",
10928 ast_channel_name(chan));
10932 else if (samples > (8000 * 10))
10938 ast_debug(1,
"CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10940 if (distinctiveringaftercid == 1) {
10942 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10943 curRingData[receivedRingT] = 0;
10946 ast_verb(3,
"Detecting post-CID distinctive ring\n");
10948 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10949 if ((res = ioctl(p->
subs[idx].dfd, DAHDI_IOMUX, &i))) {
10950 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
10955 if (i & DAHDI_IOMUX_SIGEVENT) {
10957 ast_log(LOG_NOTICE,
"Got event %d (%s)...\n", res, event2str(res));
10958 if (res == DAHDI_EVENT_NOALARM) {
10964 curRingData[receivedRingT] = p->
ringt;
10970 if (++receivedRingT == ARRAY_LEN(curRingData))
10972 }
else if (i & DAHDI_IOMUX_READ) {
10973 res = read(p->
subs[idx].dfd, buf,
sizeof(buf));
10975 if (errno != ELAST) {
10976 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
10983 if (p->
ringt > 0) {
10984 if (!(--p->
ringt)) {
10994 ast_verb(3,
"Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10996 for (counter = 0; counter < 3; counter++) {
11000 ast_verb(3,
"Checking %d,%d,%d\n",
11001 p->
drings.ringnum[counter].ring[0],
11002 p->
drings.ringnum[counter].ring[1],
11003 p->
drings.ringnum[counter].ring[2]);
11005 for (counter1 = 0; counter1 < 3; counter1++) {
11006 ast_verb(3,
"Ring pattern check range: %d\n", p->
drings.ringnum[counter].range);
11007 if (p->
drings.ringnum[counter].ring[counter1] == -1) {
11008 ast_verb(3,
"Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11009 curRingData[counter1]);
11012 else if (curRingData[counter1] <= (p->
drings.ringnum[counter].ring[counter1] + p->
drings.ringnum[counter].range) &&
11013 curRingData[counter1] >= (p->
drings.ringnum[counter].ring[counter1] - p->
drings.ringnum[counter].range)) {
11014 ast_verb(3,
"Ring pattern matched in range: %d to %d\n",
11015 (p->
drings.ringnum[counter].ring[counter1] - p->
drings.ringnum[counter].range),
11016 (p->
drings.ringnum[counter].ring[counter1] + p->
drings.ringnum[counter].range));
11020 if (distMatches == 3) {
11023 ast_channel_context_set(chan,
S_OR(p->
drings.ringContext[counter].contextData, p->
defcontext));
11024 ast_verb(3,
"Distinctive Ring matched context %s\n",p->
context);
11030 dahdi_setlinear(p->
subs[idx].dfd, p->
subs[idx].linear);
11035 ast_log(LOG_WARNING,
"CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11038 ast_log(LOG_WARNING,
"Unable to get caller ID space\n");
11047 ao2_cleanup(smdi_msg);
11052 my_handle_notify_message(chan, p, flags, -1);
11054 ast_channel_lock(chan);
11056 ast_channel_rings_set(chan, 1);
11057 ast_channel_unlock(chan);
11062 ast_log(LOG_WARNING,
"PBX exited non-zero\n");
11066 ast_log(LOG_WARNING,
"Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->
sig), p->
channel);
11067 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
11069 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", p->
channel);
11071 res = tone_zone_play_tone(p->
subs[idx].dfd, DAHDI_TONE_CONGESTION);
11073 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", p->
channel);
11076 ast_mutex_lock(&ss_thread_lock);
11078 ast_cond_signal(&ss_thread_complete);
11079 ast_mutex_unlock(&ss_thread_lock);
11089 static int calc_energy(
const unsigned char *buf,
int len,
struct ast_format *law)
11097 for (x = 0; x < len; x++)
11098 sum += abs(law ==
ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11103 static void *mwi_thread(
void *data)
11107 pthread_t threadid;
11109 char *name, *number;
11112 unsigned int spill_done = 0;
11113 int spill_result = -1;
11116 goto quit_no_clean;
11121 bump_gains(mtd->pvt);
11124 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11125 if ((res = ioctl(mtd->pvt->
subs[
SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11126 ast_log(LOG_WARNING,
"I/O MUX failed: %s\n", strerror(errno));
11130 if (i & DAHDI_IOMUX_SIGEVENT) {
11132 ast_callid callid = 0;
11133 int callid_created;
11141 case DAHDI_EVENT_NEONMWI_ACTIVE:
11142 case DAHDI_EVENT_NEONMWI_INACTIVE:
11143 case DAHDI_EVENT_NONE:
11144 case DAHDI_EVENT_BITSCHANGED:
11146 case DAHDI_EVENT_NOALARM:
11147 if (dahdi_analog_lib_handles(mtd->pvt->
sig, mtd->pvt->
radio, mtd->pvt->
oprmode)) {
11148 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11150 analog_p->inalarm = 0;
11153 handle_clear_alarms(mtd->pvt);
11155 case DAHDI_EVENT_ALARM:
11156 if (dahdi_analog_lib_handles(mtd->pvt->
sig, mtd->pvt->
radio, mtd->pvt->
oprmode)) {
11157 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11159 analog_p->inalarm = 1;
11163 handle_alarms(mtd->pvt, res);
11167 ast_log(LOG_NOTICE,
"Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11170 restore_gains(mtd->pvt);
11176 if (dahdi_analog_lib_handles(mtd->pvt->
sig, mtd->pvt->
radio, mtd->pvt->
oprmode)) {
11177 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11179 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11182 ast_log(LOG_WARNING,
"Unable to start simple switch thread on channel %d\n", mtd->pvt->
channel);
11183 res = tone_zone_play_tone(mtd->pvt->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11185 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", mtd->pvt->
channel);
11189 ast_log(LOG_WARNING,
"Could not create channel to handle call\n");
11193 goto quit_no_clean;
11195 }
else if (i & DAHDI_IOMUX_READ) {
11196 if ((res = read(mtd->pvt->
subs[
SUB_REAL].dfd, mtd->buf,
sizeof(mtd->buf))) < 0) {
11197 if (errno != ELAST) {
11198 ast_log(LOG_WARNING,
"read returned error: %s\n", strerror(errno));
11205 if ((spill_result =
callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11210 ast_log(LOG_WARNING,
"Failed to decode CallerID\n");
11212 }
else if (spill_result) {
11219 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11222 if (samples > (8000 * 4))
11227 if (spill_result == 1) {
11229 if (flags & CID_MSGWAITING) {
11230 ast_log(LOG_NOTICE,
"mwi: Have Messages on channel %d\n", mtd->pvt->
channel);
11232 }
else if (flags & CID_NOMSGWAITING) {
11233 ast_log(LOG_NOTICE,
"mwi: No Messages on channel %d\n", mtd->pvt->
channel);
11236 ast_log(LOG_NOTICE,
"mwi: Status unknown on channel %d\n", mtd->pvt->
channel);
11244 restore_gains(mtd->pvt);
11260 static int mwi_send_init(
struct dahdi_pvt * pvt)
11264 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11267 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11269 }
else if (pvt->mwisend_fsk) {
11270 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11277 if (mwisend_rpas) {
11278 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11280 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11286 ast_log(LOG_WARNING,
"cidspill already exists when trying to send FSK MWI\n");
11297 x = DAHDI_FLUSH_BOTH;
11300 ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11301 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11302 if (pvt->mwisend_fsk) {
11307 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11313 static int mwi_send_process_buffer(
struct dahdi_pvt * pvt,
int num_read)
11315 struct timeval now;
11321 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->
cidspill) {
11322 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11323 }
else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11325 switch ( pvt->mwisend_data.mwisend_current) {
11328 res = ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11330 ast_log(LOG_WARNING,
"Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11333 res = dahdi_set_hook(pvt->
subs[
SUB_REAL].dfd, DAHDI_RING);
11334 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11336 case MWI_SEND_SA_WAIT:
11338 case MWI_SEND_PAUSE:
11339 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11340 if (pvt->mwisend_fsk) {
11342 gettimeofday(&now, NULL);
11343 if ((
int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (
int)now.tv_usec - (
int)pvt->mwisend_data.pause.tv_usec > 500000) {
11344 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11346 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11348 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11352 case MWI_SEND_SPILL:
11354 if (0 < num_read) {
11362 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11365 ast_log(LOG_WARNING,
"MWI FSK Send Write failed: %s\n", strerror(errno));
11370 case MWI_SEND_CLEANUP:
11372 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11380 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11401 static int mwi_send_process_event(
struct dahdi_pvt * pvt,
int event)
11405 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11407 case DAHDI_EVENT_RINGEROFF:
11408 if (pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11411 if (dahdi_set_hook(pvt->
subs[
SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11412 ast_log(LOG_WARNING,
"Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11415 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11418 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11419 gettimeofday(&pvt->mwisend_data.pause, NULL);
11424 case DAHDI_EVENT_RINGOFFHOOK:
11431 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11434 case DAHDI_EVENT_RINGERON:
11435 case DAHDI_EVENT_HOOKCOMPLETE:
11445 static void dahdi_destroy_channel_range(
int start,
int end)
11449 int destroyed_first = 0;
11450 int destroyed_last = 0;
11452 ast_mutex_lock(&
iflock);
11453 ast_debug(1,
"range: %d-%d\n", start, end);
11454 for (cur = iflist; cur; cur =
next) {
11457 int x = DAHDI_FLASH;
11459 if (cur->
channel > destroyed_last) {
11460 destroyed_last = cur->
channel;
11462 if (destroyed_first < 1 || cur->channel < destroyed_first) {
11463 destroyed_first = cur->
channel;
11469 destroy_channel(cur, 1);
11473 ast_mutex_unlock(&
iflock);
11474 if (destroyed_first > start || destroyed_last < end) {
11475 ast_debug(1,
"Asked to destroy %d-%d, destroyed %d-%d,\n",
11476 start, end, destroyed_first, destroyed_last);
11481 static void dahdi_r2_destroy_nodev(
void)
11483 struct r2link_entry *cur;
11487 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11488 ast_debug(3,
"About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11489 for (i = 0; i < r2->numchans; i++) {
11496 ast_debug(3,
"About to destroy B-channel %d.\n", channel);
11497 dahdi_destroy_channel_range(channel, channel);
11501 if (r2->r2master != AST_PTHREADT_NULL) {
11502 pthread_cancel(r2->r2master);
11503 pthread_join(r2->r2master, NULL);
11504 r2->r2master = AST_PTHREADT_NULL;
11505 openr2_context_delete(r2->protocol_context);
11514 static int setup_dahdi(
int reload);
11527 static int dahdi_create_channel_range(
int start,
int end)
11533 int ret = RESULT_FAILURE;
11535 ast_debug(1,
"channel range caps: %d - %d\n", start, end);
11536 ast_mutex_lock(&
iflock);
11537 for (cur = iflist; cur; cur = cur->
next) {
11540 "channel range %d-%d is occupied\n",
11548 for (x = 0; x < NUM_SPANS; x++) {
11551 if (!pris[x].pri.pvts[0]) {
11560 if (!pri->pri.
fds[i]) {
11563 if (channo >= start && channo <= end) {
11565 "channel range %d-%d is occupied by span %d\n",
11566 start, end, x + 1);
11573 if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11574 !conf.chan.cc_params) {
11583 if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11584 ret = RESULT_SUCCESS;
11590 ast_mutex_unlock(&
iflock);
11598 pthread_t threadid;
11600 ast_callid callid = 0;
11601 int callid_created;
11606 case DAHDI_EVENT_NONE:
11607 case DAHDI_EVENT_BITSCHANGED:
11609 case DAHDI_EVENT_WINKFLASH:
11610 case DAHDI_EVENT_RINGOFFHOOK:
11612 if (i->
radio)
break;
11618 res = dahdi_set_hook(i->
subs[
SUB_REAL].dfd, DAHDI_OFFHOOK);
11619 if (res && (errno == EBUSY)) {
11628 restore_conference(i);
11631 dahdi_ec_enable(i);
11633 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11636 ast_log(LOG_WARNING,
"Unable to start PBX on channel %d\n", i->
channel);
11637 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11639 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", i->
channel);
11646 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11648 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11650 ast_log(LOG_WARNING,
"Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->
channel);
11651 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11652 ast_log(LOG_WARNING,
"Unable to start simple switch thread on channel %d\n", i->
channel);
11653 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11655 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", i->
channel);
11659 ast_log(LOG_WARNING,
"Unable to create channel\n");
11672 case SIG_FEATDMF_TA:
11675 case SIG_FGC_CAMAMF:
11681 case SIG_SF_FEATDMF:
11686 if (i->
cid_start == CID_START_POLARITY_IN) {
11693 ast_log(LOG_WARNING,
"Cannot allocate new structure on channel %d\n", i->
channel);
11694 }
else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11695 ast_log(LOG_WARNING,
"Unable to start simple switch thread on channel %d\n", i->
channel);
11696 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11698 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", i->
channel);
11706 ast_log(LOG_WARNING,
"Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->
sig), i->
channel);
11707 res = tone_zone_play_tone(i->
subs[
SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11709 ast_log(LOG_WARNING,
"Unable to play congestion tone on channel %d\n", i->
channel);
11713 case DAHDI_EVENT_NOALARM:
11715 #if defined(HAVE_PRI)
11716 case SIG_PRI_LIB_HANDLE_CASES:
11717 ast_mutex_lock(&i->
lock);
11719 ast_mutex_unlock(&i->
lock);
11722 #if defined(HAVE_SS7)
11724 sig_ss7_set_alarm(i->sig_pvt, 0);
11731 handle_clear_alarms(i);
11733 case DAHDI_EVENT_ALARM:
11735 #if defined(HAVE_PRI)
11736 case SIG_PRI_LIB_HANDLE_CASES:
11737 ast_mutex_lock(&i->
lock);
11739 ast_mutex_unlock(&i->
lock);
11742 #if defined(HAVE_SS7)
11744 sig_ss7_set_alarm(i->sig_pvt, 1);
11752 handle_alarms(i, res);
11754 case DAHDI_EVENT_ONHOOK:
11763 case SIG_FEATDMF_TA:
11766 case SIG_FGC_CAMAMF:
11772 case SIG_SF_FEATDMF:
11780 dahdi_ec_disable(i);
11790 case SIG_PRI_LIB_HANDLE_CASES:
11791 dahdi_ec_disable(i);
11795 ast_log(LOG_WARNING,
"Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->
sig), i->
channel);
11800 case DAHDI_EVENT_POLARITY:
11814 ast_verb(2,
"Starting post polarity "
11815 "CID detection on channel %d\n",
11819 ast_log(LOG_WARNING,
"Cannot allocate new structure on channel %d\n", i->
channel);
11820 }
else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11821 ast_log(LOG_WARNING,
"Unable to start simple switch thread on channel %d\n", i->
channel);
11828 ast_log(LOG_WARNING,
"handle_init_event detected "
11829 "polarity reversal on non-FXO (SIG_FXS) "
11830 "interface %d\n", i->
channel);
11833 case DAHDI_EVENT_REMOVED:
11834 ast_log(LOG_NOTICE,
11835 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11838 case DAHDI_EVENT_NEONMWI_ACTIVE:
11841 ast_log(LOG_NOTICE,
"NEON MWI set for channel %d, mailbox %s \n", i->
channel, i->
mailbox);
11844 case DAHDI_EVENT_NEONMWI_INACTIVE:
11847 ast_log(LOG_NOTICE,
"NEON MWI cleared for channel %d, mailbox %s\n", i->
channel, i->
mailbox);
11854 static void monitor_pfds_clean(
void *arg) {
11855 struct pollfd **pfds = arg;
11859 static void *do_monitor(
void *data)
11861 int count, res, res2, spoint, pollres=0;
11865 time_t thispass = 0, lastpass = 0;
11868 struct pollfd *pfds=NULL;
11869 int lastalloc = -1;
11874 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11875 ast_log(LOG_WARNING,
"Unable to set cancel type to asynchronous\n");
11880 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11882 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11885 ast_mutex_lock(&
iflock);
11886 if (!pfds || (lastalloc != ifcount)) {
11892 if (!(pfds =
ast_calloc(1, ifcount *
sizeof(*pfds)))) {
11893 ast_mutex_unlock(&
iflock);
11897 lastalloc = ifcount;
11902 for (i = iflist; i; i = i->
next) {
11903 ast_mutex_lock(&i->
lock);
11909 ast_log(LOG_ERROR,
"No sig_pvt?\n");
11913 pfds[count].events = POLLPRI;
11914 pfds[count].revents = 0;
11917 (i->
cid_start == CID_START_DTMF_NOALERT && (i->
sig == SIG_FXSLS || i->
sig == SIG_FXSGS || i->
sig == SIG_FXSKS))) {
11918 pfds[count].events |= POLLIN;
11926 pfds[count].events = POLLPRI;
11927 pfds[count].revents = 0;
11931 (i->
cid_start == CID_START_DTMF_NOALERT && (i->
sig == SIG_FXSLS || i->
sig == SIG_FXSGS || i->
sig == SIG_FXSKS))) {
11932 pfds[count].events |= POLLIN;
11938 ast_mutex_unlock(&i->
lock);
11941 ast_mutex_unlock(&
iflock);
11943 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11944 pthread_testcancel();
11946 res = poll(pfds, count, 1000);
11947 pthread_testcancel();
11948 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11952 if ((errno != EAGAIN) && (errno != EINTR))
11953 ast_log(LOG_WARNING,
"poll return %d: %s\n", res, strerror(errno));
11958 ast_mutex_lock(&
iflock);
11961 lastpass = thispass;
11962 thispass = time(NULL);
11964 for (i = iflist;; i = i->
next) {
11973 if (thispass != lastpass) {
11974 if (!found && ((i == last) || ((i == iflist) && !last))) {
11977 struct analog_pvt *analog_p = last->sig_pvt;
11981 && (last->
sig & __DAHDI_SIG_FXO)
11982 && !analog_p->fxsoffhookstate
11986 && (thispass - analog_p->onhooktime > 3)) {
11990 res2 = ioctl(last->
subs[
SUB_REAL].dfd, DAHDI_VMWI, &res);
11993 ast_debug(3,
"Unable to control message waiting led on channel %d: %s\n", last->
channel, strerror(errno));
11996 if (mwi_send_init(last)) {
11997 ast_log(LOG_WARNING,
"Unable to initiate mwi send sequence on channel %d\n", last->
channel);
12013 ast_debug(1,
"Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->
channel);
12015 ast_mutex_unlock(&
iflock);
12017 doomed = (
struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12019 doomed = handle_init_event(i, res);
12020 ast_mutex_lock(&
iflock);
12025 if (pollres & POLLIN) {
12030 ast_log(LOG_WARNING,
"Whoa.... I'm owned but found (%d) in read...\n", i->
subs[
SUB_REAL].dfd);
12034 ast_log(LOG_WARNING,
"Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->
subs[
SUB_REAL].dfd);
12040 if (calc_energy((
unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12041 pthread_attr_t attr;
12042 pthread_t threadid;
12045 pthread_attr_init(&attr);
12046 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12051 memcpy(mtd->buf, buf, res);
12054 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12055 ast_log(LOG_WARNING,
"Unable to start mwi thread on channel %d\n", i->
channel);
12062 }
else if (i->
cid_start == CID_START_DTMF_NOALERT) {
12064 struct timeval now;
12072 gettimeofday(&now, NULL);
12077 energy = calc_energy((
unsigned char *) buf, res, AST_LAW(i));
12079 pthread_t threadid;
12081 ast_mutex_unlock(&
iflock);
12084 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
12087 ast_callid callid = 0;
12091 ast_log(LOG_WARNING,
"Cannot allocate new structure on channel %d\n", i->
channel);
12093 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12095 ast_log(LOG_WARNING,
"Unable to start simple switch thread on channel %d\n", i->
channel);
12103 ast_mutex_lock(&
iflock);
12108 mwi_send_process_buffer(i, res);
12111 ast_log(LOG_WARNING,
"Read failed with %d: %s\n", res, strerror(errno));
12114 if (pollres & POLLPRI) {
12119 ast_log(LOG_WARNING,
"Whoa.... I'm owned but found (%d)...\n", i->
subs[
SUB_REAL].dfd);
12123 ast_debug(1,
"Monitor doohicky got event %s on channel %d\n", event2str(res), i->
channel);
12125 ast_mutex_unlock(&
iflock);
12126 if (0 == i->
mwisendactive || 0 == mwi_send_process_event(i, res)) {
12128 doomed = (
struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12130 doomed = handle_init_event(i, res);
12140 if (!my_is_off_hook(i)) {
12141 ast_debug(1,
"Woah! Went back on hook before reoriginate could happen on channel %d\n", i->
channel);
12143 ast_verb(3,
"Automatic reorigination on channel %d\n", i->
channel);
12144 res = DAHDI_EVENT_RINGOFFHOOK;
12146 doomed = (
struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12148 doomed = handle_init_event(i, res);
12152 ast_mutex_lock(&
iflock);
12156 ast_mutex_unlock(&
iflock);
12157 release_doomed_pris();
12159 dahdi_r2_destroy_nodev();
12163 pthread_cleanup_pop(1);
12168 static int restart_monitor(
void)
12176 ast_log(LOG_WARNING,
"Cannot kill myself\n");
12184 if (ast_pthread_create_background(&
monitor_thread, NULL, do_monitor, NULL) < 0) {
12186 ast_log(LOG_ERROR,
"Unable to start monitor thread.\n");
12194 #if defined(HAVE_PRI)
12195 static int pri_resolve_span(
int *span,
int channel,
int offset,
struct dahdi_spaninfo *si)
12203 for (x = 0; x < NUM_SPANS; x++) {
12204 if (pris[x].pri.trunkgroup == trunkgroup) {
12209 ast_log(LOG_WARNING,
"Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12212 if (pris[*span].pri.trunkgroup) {
12213 ast_log(LOG_WARNING,
"Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
12215 }
else if (pris[*span].mastertrunkgroup) {
12216 ast_log(LOG_WARNING,
"Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12219 if (si->totalchans == 31) {
12222 }
else if (si->totalchans == 24) {
12225 }
else if (si->totalchans == 3) {
12229 ast_log(LOG_WARNING,
"Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
12240 #if defined(HAVE_PRI)
12241 static int pri_create_trunkgroup(
int trunkgroup,
int *channels)
12243 struct dahdi_spaninfo si;
12244 struct dahdi_params p;
12249 for (x = 0; x < NUM_SPANS; x++) {
12250 if (pris[x].pri.trunkgroup == trunkgroup) {
12251 ast_log(LOG_WARNING,
"Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12258 memset(&si, 0,
sizeof(si));
12259 memset(&p, 0,
sizeof(p));
12260 fd = open(
"/dev/dahdi/channel", O_RDWR);
12262 ast_log(LOG_WARNING,
"Failed to open channel: %s\n", strerror(errno));
12266 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12267 ast_log(LOG_WARNING,
"Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12271 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12272 ast_log(LOG_WARNING,
"Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12276 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12277 ast_log(LOG_WARNING,
"Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12281 span = p.spanno - 1;
12282 if (pris[span].pri.trunkgroup) {
12283 ast_log(LOG_WARNING,
"Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12287 if (pris[span].pri.pvts[0]) {
12288 ast_log(LOG_WARNING,
"Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12296 pris[ospan].
dchannels[y] = channels[y];
12297 pris[span].pri.
span = span + 1;
12304 #if defined(HAVE_PRI)
12305 static int pri_create_spanmap(
int span,
int trunkgroup,
int logicalspan)
12307 if (pris[span].mastertrunkgroup) {
12308 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);
12317 #if defined(HAVE_SS7)
12318 static unsigned int parse_pointcode(
const char *pcstring)
12320 unsigned int code1, code2, code3;
12323 numvals = sscanf(pcstring,
"%30d-%30d-%30d", &code1, &code2, &code3);
12327 return (code1 << 16) | (code2 << 8) | code3;
12333 #if defined(HAVE_SS7)
12334 static struct dahdi_ss7 * ss7_resolve_linkset(
int linkset)
12336 if ((linkset < 0) || (linkset >= NUM_SPANS))
12339 return &linksets[linkset - 1];
12344 static void dahdi_r2_destroy_links(
void)
12346 struct r2link_entry *cur;
12351 ast_debug(3,
"MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
12357 dahdi_r2_destroy_nodev();
12361 #define R2_LINK_CAPACITY 30
12362 static struct r2link_entry *dahdi_r2_get_link(
const struct dahdi_chan_conf *conf)
12364 struct r2link_entry *cur = NULL;
12372 if (memcmp(&conf->mfcr2, &cur->mfcr2.conf,
sizeof(conf->mfcr2))) {
12373 ast_debug(3,
"Need new R2 link because of: Configuration change\n");
12375 }
else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
12376 ast_debug(3,
"Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
12381 struct r2link_entry *tmp = NULL;
12382 int new_idx = r2links_count + 1;
12384 for (i = 1; i <= r2links_count; i++) {
12387 if (i == tmp->mfcr2.index) {
12399 ast_log(LOG_ERROR,
"Cannot allocate R2 link!\n");
12402 cur->mfcr2.index = new_idx;
12403 cur->mfcr2.r2master = AST_PTHREADT_NULL;
12405 ast_debug(3,
"Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12412 static int dahdi_r2_set_context(
struct dahdi_mfcr2 *r2_link,
const struct dahdi_chan_conf *conf)
12414 char tmplogdir[] =
"/tmp";
12415 char logdir[OR2_MAX_PATH];
12418 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12419 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12420 conf->mfcr2.max_dnis);
12421 if (!r2_link->protocol_context) {
12424 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12425 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12426 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12427 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12429 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12430 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12431 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12432 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12433 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12434 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12435 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12436 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12438 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12439 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12441 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12442 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12443 ast_log(LOG_ERROR,
"Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12446 snres = snprintf(logdir,
sizeof(logdir),
"%s/%s/%s", ast_config_AST_LOG_DIR,
"mfcr2", conf->mfcr2.logdir);
12447 if (snres >=
sizeof(logdir)) {
12448 ast_log(LOG_ERROR,
"MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12449 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12450 ast_log(LOG_ERROR,
"Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12453 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12454 ast_log(LOG_ERROR,
"Failed setting MFC/R2 log directory %s\n", logdir);
12458 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12459 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12460 ast_log(LOG_ERROR,
"Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12464 memcpy(&r2_link->conf, &conf->mfcr2,
sizeof(r2_link->conf));
12474 static int sigtype_to_signalling(
int sigtype)
12498 struct dahdi_bufferinfo bi;
12501 #if defined(HAVE_PRI)
12507 struct dahdi_params p;
12508 #if defined(HAVE_PRI)
12509 struct dahdi_spaninfo si;
12512 #if defined(HAVE_SS7)
12517 for (tmp = iflist; tmp; tmp = tmp->
next) {
12519 if (tmp->
channel == channel) {
12524 if (tmp->
channel > channel) {
12532 if (!here && reloading != 1) {
12538 if (!tmp->cc_params) {
12542 ast_mutex_init(&tmp->
lock);
12544 for (x = 0; x < 3; x++)
12545 tmp->
subs[x].dfd = -1;
12551 int chan_sig = conf->chan.
sig;
12554 if (reloading && tmp->
vars) {
12561 if ((channel != CHAN_PSEUDO)) {
12564 snprintf(fn,
sizeof(fn),
"%d", channel);
12568 while (tmp->
subs[
SUB_REAL].dfd < 0 && reloading == 2 && count < 1000 && errno != ENXIO) {
12575 ast_log(LOG_ERROR,
"Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->
channel, channel);
12576 destroy_dahdi_pvt(tmp);
12579 memset(&p, 0,
sizeof(p));
12580 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12582 ast_log(LOG_ERROR,
"Unable to get parameters: %s\n", strerror(errno));
12583 destroy_dahdi_pvt(tmp);
12587 chan_sig = sigtype_to_signalling(p.sigtype);
12588 if (p.sigtype != (chan_sig & 0x3ffff)) {
12589 ast_log(LOG_ERROR,
"Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
12590 destroy_dahdi_pvt(tmp);
12594 tmp->
law = p.curlaw;
12595 tmp->
span = p.spanno;
12596 #if defined(HAVE_PRI)
12597 span = p.spanno - 1;
12602 tmp->
sig = chan_sig;
12605 if (dahdi_analog_lib_handles(chan_sig, tmp->
radio, tmp->
oprmode)) {
12606 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12608 destroy_dahdi_pvt(tmp);
12611 tmp->sig_pvt = analog_p;
12613 #if defined(HAVE_SS7)
12614 if (chan_sig == SIG_SS7) {
12615 struct dahdi_ss7 *ss7;
12618 if (ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12619 ast_log(LOG_ERROR,
"Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12620 destroy_dahdi_pvt(tmp);
12624 ss7 = ss7_resolve_linkset(cur_linkset);
12626 ast_log(LOG_ERROR,
"Unable to find linkset %d\n", cur_linkset);
12627 destroy_dahdi_pvt(tmp);
12630 ss7->ss7.span = cur_linkset;
12631 if (cur_cicbeginswith < 0) {
12632 ast_log(LOG_ERROR,
"Need to set cicbeginswith for the channels!\n");
12633 destroy_dahdi_pvt(tmp);
12636 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12638 destroy_dahdi_pvt(tmp);
12641 tmp->sig_pvt = ss7_chan;
12642 tmp->ss7 = &ss7->ss7;
12645 ss7_chan->
cic = cur_cicbeginswith++;
12648 ss7_chan->
dpc = cur_defaultdpc;
12650 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12652 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix,
sizeof(ss7->ss7.internationalprefix));
12653 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix,
sizeof(ss7->ss7.nationalprefix));
12654 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix,
sizeof(ss7->ss7.subscriberprefix));
12655 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix,
sizeof(ss7->ss7.unknownprefix));
12656 ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix,
sizeof(ss7->ss7.networkroutedprefix));
12658 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12659 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12663 if (chan_sig == SIG_MFCR2) {
12664 struct dahdi_mfcr2 *r2_link;
12665 struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12666 r2_link = &r2_le->mfcr2;
12668 ast_log(LOG_WARNING,
"Cannot get another R2 DAHDI context!\n");
12669 destroy_dahdi_pvt(tmp);
12672 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12673 ast_log(LOG_ERROR,
"Cannot create OpenR2 protocol context.\n");
12674 destroy_dahdi_pvt(tmp);
12677 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12678 ast_log(LOG_ERROR,
"Cannot add more channels to this link!\n");
12679 destroy_dahdi_pvt(tmp);
12682 r2_link->pvts[r2_link->numchans++] = tmp;
12683 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12686 if (!tmp->r2chan) {
12687 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12688 ast_log(LOG_ERROR,
"Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12689 destroy_dahdi_pvt(tmp);
12692 r2_link->live_chans++;
12693 tmp->mfcr2 = r2_link;
12694 if (conf->mfcr2.call_files) {
12695 openr2_chan_enable_call_files(tmp->r2chan);
12697 openr2_chan_set_client_data(tmp->r2chan, tmp);
12699 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12700 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12701 tmp->mfcr2_category = conf->mfcr2.category;
12702 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12703 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12704 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12705 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12706 tmp->mfcr2call = 0;
12707 tmp->mfcr2_dnis_index = 0;
12708 tmp->mfcr2_ani_index = 0;
12712 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12716 int myswitchtype = 0;
12719 if (ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12720 ast_log(LOG_ERROR,
"Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12721 destroy_dahdi_pvt(tmp);
12724 if (span >= NUM_SPANS) {
12725 ast_log(LOG_ERROR,
"Channel %d does not lie on a span I know of (%d)\n", channel, span);
12726 destroy_dahdi_pvt(tmp);
12730 if (ioctl(tmp->
subs[
SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12731 ast_log(LOG_ERROR,
"Unable to get span status: %s\n", strerror(errno));
12732 destroy_dahdi_pvt(tmp);
12737 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12739 ast_log(LOG_WARNING,
"Channel %d: Unable to find locate channel/trunk group!\n", channel);
12740 destroy_dahdi_pvt(tmp);
12746 for (x = 0; x < NUM_SPANS; x++) {
12748 if (pris[x].dchannels[y] == tmp->
channel) {
12754 if (!matchesdchan) {
12755 if (pris[span].pri.nodetype && (pris[span].pri.
nodetype != conf->pri.pri.
nodetype)) {
12756 ast_log(LOG_ERROR,
"Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12757 destroy_dahdi_pvt(tmp);
12760 if (pris[span].pri.switchtype && (pris[span].pri.
switchtype != myswitchtype)) {
12761 ast_log(LOG_ERROR,
"Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12762 destroy_dahdi_pvt(tmp);
12765 if ((pris[span].pri.dialplan) && (pris[span].pri.
dialplan != conf->pri.pri.
dialplan)) {
12766 ast_log(LOG_ERROR,
"Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ?
"Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12767 destroy_dahdi_pvt(tmp);
12770 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.
idledial)) {
12771 ast_log(LOG_ERROR,
"Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.
idledial);
12772 destroy_dahdi_pvt(tmp);
12775 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.
idleext)) {
12776 ast_log(LOG_ERROR,
"Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.
idleext);
12777 destroy_dahdi_pvt(tmp);
12780 if (pris[span].pri.minunused && (pris[span].pri.
minunused != conf->pri.pri.
minunused)) {
12781 ast_log(LOG_ERROR,
"Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.
minunused);
12782 destroy_dahdi_pvt(tmp);
12785 if (pris[span].pri.minidle && (pris[span].pri.
minidle != conf->pri.pri.
minidle)) {
12786 ast_log(LOG_ERROR,
"Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.
minidle);
12787 destroy_dahdi_pvt(tmp);
12790 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12791 ast_log(LOG_ERROR,
"Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12792 pris[span].pri.trunkgroup);
12793 destroy_dahdi_pvt(tmp);
12797 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].
mastertrunkgroup);
12799 destroy_dahdi_pvt(tmp);
12802 tmp->sig_pvt = pri_chan;
12803 tmp->pri = &pris[span].pri;
12810 destroy_dahdi_pvt(tmp);
12815 conf->chan.cc_params);
12817 pris[span].pri.
sig = chan_sig;
12820 pris[span].pri.
nsf = conf->pri.pri.
nsf;
12824 pris[span].pri.
pvts[pris[span].pri.
numchans++] = tmp->sig_pvt;
12830 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12833 #ifdef HAVE_PRI_INBANDDISCONNECT
12836 #if defined(HAVE_PRI_CALL_HOLD)
12840 #if defined(HAVE_PRI_CCSS)
12848 #if defined(HAVE_PRI_CALL_WAITING)
12856 #if defined(HAVE_PRI_L2_PERSISTENCE)
12860 #if defined(HAVE_PRI_AOC_EVENTS)
12864 if (chan_sig == SIG_BRI_PTMP) {
12875 #if defined(HAVE_PRI_MWI)
12893 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12895 #if defined(HAVE_PRI_DISPLAY_TEXT)
12899 #if defined(HAVE_PRI_MCID)
12903 #if defined(HAVE_PRI_DATETIME_SEND)
12907 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12908 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12911 #if defined(HAVE_PRI_CALL_WAITING)
12913 pris[span].pri.ch_cfg.stripmsd = conf->chan.
stripmsd;
12914 pris[span].pri.ch_cfg.hidecallerid = conf->chan.
hidecallerid;
12921 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.
context,
sizeof(pris[span].pri.ch_cfg.context));
12925 ast_log(LOG_ERROR,
"Channel %d is reserved for D-channel.\n", p.chanpos);
12926 destroy_dahdi_pvt(tmp);
12934 ast_log(LOG_WARNING,
"Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->
channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->
sig));
12935 chan_sig = tmp->
sig;
12937 memset(&p, 0,
sizeof(p));
12938 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12942 switch (chan_sig) {
12950 case SIG_FEATDMF_TA:
12956 case SIG_FGC_CAMAMF:
12958 case SIG_SF_FEATDMF:
12966 p.channo = channel;
12970 p.debouncetime = 5;
12972 p.channo = channel;
12974 if (conf->timing.prewinktime >= 0)
12975 p.prewinktime = conf->timing.prewinktime;
12976 if (conf->timing.preflashtime >= 0)
12977 p.preflashtime = conf->timing.preflashtime;
12978 if (conf->timing.winktime >= 0)
12979 p.winktime = conf->timing.winktime;
12980 if (conf->timing.flashtime >= 0)
12981 p.flashtime = conf->timing.flashtime;
12982 if (conf->timing.starttime >= 0)
12983 p.starttime = conf->timing.starttime;
12984 if (conf->timing.rxwinktime >= 0)
12985 p.rxwinktime = conf->timing.rxwinktime;
12986 if (conf->timing.rxflashtime >= 0)
12987 p.rxflashtime = conf->timing.rxflashtime;
12988 if (conf->timing.debouncetime >= 0)
12989 p.debouncetime = conf->timing.debouncetime;
12995 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12997 ast_log(LOG_ERROR,
"Unable to set parameters: %s\n", strerror(errno));
12998 destroy_dahdi_pvt(tmp);
13004 memset(&bi, 0,
sizeof(bi));
13005 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13009 bi.numbufs = conf->chan.
buf_no;
13010 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13012 ast_log(LOG_WARNING,
"Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13015 ast_log(LOG_WARNING,
"Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13033 if (chan_sig & __DAHDI_SIG_FXS) {
13040 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13049 if (tmp->
drings.ringnum[0].range == 0)
13050 tmp->
drings.ringnum[0].range = 10;
13051 if (tmp->
drings.ringnum[1].range == 0)
13052 tmp->
drings.ringnum[1].range = 10;
13053 if (tmp->
drings.ringnum[2].range == 0)
13054 tmp->
drings.ringnum[2].range = 10;
13073 ast_log(LOG_NOTICE,
"echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13100 ast_log(LOG_NOTICE,
"Distinctive Ring detect requires 'usecallerid' be on\n");
13107 ast_log(LOG_WARNING,
"SMDI callerid requires SMDI to be enabled, enabling...\n");
13114 ast_log(LOG_ERROR,
"Invalid SMDI port specfied, disabling SMDI support\n");
13142 #if defined(HAVE_PRI)
13143 if (dahdi_sig_pri_lib_handles(tmp->
sig)) {
13152 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->
mailbox)) {
13159 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13161 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13172 if (conf->chan.
vars) {
13174 for (v = conf->chan.
vars ; v ; v = v->
next) {
13175 if ((tmpvar = ast_variable_new(v->
name, v->
value, v->
file))) {
13178 tmp->
vars = tmpvar;
13191 tmp->rxdrc = conf->chan.rxdrc;
13203 dahdi_conf_update(tmp);
13205 switch (chan_sig) {
13206 case SIG_PRI_LIB_HANDLE_CASES:
13212 dahdi_set_hook(tmp->
subs[
SUB_REAL].dfd, DAHDI_ONHOOK);
13217 if ((res =
get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13219 switch (tmp->
sig) {
13221 case SIG_PRI_LIB_HANDLE_CASES:
13222 sig_pri_set_alarm(tmp->sig_pvt, 1);
13225 #if defined(HAVE_SS7)
13227 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13232 analog_p = tmp->sig_pvt;
13234 analog_p->inalarm = 1;
13239 handle_alarms(tmp, res);
13256 switch (tmp->
sig) {
13257 #if defined(HAVE_PRI)
13258 case SIG_PRI_LIB_HANDLE_CASES:
13260 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13261 ((
struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13262 if (chan_sig == SIG_PRI) {
13263 char db_chan_name[20];
13270 snprintf(db_chan_name,
sizeof(db_chan_name),
"%s/%d:%d",
dahdi_db, tmp->
span, tmp->
channel);
13274 why = &((
struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13278 sscanf(db_answer,
"%1c:%30u", &state, why);
13291 #if defined(HAVE_SS7)
13294 if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
13306 switch (tmp->
sig) {
13307 #if defined(HAVE_PRI)
13308 case SIG_PRI_LIB_HANDLE_CASES:
13314 pri_chan->inalarm = tmp->
inalarm;
13320 sizeof(pri_chan->context));
13322 sizeof(pri_chan->mohinterpret));
13323 pri_chan->stripmsd = tmp->
stripmsd;
13327 #if defined(HAVE_SS7)
13341 sizeof(ss7_chan->context));
13343 sizeof(ss7_chan->mohinterpret));
13349 analog_p = tmp->sig_pvt;
13360 analog_p->callreturn = conf->chan.
callreturn;
13362 analog_p->canpark = conf->chan.
canpark;
13364 analog_p->immediate = conf->chan.
immediate;
13368 analog_p->pulse = conf->chan.
pulse;
13370 analog_p->transfer = conf->chan.
transfer;
13377 analog_p->outsigmod = ANALOG_SIG_NONE;
13380 analog_p->stripmsd = conf->chan.
stripmsd;
13382 case CID_START_POLARITY:
13383 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13385 case CID_START_POLARITY_IN:
13386 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13388 case CID_START_DTMF_NOALERT:
13389 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13392 analog_p->cid_start = ANALOG_CID_START_RING;
13396 analog_p->ringt = conf->chan.
ringt;
13398 analog_p->onhooktime = time(NULL);
13399 if (chan_sig & __DAHDI_SIG_FXO) {
13400 memset(&p, 0,
sizeof(p));
13401 res = ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13403 analog_p->fxsoffhookstate = p.rxisoffhook;
13405 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13415 analog_config_complete(analog_p);
13419 #if defined(HAVE_PRI)
13420 if (tmp->
channel == CHAN_PSEUDO) {
13432 if (tmp && !here) {
13434 dahdi_iflist_insert(tmp);
13439 static int is_group_or_channel_match(
struct dahdi_pvt *p,
int span, ast_group_t groupmatch,
int *groupmatched,
int channelmatch,
int *channelmatched)
13441 #if defined(HAVE_PRI)
13444 if (!p->pri || p->pri->
span != span) {
13447 if (!groupmatch && channelmatch == -1) {
13456 if ((p->
group & groupmatch) != groupmatch)
13462 if (channelmatch != -1) {
13463 if (p->
channel != channelmatch)
13466 *channelmatched = 1;
13472 static int available(
struct dahdi_pvt **pvt,
int is_specific_channel)
13480 return analog_available(p->sig_pvt);
13483 #if defined(HAVE_PRI)
13484 case SIG_PRI_LIB_HANDLE_CASES:
13489 pvt_chan = p->sig_pvt;
13490 res = sig_pri_available(&pvt_chan, is_specific_channel);
13495 #if defined(HAVE_SS7)
13497 return sig_ss7_available(p->sig_pvt);
13512 if (p->mfcr2call) {
13525 #if defined(HAVE_PRI)
13526 #if defined(HAVE_PRI_CALL_WAITING)
13537 static void my_pri_init_config(
void *priv,
struct sig_pri_span *pri)
13541 pvt->
stripmsd = pri->ch_cfg.stripmsd;
13555 #if defined(HAVE_PRI)
13568 static int dahdi_new_pri_nobch_channel(
struct sig_pri_span *pri)
13575 struct dahdi_bufferinfo bi;
13577 static int nobch_channel = CHAN_PSEUDO;
13580 for (pvt_idx = 0; pvt_idx < pri->
numchans; ++pvt_idx) {
13581 if (!pri->
pvts[pvt_idx]) {
13586 if (ARRAY_LEN(pri->
pvts) <= pvt_idx) {
13587 ast_log(LOG_ERROR,
"Unable to add a no-B-channel interface!\n");
13592 pri->
pvts[pvt_idx] = NULL;
13601 if (!pvt->cc_params) {
13605 ast_mutex_init(&pvt->
lock);
13606 for (idx = 0; idx < ARRAY_LEN(pvt->
subs); ++idx) {
13607 pvt->
subs[idx].dfd = -1;
13614 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13616 destroy_dahdi_pvt(pvt);
13631 pvt->sig_pvt = chan;
13632 pri->
pvts[pvt_idx] = chan;
13634 pvt->
subs[
SUB_REAL].dfd = dahdi_open(
"/dev/dahdi/pseudo");
13636 ast_log(LOG_ERROR,
"Unable to open no B channel interface pseudo channel: %s\n",
13638 destroy_dahdi_pvt(pvt);
13641 memset(&bi, 0,
sizeof(bi));
13642 res = ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13647 bi.numbufs = pvt->
buf_no;
13648 res = ioctl(pvt->
subs[
SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13650 ast_log(LOG_WARNING,
13651 "Unable to set buffer policy on no B channel interface: %s\n",
13655 ast_log(LOG_WARNING,
13656 "Unable to check buffer policy on no B channel interface: %s\n",
13660 if (CHAN_PSEUDO < nobch_channel) {
13661 nobch_channel = CHAN_PSEUDO - 1;
13663 pvt->
channel = nobch_channel;
13667 dahdi_nobch_insert(pri, pvt);
13681 struct dahdi_bufferinfo bi;
13692 if (!p->cc_params) {
13701 ast_mutex_init(&p->
lock);
13702 p->
subs[
SUB_REAL].dfd = dahdi_open(
"/dev/dahdi/pseudo");
13704 ast_log(LOG_ERROR,
"Unable to dup channel: %s\n", strerror(errno));
13705 destroy_dahdi_pvt(p);
13708 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13712 bi.numbufs = src->
buf_no;
13713 res = ioctl(p->
subs[
SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13715 ast_log(LOG_WARNING,
"Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13718 ast_log(LOG_WARNING,
"Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13720 dahdi_iflist_insert(p);
13749 char *subdir = NULL;
13783 ast_log(LOG_WARNING,
"Channel requested with no data\n");
13787 if (!args.argc || ast_strlen_zero(args.group)) {
13788 ast_log(LOG_WARNING,
"No channel/group specified\n");
13793 memset(param, 0,
sizeof(*param));
13796 if (strchr(args.group,
'!') != NULL) {
13797 char *
prev = args.group;
13798 while ((s = strchr(prev,
'!')) != NULL) {
13802 *(prev - 1) =
'\0';
13803 subdir = args.group;
13805 }
else if (args.group[0] ==
'i') {
13807 res = sscanf(args.group + 1,
"%30d", &x);
13809 ast_log(LOG_WARNING,
"Unable to determine ISDN span for data %s\n", data);
13815 s = strchr(args.group,
'-');
13820 args.group = s + 1;
13823 if (toupper(args.group[0]) ==
'G' || toupper(args.group[0])==
'R') {
13825 s = args.group + 1;
13826 res = sscanf(s,
"%30d%1c%30d", &x, ¶m->
opt, ¶m->
cadence);
13828 ast_log(LOG_WARNING,
"Unable to determine group for data %s\n", data);
13833 if (toupper(args.group[0]) ==
'G') {
13834 if (args.group[0] ==
'G') {
13840 if (ARRAY_LEN(round_robin) <= x) {
13841 ast_log(LOG_WARNING,
"Round robin index %d out of range for data %s\n",
13845 if (args.group[0] ==
'R') {
13847 p = round_robin[x] ? round_robin[x]->
prev :
ifend;
13851 p = round_robin[x] ? round_robin[x]->
next :
iflist;
13860 if (!strcasecmp(s,
"pseudo")) {
13865 res = sscanf(s,
"%30d%1c%30d", &x, ¶m->
opt, ¶m->
cadence);
13867 ast_log(LOG_WARNING,
"Unable to determine channel for data %s\n", data);
13874 char path[PATH_MAX];
13877 snprintf(path,
sizeof(path),
"/dev/dahdi/%s/%d",
13879 if (stat(path, &stbuf) < 0) {
13880 ast_log(LOG_WARNING,
"stat(%s) failed: %s\n",
13881 path, strerror(errno));
13884 if (!S_ISCHR(stbuf.st_mode)) {
13885 ast_log(LOG_ERROR,
"%s: Not a character device file\n",
13895 if (param->
opt ==
'r' && res < 3) {
13896 ast_log(LOG_WARNING,
"Distinctive ring missing identifier in '%s'\n", data);
13905 const char *data,
int *cause)
13911 int channelmatched = 0;
13912 int foundowner = 0;
13913 int groupmatched = 0;
13914 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13915 int transcapdigital = 0;
13918 ast_callid callid = 0;
13921 ast_mutex_lock(&
iflock);
13922 p = determine_starting_point(data, &start);
13925 ast_mutex_unlock(&
iflock);
13932 while (p && !tmp) {
13933 if (start.roundrobin)
13934 round_robin[start.rr_starting_point] = p;
13940 if (is_group_or_channel_match(p, start.
span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13941 && available(&p, channelmatched)) {
13944 callwait = (p->
owner != NULL);
13947 ast_mutex_lock(&p->
lock);
13948 if (p->mfcr2call) {
13949 ast_mutex_unlock(&p->
lock);
13950 ast_debug(1,
"Yay!, someone just beat us in the race for channel %d.\n", p->
channel);
13954 ast_mutex_unlock(&p->
lock);
13957 if (p->
channel == CHAN_PSEUDO) {
13958 p = duplicate_pseudo(p);
13966 switch (start.opt) {
13979 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13981 transcapdigital = AST_TRANS_CAP_DIGITAL;
13985 ast_log(LOG_WARNING,
"Unknown option '%c' in '%s'\n", start.opt, data);
13991 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13993 }
else if (dahdi_sig_pri_lib_handles(p->
sig)) {
13999 ast_mutex_lock(&p->
lock);
14000 ast_mutex_unlock(&p->
lock);
14004 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
14006 #if defined(HAVE_SS7)
14007 }
else if (p->
sig == SIG_SS7) {
14008 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
14015 #if defined(HAVE_PRI)
14017 case SIG_PRI_LIB_HANDLE_CASES:
14018 #if defined(HAVE_PRI_CALL_WAITING)
14019 if (((
struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14020 ((
struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14035 snprintf(p->dialstring,
sizeof(p->dialstring),
"DAHDI/%s", data);
14042 if (start.backwards) {
14055 ast_mutex_unlock(&
iflock);
14057 if (cause && !tmp) {
14058 if (callwait || (channelmatched && foundowner)) {
14059 *cause = AST_CAUSE_BUSY;
14060 }
else if (groupmatched) {
14061 *cause = AST_CAUSE_CONGESTION;
14084 static int dahdi_devicestate(
const char *data)
14086 #if defined(HAVE_PRI)
14087 const char *device;
14093 if (*device !=
'I') {
14097 res = sscanf(device,
"I%30u", &span);
14098 if (res != 1 || !span || NUM_SPANS < span) {
14102 device = strchr(device,
'/');
14112 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14114 if (!strcmp(device,
"congestion"))
14119 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14120 else if (!strcmp(device,
"threshold")) {
14121 return pris[span - 1].pri.threshold_devstate;
14151 int groupmatched = 0;
14152 int channelmatched = 0;
14154 ast_mutex_lock(&
iflock);
14155 p = determine_starting_point(dest, &start);
14157 ast_mutex_unlock(&
iflock);
14166 const char *monitor_type;
14173 case AST_CC_MONITOR_NATIVE:
14176 #if defined(HAVE_PRI)
14177 if (dahdi_sig_pri_lib_handles(p->
sig)) {
14182 snprintf(full_device_name,
sizeof(full_device_name),
14183 "DAHDI/I%d/congestion", p->pri->
span);
14187 #if defined(HAVE_PRI)
14188 device_name = create_channel_name(p, 1,
"");
14190 device_name = create_channel_name(p);
14192 snprintf(full_device_name,
sizeof(full_device_name),
"DAHDI/%s",
14194 ast_free(device_name);
14200 dash = strrchr(full_device_name,
'-');
14205 snprintf(dialstring,
sizeof(dialstring),
"DAHDI/%s", dest);
14215 #
if defined(HAVE_PRI)
14216 p->pri ? p->pri->
cc_params : p->cc_params,
14220 monitor_type, full_device_name, dialstring, NULL);
14228 if (p == exitpvt) {
14232 ast_mutex_unlock(&
iflock);
14236 #if defined(HAVE_SS7)
14237 static void dahdi_ss7_message(
struct ss7 *ss7,
char *s)
14242 for (i = 0; i < NUM_SPANS; i++) {
14243 if (linksets[i].ss7.ss7 == ss7) {
14244 ast_verbose_callid(0,
"[%d] %s", i + 1, s);
14249 ast_verbose_callid(0,
"%s", s);
14253 #if defined(HAVE_SS7)
14254 static void dahdi_ss7_error(
struct ss7 *ss7,
char *s)
14259 for (i = 0; i < NUM_SPANS; i++) {
14260 if (linksets[i].ss7.ss7 == ss7) {
14270 #if defined(HAVE_OPENR2)
14271 static void *mfcr2_monitor(
void *data)
14273 struct dahdi_mfcr2 *mfcr2 = data;
14281 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14291 for (i = 0; i < mfcr2->numchans; i++) {
14292 pvt = mfcr2->pvts[i];
14296 openr2_chan_set_idle(pvt->r2chan);
14297 openr2_chan_handle_cas(pvt->r2chan);
14303 for (i = 0; i < mfcr2->numchans; i++) {
14304 pollers[i].revents = 0;
14305 pollers[i].events = 0;
14306 pvt = mfcr2->pvts[i];
14313 if (mfcr2->nodev) {
14316 if (!pvt->r2chan) {
14321 openr2_chan_enable_read(pvt->r2chan);
14322 pollers[i].events = POLLIN | POLLPRI;
14329 if (pollsize == 0) {
14331 ast_debug(1,
"Monitor thread going idle since everybody has an owner\n");
14334 poll(NULL, 0, maxsleep);
14340 pthread_testcancel();
14341 res = poll(pollers, mfcr2->numchans, maxsleep);
14342 pthread_testcancel();
14343 if ((res < 0) && (errno != EINTR)) {
14344 ast_log(LOG_ERROR,
"going out, poll failed: %s\n", strerror(errno));
14348 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14349 for (i = 0; i < mfcr2->numchans; i++) {
14350 pvt = mfcr2->pvts[i];
14354 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14355 openr2_chan_process_event(pvt->r2chan);
14358 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14360 ast_log(LOG_NOTICE,
"Quitting MFC/R2 monitor thread\n");
14365 #if defined(HAVE_PRI)
14366 static void dahdi_pri_message(
struct pri *pri,
char *s)
14372 int dchancount = 0;
14375 for (x = 0; x < NUM_SPANS; x++) {
14377 if (pris[x].pri.dchans[y]) {
14381 if (pris[x].pri.dchans[y] == pri) {
14392 if (1 < dchancount) {
14393 ast_verbose_callid(0,
"[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14395 ast_verbose_callid(0,
"PRI Span: %d %s", span + 1, s);
14398 ast_verbose_callid(0,
"PRI Span: ? %s", s);
14401 ast_verbose_callid(0,
"PRI Span: ? %s", s);
14404 ast_mutex_lock(&pridebugfdlock);
14406 if (pridebugfd >= 0) {
14407 if (write(pridebugfd, s, strlen(s)) < 0) {
14408 ast_log_callid(LOG_WARNING, 0,
"write() failed: %s\n", strerror(errno));
14412 ast_mutex_unlock(&pridebugfdlock);
14416 #if defined(HAVE_PRI)
14417 static void dahdi_pri_error(
struct pri *pri,
char *s)
14423 int dchancount = 0;
14426 for (x = 0; x < NUM_SPANS; x++) {
14428 if (pris[x].pri.dchans[y]) {
14432 if (pris[x].pri.dchans[y] == pri) {
14443 if (1 < dchancount) {
14444 ast_log_callid(LOG_ERROR, 0,
"[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14455 ast_mutex_lock(&pridebugfdlock);
14457 if (pridebugfd >= 0) {
14458 if (write(pridebugfd, s, strlen(s)) < 0) {
14459 ast_log_callid(LOG_WARNING, 0,
"write() failed: %s\n", strerror(errno));
14463 ast_mutex_unlock(&pridebugfdlock);
14467 #if defined(HAVE_PRI)
14468 static int prepare_pri(
struct dahdi_pri *pri)
14471 struct dahdi_params p;
14472 struct dahdi_bufferinfo bi;
14473 struct dahdi_spaninfo si;
14478 if (pri->pri.
fds[i] >= 0) {
14482 pri->pri.
fds[i] = open(
"/dev/dahdi/channel", O_RDWR);
14483 if ((pri->pri.
fds[i] < 0)) {
14484 ast_log(LOG_ERROR,
"Unable to open D-channel (fd=%d) (%s)\n",
14485 pri->pri.
fds[i], strerror(errno));
14489 res = ioctl(pri->pri.
fds[i], DAHDI_SPECIFY, &x);
14491 dahdi_close_pri_fd(pri, i);
14492 ast_log(LOG_ERROR,
"Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14495 memset(&p, 0,
sizeof(p));
14496 res = ioctl(pri->pri.
fds[i], DAHDI_GET_PARAMS, &p);
14498 dahdi_close_pri_fd(pri, i);
14499 ast_log(LOG_ERROR,
"Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14502 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14503 dahdi_close_pri_fd(pri, i);
14504 ast_log(LOG_ERROR,
"D-channel %d is not in HDLC/FCS mode.\n", x);
14507 memset(&si, 0,
sizeof(si));
14508 res = ioctl(pri->pri.
fds[i], DAHDI_SPANSTAT, &si);
14510 dahdi_close_pri_fd(pri, i);
14511 ast_log(LOG_ERROR,
"Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14514 pri_event_noalarm(&pri->pri, i, 1);
14516 pri_event_alarm(&pri->pri, i, 1);
14518 memset(&bi, 0,
sizeof(bi));
14519 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14520 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14523 if (ioctl(pri->pri.
fds[i], DAHDI_SET_BUFINFO, &bi)) {
14524 ast_log(LOG_ERROR,
"Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14525 dahdi_close_pri_fd(pri, i);
14534 #if defined(HAVE_PRI)
14535 static char *complete_span_helper(
const char *line,
const char *word,
int pos,
int state,
int rpos)
14543 for (which = span = 0; span < NUM_SPANS; span++) {
14544 if (pris[span].pri.pri && ++which > state) {
14555 #if defined(HAVE_PRI)
14556 static char *complete_span_4(
const char *line,
const char *word,
int pos,
int state)
14558 return complete_span_helper(line,word,pos,state,3);
14562 #if defined(HAVE_PRI)
14568 e->
command =
"pri set debug file";
14569 e->
usage =
"Usage: pri set debug file [output-file]\n"
14570 " Sends PRI debug output to the specified output file\n";
14576 return CLI_SHOWUSAGE;
14578 if (ast_strlen_zero(a->argv[4]))
14579 return CLI_SHOWUSAGE;
14581 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14583 ast_cli(a->fd,
"Unable to open '%s' for writing\n", a->argv[4]);
14584 return CLI_SUCCESS;
14587 ast_mutex_lock(&pridebugfdlock);
14589 if (pridebugfd >= 0)
14593 ast_copy_string(pridebugfilename,a->argv[4],
sizeof(pridebugfilename));
14594 ast_mutex_unlock(&pridebugfdlock);
14595 ast_cli(a->fd,
"PRI debug output will be sent to '%s'\n", a->argv[4]);
14596 return CLI_SUCCESS;
14600 #if defined(HAVE_PRI)
14601 static int action_pri_debug_file_set(
struct mansession *s,
const struct message *m)
14606 if (ast_strlen_zero(output_file)) {
14610 myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14616 ast_mutex_lock(&pridebugfdlock);
14618 if (pridebugfd >= 0) {
14623 ast_copy_string(pridebugfilename, output_file,
sizeof(pridebugfilename));
14624 ast_mutex_unlock(&pridebugfdlock);
14625 astman_send_ack(s, m,
"PRI debug output will now be sent to requested file.");
14631 #if defined(HAVE_PRI)
14632 static int action_pri_debug_file_unset(
struct mansession *s,
const struct message *m)
14634 ast_mutex_lock(&pridebugfdlock);
14636 if (pridebugfd >= 0) {
14642 ast_mutex_unlock(&pridebugfdlock);
14649 #if defined(HAVE_PRI)
14658 e->
command =
"pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14660 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14661 " Enables debugging on a given PRI span\n"
14662 " Level is a bitmap of the following values:\n"
14663 " 1 General debugging incl. state changes\n"
14664 " 2 Decoded Q.931 messages\n"
14665 " 4 Decoded Q.921 messages\n"
14666 " 8 Raw hex dumps of Q.921 frames\n"
14667 " on - equivalent to 3\n"
14668 " hex - equivalent to 8\n"
14669 " intense - equivalent to 15\n";
14672 return complete_span_4(a->line, a->word, a->pos, a->n);
14675 return CLI_SHOWUSAGE;
14678 if (!strcasecmp(a->argv[3],
"on")) {
14680 }
else if (!strcasecmp(a->argv[3],
"off")) {
14682 }
else if (!strcasecmp(a->argv[3],
"intense")) {
14684 }
else if (!strcasecmp(a->argv[3],
"hex")) {
14687 level = atoi(a->argv[3]);
14689 span = atoi(a->argv[5]);
14690 if ((span < 1) || (span > NUM_SPANS)) {
14691 ast_cli(a->fd,
"Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14692 return CLI_SUCCESS;
14694 if (!pris[span-1].pri.pri) {
14695 ast_cli(a->fd,
"No PRI running on span %d\n", span);
14696 return CLI_SUCCESS;
14700 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14701 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14702 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14706 if (pris[span - 1].pri.dchans[x]) {
14707 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14712 ast_mutex_lock(&pridebugfdlock);
14713 if (0 <= pridebugfd) {
14716 ast_cli(a->fd,
"Disabled PRI debug output to file '%s'\n",
14719 ast_mutex_unlock(&pridebugfdlock);
14721 pris[span - 1].pri.
debug = (level) ? 1 : 0;
14722 ast_cli(a->fd,
"%s debugging on span %d\n", (level) ?
"Enabled" :
"Disabled", span);
14723 return CLI_SUCCESS;
14727 #if defined(HAVE_PRI)
14737 if (ast_strlen_zero(level)) {
14742 if (ast_strlen_zero(span)) {
14747 if (!strcasecmp(level,
"on")) {
14749 }
else if (!strcasecmp(level,
"off")) {
14751 }
else if (!strcasecmp(level,
"intense")) {
14753 }
else if (!strcasecmp(level,
"hex")) {
14756 if (sscanf(level,
"%30d", &level_val) != 1) {
14762 if (sscanf(span,
"%30d", &span_val) != 1) {
14766 if ((span_val < 1) || (span_val > NUM_SPANS)) {
14768 char id_text[256] =
"";
14770 if (!ast_strlen_zero(
id)) {
14771 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
14776 "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14784 if (!pris[span_val-1].pri.pri) {
14789 if (level_val & 1) {
14792 if (level_val & 2) {
14793 debugmask |= PRI_DEBUG_Q931_DUMP;
14795 if (level_val & 4) {
14796 debugmask |= PRI_DEBUG_Q921_DUMP;
14798 if (level_val & 8) {
14799 debugmask |= PRI_DEBUG_Q921_RAW;
14804 if (pris[span_val - 1].pri.dchans[x]) {
14805 pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14809 pris[span_val - 1].pri.
debug = (level_val) ? 1 : 0;
14816 #if defined(HAVE_PRI)
14817 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14823 int x, y, fd = a->fd;
14824 int interfaceid = 0;
14825 char db_chan_name[20], db_answer[15];
14829 if (a->argc < 5 || a->argc > 6)
14830 return CLI_SHOWUSAGE;
14831 if (strchr(a->argv[4],
':')) {
14832 if (sscanf(a->argv[4],
"%30d:%30d", &trunkgroup, &channel) != 2)
14833 return CLI_SHOWUSAGE;
14834 if ((trunkgroup < 1) || (channel < 1))
14835 return CLI_SHOWUSAGE;
14837 for (x=0;x<NUM_SPANS;x++) {
14838 if (pris[x].pri.trunkgroup == trunkgroup) {
14844 ast_cli(fd,
"No such trunk group %d\n", trunkgroup);
14845 return CLI_FAILURE;
14848 channel = atoi(a->argv[4]);
14851 interfaceid = atoi(a->argv[5]);
14854 for (x = 0; x < NUM_SPANS; x++) {
14859 ast_mutex_lock(&pri->pri.
lock);
14860 pri_maintenance_service(pri->pri.
pri, interfaceid, -1, changestatus);
14861 ast_mutex_unlock(&pri->pri.
lock);
14864 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14865 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14867 return CLI_SUCCESS;
14873 ast_mutex_lock(&
iflock);
14874 for (tmp = iflist; tmp; tmp = tmp->
next) {
14875 if (tmp->pri && tmp->
channel == channel) {
14876 ast_mutex_unlock(&
iflock);
14877 ast_mutex_lock(&tmp->pri->
lock);
14879 ast_mutex_unlock(&tmp->pri->
lock);
14881 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14882 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14883 return CLI_SUCCESS;
14885 snprintf(db_chan_name,
sizeof(db_chan_name),
"%s/%d:%d",
dahdi_db, tmp->
span, channel);
14886 why = &((
struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14887 switch(changestatus) {
14893 snprintf(db_answer,
sizeof(db_answer),
"%s:%u",
SRVST_TYPE_OOS, *why);
14896 dahdi_pri_update_span_devstate(tmp->pri);
14904 snprintf(db_answer,
sizeof(db_answer),
"%s:%u",
SRVST_TYPE_OOS, *why);
14906 dahdi_pri_update_span_devstate(tmp->pri);
14911 ast_log(LOG_WARNING,
"Unsupported changestatus: '%d'\n", changestatus);
14914 pri_maintenance_bservice(tmp->pri->
pri, tmp->sig_pvt, changestatus);
14915 ast_mutex_unlock(&tmp->pri->
lock);
14916 return CLI_SUCCESS;
14919 ast_mutex_unlock(&
iflock);
14921 ast_cli(fd,
"Unable to find given channel %d, possibly not a PRI\n", channel);
14922 return CLI_FAILURE;
14929 e->
command =
"pri service enable channel";
14931 "Usage: pri service enable channel <channel> [<interface id>]\n"
14932 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14933 " to restore a channel to service, with optional interface id\n"
14934 " as agreed upon with remote switch operator\n";
14939 return handle_pri_service_generic(e, cmd, a, 0);
14946 e->
command =
"pri service disable channel";
14948 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14949 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14950 " to remove a channel from service, with optional interface id\n"
14951 " as agreed upon with remote switch operator\n";
14956 return handle_pri_service_generic(e, cmd, a, 2);
14961 #if defined(HAVE_PRI)
14968 e->
command =
"pri show channels";
14970 "Usage: pri show channels\n"
14971 " Displays PRI channel information such as the current mapping\n"
14972 " of DAHDI B channels to Asterisk channel names and which calls\n"
14973 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14974 " are not associated with any B channel.\n";
14981 return CLI_SHOWUSAGE;
14983 sig_pri_cli_show_channels_header(a->fd);
14984 for (span = 0; span < NUM_SPANS; ++span) {
14985 if (pris[span].pri.pri) {
14986 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14989 return CLI_SUCCESS;
14993 #if defined(HAVE_PRI)
15000 e->
command =
"pri show spans";
15002 "Usage: pri show spans\n"
15003 " Displays PRI span information\n";
15010 return CLI_SHOWUSAGE;
15012 for (span = 0; span < NUM_SPANS; span++) {
15013 if (pris[span].pri.pri) {
15014 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
15017 return CLI_SUCCESS;
15021 #if defined(HAVE_PRI)
15022 #define container_of(ptr, type, member) \
15023 ((type *)((char *)(ptr) - offsetof(type, member)))
15035 static void pri_destroy_span(
struct sig_pri_span *pri)
15041 pthread_t master = pri->
master;
15043 if (!master || (master == AST_PTHREADT_NULL)) {
15046 ast_debug(2,
"About to destroy DAHDI channels of span %d.\n", pri->
span);
15047 for (i = 0; i < pri->
numchans; i++) {
15055 ast_debug(2,
"About to destroy B-channel %d.\n", channel);
15056 dahdi_destroy_channel_range(channel, channel);
15059 cancel_code = pthread_cancel(master);
15060 pthread_kill(master, SIGURG);
15062 "Waiting to join thread of span %d "
15063 "with pid=%p cancel_code=%d\n",
15064 pri->
span, (
void *)master, cancel_code);
15065 res = pthread_join(master, NULL);
15067 ast_log(LOG_NOTICE,
"pthread_join failed: %d\n", res);
15069 pri->
master = AST_PTHREADT_NULL;
15072 dahdi_pri = container_of(pri,
struct dahdi_pri, pri);
15074 ast_debug(4,
"closing pri_fd %d\n", i);
15075 dahdi_close_pri_fd(dahdi_pri, i);
15078 sig_pri_init_pri(pri);
15082 static char *handle_pri_destroy_span(
struct ast_cli_entry *e,
int cmd,
15091 e->
command =
"pri destroy span";
15093 "Usage: pri destroy span <span>\n"
15094 " Destorys D-channel of span and its B-channels.\n"
15095 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15098 return complete_span_4(a->line, a->word, a->pos, a->n);
15102 return CLI_SHOWUSAGE;
15104 res = sscanf(a->argv[3],
"%30d", &span);
15105 if ((res != 1) || span < 1 || span > NUM_SPANS) {
15107 "Invalid span '%s'. Should be a number from %d to %d\n",
15108 a->argv[3], 1, NUM_SPANS);
15109 return CLI_SUCCESS;
15111 pri = &pris[span - 1].pri;
15113 ast_cli(a->fd,
"No PRI running on span %d\n", span);
15114 return CLI_SUCCESS;
15117 pri_destroy_span(pri);
15118 return CLI_SUCCESS;
15123 #if defined(HAVE_PRI)
15130 e->
command =
"pri show span";
15132 "Usage: pri show span <span>\n"
15133 " Displays PRI Information on a given PRI span\n";
15136 return complete_span_4(a->line, a->word, a->pos, a->n);
15140 return CLI_SHOWUSAGE;
15141 span = atoi(a->argv[3]);
15142 if ((span < 1) || (span > NUM_SPANS)) {
15143 ast_cli(a->fd,
"Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15144 return CLI_SUCCESS;
15146 if (!pris[span-1].pri.
pri) {
15147 ast_cli(a->fd,
"No PRI running on span %d\n", span);
15148 return CLI_SUCCESS;
15151 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15153 return CLI_SUCCESS;
15157 #if defined(HAVE_PRI)
15167 e->
command =
"pri show debug";
15169 "Usage: pri show debug\n"
15170 " Show the debug state of pri spans\n";
15176 for (span = 0; span < NUM_SPANS; span++) {
15177 if (pris[span].pri.
pri) {
15179 if (pris[span].pri.
dchans[x]) {
15180 debug = pri_get_debug(pris[span].pri.
dchans[x]);
15181 ast_cli(a->fd,
"Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)?
"Yes" :
"No" ,(debug&PRI_DEBUG_Q921_RAW)?
"Yes" :
"No" );
15188 ast_mutex_lock(&pridebugfdlock);
15189 if (pridebugfd >= 0)
15190 ast_cli(a->fd,
"Logging PRI debug to file %s\n", pridebugfilename);
15191 ast_mutex_unlock(&pridebugfdlock);
15194 ast_cli(a->fd,
"No PRI running\n");
15195 return CLI_SUCCESS;
15199 #if defined(HAVE_PRI)
15204 e->
command =
"pri show version";
15206 "Usage: pri show version\n"
15207 "Show libpri version information\n";
15213 ast_cli(a->fd,
"libpri version: %s\n", pri_get_version());
15215 return CLI_SUCCESS;
15219 #if defined(HAVE_PRI)
15221 AST_CLI_DEFINE(handle_pri_debug,
"Enables PRI debugging on a span"),
15222 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15223 AST_CLI_DEFINE(handle_pri_service_enable_channel,
"Return a channel to service"),
15224 AST_CLI_DEFINE(handle_pri_service_disable_channel,
"Remove a channel from service"),
15226 AST_CLI_DEFINE(handle_pri_show_channels,
"Displays PRI channel information"),
15227 AST_CLI_DEFINE(handle_pri_show_spans,
"Displays PRI span information"),
15228 AST_CLI_DEFINE(handle_pri_show_span,
"Displays PRI span information"),
15229 AST_CLI_DEFINE(handle_pri_destroy_span,
"Destroy a PRI span"),
15230 AST_CLI_DEFINE(handle_pri_show_debug,
"Displays current PRI debug settings"),
15231 AST_CLI_DEFINE(handle_pri_set_debug_file,
"Sends PRI debug output to the specified file"),
15232 AST_CLI_DEFINE(handle_pri_version,
"Displays libpri version"),
15242 e->
command =
"mfcr2 show version";
15244 "Usage: mfcr2 show version\n"
15245 " Shows the version of the OpenR2 library being used.\n";
15250 ast_cli(a->fd,
"OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15251 return CLI_SUCCESS;
15256 #define FORMAT "%4s %40s\n"
15258 int numvariants = 0;
15259 const openr2_variant_entry_t *variants;
15262 e->
command =
"mfcr2 show variants";
15264 "Usage: mfcr2 show variants\n"
15265 " Shows the list of MFC/R2 variants supported.\n";
15270 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15271 ast_cli(a->fd,
"Failed to get list of variants.\n");
15272 return CLI_FAILURE;
15274 ast_cli(a->fd, FORMAT,
"Variant Code",
"Country");
15275 for (i = 0; i < numvariants; i++) {
15276 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15278 return CLI_SUCCESS;
15284 #define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15285 int filtertype = 0;
15292 openr2_context_t *r2context;
15293 openr2_variant_t r2variant;
15296 e->
command =
"mfcr2 show channels [group|context]";
15298 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15299 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15304 if (!((a->argc == 3) || (a->argc == 5))) {
15305 return CLI_SHOWUSAGE;
15307 if (a->argc == 5) {
15308 if (!strcasecmp(a->argv[3],
"group")) {
15309 targetnum = atoi(a->argv[4]);
15310 if ((targetnum < 0) || (targetnum > 63))
15311 return CLI_SHOWUSAGE;
15312 targetnum = 1 << targetnum;
15314 }
else if (!strcasecmp(a->argv[3],
"context")) {
15317 return CLI_SHOWUSAGE;
15320 ast_cli(a->fd, FORMAT,
"Chan",
"Link#",
"Variant",
"Max ANI",
"Max DNIS",
"ANI First",
"Immediate Accept",
"Tx CAS",
"Rx CAS");
15321 ast_mutex_lock(&
iflock);
15322 for (p = iflist; p; p = p->
next) {
15323 if (!(p->
sig & SIG_MFCR2) || !p->r2chan) {
15327 switch(filtertype) {
15329 if (p->
group != targetnum) {
15334 if (strcasecmp(p->
context, a->argv[4])) {
15342 r2context = openr2_chan_get_context(p->r2chan);
15343 r2variant = openr2_context_get_variant(r2context);
15344 snprintf(channo,
sizeof(channo),
"%d", p->
channel);
15345 snprintf(linkno,
sizeof(linkno),
"%d", p->mfcr2->index);
15346 snprintf(anino,
sizeof(anino),
"%d", openr2_context_get_max_ani(r2context));
15347 snprintf(dnisno,
sizeof(dnisno),
"%d", openr2_context_get_max_dnis(r2context));
15348 ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
15349 anino, dnisno, openr2_context_get_ani_first(r2context) ?
"Yes" :
"No",
15350 openr2_context_get_immediate_accept(r2context) ?
"Yes" :
"No",
15351 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15353 ast_mutex_unlock(&
iflock);
15354 return CLI_SUCCESS;
15362 char *toklevel = NULL;
15363 char *saveptr = NULL;
15364 char *logval = NULL;
15365 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15366 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15369 e->
command =
"mfcr2 set debug";
15371 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15372 " Set a new logging level for the specified channel.\n"
15373 " If no channel is specified the logging level will be applied to all channels.\n";
15379 return CLI_SHOWUSAGE;
15381 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15383 toklevel = strtok_r(logval,
",", &saveptr);
15384 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15385 ast_cli(a->fd,
"Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15386 return CLI_FAILURE;
15387 }
else if (OR2_LOG_NOTHING == tmplevel) {
15388 loglevel = tmplevel;
15390 loglevel |= tmplevel;
15391 while ((toklevel = strtok_r(NULL,
",", &saveptr))) {
15392 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15393 ast_cli(a->fd,
"Ignoring invalid logging level: '%s'.\n", toklevel);
15396 loglevel |= tmplevel;
15399 ast_mutex_lock(&
iflock);
15400 for (p = iflist; p; p = p->
next) {
15401 if (!(p->
sig & SIG_MFCR2) || !p->r2chan) {
15404 if ((channo != -1) && (p->
channel != channo )) {
15407 openr2_chan_set_log_level(p->r2chan, loglevel);
15408 if (channo != -1) {
15409 ast_cli(a->fd,
"MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->
channel);
15413 if ((channo != -1) && !p) {
15414 ast_cli(a->fd,
"MFC/R2 channel %d not found.\n", channo);
15416 if (channo == -1) {
15417 ast_cli(a->fd,
"MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15419 ast_mutex_unlock(&
iflock);
15420 return CLI_SUCCESS;
15429 e->
command =
"mfcr2 call files [on|off]";
15431 "Usage: mfcr2 call files [on|off] <channel>\n"
15432 " Enable call files creation on the specified channel.\n"
15433 " If no channel is specified call files creation policy will be applied to all channels.\n";
15439 return CLI_SHOWUSAGE;
15441 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15442 ast_mutex_lock(&
iflock);
15443 for (p = iflist; p; p = p->
next) {
15444 if (!(p->
sig & SIG_MFCR2) || !p->r2chan) {
15447 if ((channo != -1) && (p->
channel != channo )) {
15451 openr2_chan_enable_call_files(p->r2chan);
15453 openr2_chan_disable_call_files(p->r2chan);
15455 if (channo != -1) {
15457 ast_cli(a->fd,
"MFC/R2 call files enabled for channel %d.\n", p->
channel);
15459 ast_cli(a->fd,
"MFC/R2 call files disabled for channel %d.\n", p->
channel);
15464 if ((channo != -1) && !p) {
15465 ast_cli(a->fd,
"MFC/R2 channel %d not found.\n", channo);
15467 if (channo == -1) {
15469 ast_cli(a->fd,
"MFC/R2 Call files enabled for all channels.\n");
15471 ast_cli(a->fd,
"MFC/R2 Call files disabled for all channels.\n");
15474 ast_mutex_unlock(&
iflock);
15475 return CLI_SUCCESS;
15484 e->
command =
"mfcr2 set idle";
15486 "Usage: mfcr2 set idle <channel>\n"
15487 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15488 " Force the given channel into IDLE state.\n"
15489 " If no channel is specified, all channels will be set to IDLE.\n";
15494 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15495 ast_mutex_lock(&
iflock);
15496 for (p = iflist; p; p = p->
next) {
15497 if (!(p->
sig & SIG_MFCR2) || !p->r2chan) {
15500 if ((channo != -1) && (p->
channel != channo )) {
15503 openr2_chan_set_idle(p->r2chan);
15504 ast_mutex_lock(&p->
lock);
15507 ast_mutex_unlock(&p->
lock);
15508 if (channo != -1) {
15512 if ((channo != -1) && !p) {
15513 ast_cli(a->fd,
"MFC/R2 channel %d not found.\n", channo);
15515 ast_mutex_unlock(&
iflock);
15516 return CLI_SUCCESS;
15525 e->
command =
"mfcr2 set blocked";
15527 "Usage: mfcr2 set blocked <channel>\n"
15528 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15529 " Force the given channel into BLOCKED state.\n"
15530 " If no channel is specified, all channels will be set to BLOCKED.\n";
15535 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15536 ast_mutex_lock(&
iflock);
15537 for (p = iflist; p; p = p->
next) {
15538 if (!(p->
sig & SIG_MFCR2) || !p->r2chan) {
15541 if ((channo != -1) && (p->
channel != channo )) {
15544 openr2_chan_set_blocked(p->r2chan);
15545 ast_mutex_lock(&p->
lock);
15547 ast_mutex_unlock(&p->
lock);
15548 if (channo != -1) {
15552 if ((channo != -1) && !p) {
15553 ast_cli(a->fd,
"MFC/R2 channel %d not found.\n", channo);
15555 ast_mutex_unlock(&
iflock);
15556 return CLI_SUCCESS;
15559 static void mfcr2_show_links_of(
struct ast_cli_args *a,
struct r2links *list_head,
const char *title)
15561 #define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15566 char live_chans_str[5];
15567 char channel_list[R2_LINK_CAPACITY * 4];
15568 struct r2link_entry *cur;
15569 ast_cli(a->fd,
"%s\n", title);
15570 ast_cli(a->fd, FORMAT,
"Index",
"Thread",
"Dahdi-Device",
"Channels",
"Channel-List");
15572 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15573 const char *thread_status = NULL;
15580 if (mfcr2->r2master == 0L) {
15581 thread_status =
"zero";
15582 }
else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15583 thread_status =
"none";
15585 thread_status =
"created";
15587 snprintf(index,
sizeof(index),
"%d", mfcr2->index);
15588 snprintf(live_chans_str,
sizeof(live_chans_str),
"%d", mfcr2->live_chans);
15594 for (i = 0; i < mfcr2->numchans && len <
sizeof(channel_list) - 1; i++) {
15601 if (prev_channo && prev_channo == channo - 1) {
15602 prev_channo = channo;
15606 if (inside_range) {
15608 len += snprintf(channel_list + len,
sizeof(channel_list) - len - 1,
"-%d,%d", prev_channo, channo);
15610 }
else if (prev_channo) {
15612 len += snprintf(channel_list + len,
sizeof(channel_list) - len - 1,
",%d", channo);
15615 len += snprintf(channel_list + len,
sizeof(channel_list) - len - 1,
"%d", channo);
15617 prev_channo = channo;
15620 if (inside_range) {
15622 len += snprintf(channel_list + len,
sizeof(channel_list) - len - 1,
"-%d", channo);
15624 }
else if (prev_channo) {
15626 len += snprintf(channel_list + len,
sizeof(channel_list) - len - 1,
",%d", channo);
15629 ast_cli(a->fd, FORMAT,
15632 (mfcr2->nodev) ?
"MISSING" :
"OK",
15645 e->
command =
"mfcr2 show links";
15647 "Usage: mfcr2 show links\n"
15648 " Shows the DAHDI MFC/R2 links.\n";
15653 if (a->argc != 3) {
15654 return CLI_SHOWUSAGE;
15656 mfcr2_show_links_of(a, &r2links,
"Live links\n");
15657 mfcr2_show_links_of(a, &nodev_r2links,
"Links to be removed (device missing)\n");
15658 return CLI_SUCCESS;
15664 int wanted_link_index;
15665 int found_link = 0;
15666 struct r2link_entry *cur = NULL;
15670 e->
command =
"mfcr2 destroy link";
15672 "Usage: mfcr2 destroy link <index-number>\n"
15673 " Destorys D-channel of link and its B-channels.\n"
15674 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15680 return CLI_SHOWUSAGE;
15682 res = sscanf(a->argv[3],
"%30d", &wanted_link_index);
15683 if ((res != 1) || wanted_link_index < 1) {
15685 "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15686 return CLI_SUCCESS;
15690 struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15691 if (wanted_link_index == mfcr2->index) {
15699 if (! found_link) {
15700 ast_cli(a->fd,
"No link found with index %d.\n", wanted_link_index);
15701 return CLI_FAILURE;
15703 return CLI_SUCCESS;
15707 AST_CLI_DEFINE(handle_mfcr2_version,
"Show OpenR2 library version"),
15708 AST_CLI_DEFINE(handle_mfcr2_show_variants,
"Show supported MFC/R2 variants"),
15709 AST_CLI_DEFINE(handle_mfcr2_show_channels,
"Show MFC/R2 channels"),
15710 AST_CLI_DEFINE(handle_mfcr2_show_links,
"Show MFC/R2 links"),
15711 AST_CLI_DEFINE(handle_mfcr2_set_debug,
"Set MFC/R2 channel logging level"),
15712 AST_CLI_DEFINE(handle_mfcr2_call_files,
"Enable/Disable MFC/R2 call files"),
15713 AST_CLI_DEFINE(handle_mfcr2_set_idle,
"Reset MFC/R2 channel forcing it to IDLE"),
15714 AST_CLI_DEFINE(handle_mfcr2_set_blocked,
"Reset MFC/R2 channel forcing it to BLOCKED"),
15715 AST_CLI_DEFINE(handle_mfcr2_destroy_link,
"Destroy given MFC/R2 link"),
15726 e->
command =
"dahdi destroy channels";
15728 "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15729 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15734 if ((a->argc < 4) || a->argc > 5) {
15735 return CLI_SHOWUSAGE;
15737 start = atoi(a->argv[3]);
15739 ast_cli(a->fd,
"Invalid starting channel number %s.\n",
15741 return CLI_FAILURE;
15743 if (a->argc == 5) {
15744 end = atoi(a->argv[4]);
15746 ast_cli(a->fd,
"Invalid ending channel number %s.\n",
15748 return CLI_FAILURE;
15756 "range end (%d) is smaller than range start (%d)\n",
15758 return CLI_FAILURE;
15760 dahdi_destroy_channel_range(start, end);
15761 return CLI_SUCCESS;
15772 e->
command =
"dahdi create channels";
15773 e->
usage =
"Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15774 " dahdi create channels new - add channels not yet created\n"
15775 "For ISDN and SS7 the range should include complete spans.\n";
15780 if ((a->argc < 4) || a->argc > 5) {
15781 return CLI_SHOWUSAGE;
15783 if (a->argc == 4 && !strcmp(a->argv[3],
"new")) {
15784 ret = dahdi_create_channel_range(0, 0);
15785 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15787 start = atoi(a->argv[3]);
15789 ast_cli(a->fd,
"Invalid starting channel number '%s'.\n",
15791 return CLI_FAILURE;
15793 if (a->argc == 5) {
15794 end = atoi(a->argv[4]);
15796 ast_cli(a->fd,
"Invalid ending channel number '%s'.\n",
15798 return CLI_FAILURE;
15805 "range end (%d) is smaller than range start (%d)\n",
15807 return CLI_FAILURE;
15809 ret = dahdi_create_channel_range(start, end);
15810 return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15813 static void dahdi_softhangup_all(
void)
15817 ast_mutex_lock(&
iflock);
15818 for (p = iflist; p; p = p->
next) {
15819 ast_mutex_lock(&p->
lock);
15821 if (ast_channel_trylock(p->
owner)) {
15822 if (DEBUG_ATLEAST(3))
15823 ast_verbose(
"Avoiding deadlock\n");
15825 ast_mutex_unlock(&p->
lock);
15826 ast_mutex_unlock(&
iflock);
15829 if (DEBUG_ATLEAST(3))
15830 ast_verbose(
"Softhanging up on %s\n", ast_channel_name(p->
owner));
15833 num_restart_pending++;
15834 ast_channel_unlock(p->
owner);
15836 ast_mutex_unlock(&p->
lock);
15838 ast_mutex_unlock(&
iflock);
15841 static int dahdi_restart(
void)
15843 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15849 ast_mutex_lock(&restart_lock);
15850 ast_verb(1,
"Destroying channels and reloading DAHDI configuration.\n");
15851 dahdi_softhangup_all();
15852 ast_verb(4,
"Initial softhangup of all DAHDI channels complete.\n");
15854 dahdi_r2_destroy_links();
15857 #if defined(HAVE_PRI)
15858 for (i = 0; i < NUM_SPANS; i++) {
15859 if (pris[i].pri.
master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15860 cancel_code = pthread_cancel(pris[i].pri.
master);
15861 pthread_kill(pris[i].pri.
master, SIGURG);
15862 ast_debug(4,
"Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (
void *) pris[i].pri.
master, cancel_code);
15863 pthread_join(pris[i].pri.
master, NULL);
15864 ast_debug(4,
"Joined thread of span %d\n", i);
15869 #if defined(HAVE_SS7)
15870 for (i = 0; i < NUM_SPANS; i++) {
15871 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15872 cancel_code = pthread_cancel(linksets[i].ss7.master);
15873 pthread_kill(linksets[i].ss7.master, SIGURG);
15874 ast_debug(4,
"Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (
void *) linksets[i].ss7.master, cancel_code);
15875 pthread_join(linksets[i].ss7.master, NULL);
15876 ast_debug(4,
"Joined thread of span %d\n", i);
15885 ast_debug(4,
"Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (
void *)
monitor_thread, cancel_code);
15887 ast_debug(4,
"Joined monitor thread\n");
15891 ast_mutex_lock(&ss_thread_lock);
15892 while (ss_thread_count > 0) {
15893 int x = DAHDI_FLASH;
15894 ast_debug(3,
"Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15896 ast_mutex_lock(&
iflock);
15897 for (p = iflist; p; p = p->
next) {
15903 ast_mutex_unlock(&
iflock);
15904 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15908 dahdi_softhangup_all();
15909 ast_verb(4,
"Final softhangup of all DAHDI channels complete.\n");
15910 destroy_all_channels();
15911 memset(round_robin, 0,
sizeof(round_robin));
15917 for (i = 0; i < NUM_SPANS; i++) {
15919 dahdi_close_pri_fd(&(pris[i]), j);
15922 memset(pris, 0,
sizeof(pris));
15923 for (i = 0; i < NUM_SPANS; i++) {
15924 sig_pri_init_pri(&pris[i].pri);
15926 pri_set_error(dahdi_pri_error);
15927 pri_set_message(dahdi_pri_message);
15929 #if defined(HAVE_SS7)
15930 for (i = 0; i < NUM_SPANS; i++) {
15932 dahdi_close_ss7_fd(&(linksets[i]), j);
15935 memset(linksets, 0,
sizeof(linksets));
15936 for (i = 0; i < NUM_SPANS; i++) {
15937 sig_ss7_init_linkset(&linksets[i].ss7);
15939 ss7_set_error(dahdi_ss7_error);
15940 ss7_set_message(dahdi_ss7_message);
15941 ss7_set_hangup(sig_ss7_cb_hangup);
15942 ss7_set_notinservice(sig_ss7_cb_notinservice);
15943 ss7_set_call_null(sig_ss7_cb_call_null);
15946 if (setup_dahdi(2) != 0) {
15947 ast_log(LOG_WARNING,
"Reload channels from dahdi config failed!\n");
15948 ast_mutex_unlock(&ss_thread_lock);
15951 ast_mutex_unlock(&ss_thread_lock);
15952 ast_mutex_unlock(&restart_lock);
15960 e->
command =
"dahdi restart";
15962 "Usage: dahdi restart\n"
15963 " Restarts the DAHDI channels: destroys them all and then\n"
15964 " re-reads them from chan_dahdi.conf.\n"
15965 " Note that this will STOP any running CALL on DAHDI channels.\n"
15972 return CLI_SHOWUSAGE;
15974 if (dahdi_restart() != 0)
15975 return CLI_FAILURE;
15976 return CLI_SUCCESS;
15981 if (dahdi_restart() != 0) {
15991 #define FORMAT "%7s %4d %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15992 #define FORMAT2 "%7s %4s %-20.20s %-10.10s %-15.15s %-8.8s %-20.20s %-10.10s %-10.10s %-12.12s %-32.32s\n"
15993 ast_group_t targetnum = 0;
15994 int filtertype = 0;
16001 e->
command =
"dahdi show channels [group|context]";
16003 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
16004 " Shows a list of available channels with optional filtering\n"
16005 " <group> must be a number between 0 and 63\n";
16013 if (!((a->argc == 3) || (a->argc == 5))) {
16014 return CLI_SHOWUSAGE;
16017 if (a->argc == 5) {
16018 if (!strcasecmp(a->argv[3],
"group")) {
16019 targetnum = atoi(a->argv[4]);
16020 if (63 < targetnum) {
16021 return CLI_SHOWUSAGE;
16023 targetnum = ((ast_group_t) 1) << targetnum;
16025 }
else if (!strcasecmp(a->argv[3],
"context")) {
16030 ast_cli(a->fd, FORMAT2,
"Chan",
"Span",
"Signalling",
"Extension",
"Context",
"Language",
"MOH Interpret",
"Blocked",
"In Service",
"Alarms",
"Description");
16031 ast_mutex_lock(&
iflock);
16032 for (tmp = iflist; tmp; tmp = tmp->
next) {
16035 switch(filtertype) {
16037 if (!(tmp->
group & targetnum)) {
16042 if (strcasecmp(tmp->
context, a->argv[4])) {
16051 snprintf(tmps,
sizeof(tmps),
"%d", tmp->
channel);
16059 blockstr[2] =
'\0';
16061 ast_cli(a->fd, FORMAT, tmps, tmp->
span, sig2str(tmp->
sig), tmp->
exten, tmp->
context, tmp->
language, tmp->
mohinterpret, blockstr, tmp->
inservice ?
"Yes" :
"No",
16064 ast_mutex_unlock(&
iflock);
16065 return CLI_SUCCESS;
16074 struct dahdi_confinfo ci;
16075 struct dahdi_params ps;
16082 e->
command =
"dahdi show channel";
16084 "Usage: dahdi show channel <chan num>\n"
16085 " Detailed information about a given channel\n";
16092 return CLI_SHOWUSAGE;
16094 channel = atoi(a->argv[3]);
16096 ast_mutex_lock(&
iflock);
16097 for (tmp = iflist; tmp; tmp = tmp->
next) {
16098 if (tmp->
channel == channel) {
16099 ast_cli(a->fd,
"Channel: %d\n", tmp->
channel);
16100 ast_cli(a->fd,
"Description: %s\n", tmp->
description);
16101 ast_cli(a->fd,
"File Descriptor: %d\n", tmp->
subs[
SUB_REAL].dfd);
16102 ast_cli(a->fd,
"Span: %d\n", tmp->
span);
16103 ast_cli(a->fd,
"Extension: %s\n", tmp->
exten);
16104 ast_cli(a->fd,
"Dialing: %s\n", tmp->
dialing ?
"yes" :
"no");
16105 ast_cli(a->fd,
"Context: %s\n", tmp->
context);
16106 ast_cli(a->fd,
"Caller ID: %s\n", tmp->
cid_num);
16107 ast_cli(a->fd,
"Calling TON: %d\n", tmp->
cid_ton);
16108 #if defined(HAVE_PRI)
16109 #if defined(HAVE_PRI_SUBADDR)
16110 ast_cli(a->fd,
"Caller ID subaddress: %s\n", tmp->
cid_subaddr);
16113 ast_cli(a->fd,
"Caller ID name: %s\n", tmp->
cid_name);
16114 ast_cli(a->fd,
"Mailbox: %s\n",
S_OR(tmp->
mailbox,
"none"));
16117 ast_cli(a->fd,
"Variables:\n");
16118 for (v = tmp->
vars ; v ; v = v->
next)
16119 ast_cli(a->fd,
" %s = %s\n", v->
name, v->
value);
16121 ast_cli(a->fd,
"Destroy: %d\n", tmp->
destroy);
16122 ast_cli(a->fd,
"InAlarm: %d\n", tmp->
inalarm);
16123 ast_cli(a->fd,
"Signalling Type: %s\n", sig2str(tmp->
sig));
16124 ast_cli(a->fd,
"Radio: %d\n", tmp->
radio);
16125 ast_cli(a->fd,
"Owner: %s\n", tmp->
owner ? ast_channel_name(tmp->
owner) :
"<None>");
16129 ast_cli(a->fd,
"Confno: %d\n", tmp->
confno);
16130 ast_cli(a->fd,
"Propagated Conference: %d\n", tmp->
propconfno);
16131 ast_cli(a->fd,
"Real in conference: %d\n", tmp->
inconference);
16132 ast_cli(a->fd,
"DSP: %s\n", tmp->
dsp ?
"yes" :
"no");
16133 ast_cli(a->fd,
"Busy Detection: %s\n", tmp->
busydetect ?
"yes" :
"no");
16135 #if defined(BUSYDETECT_TONEONLY)
16136 ast_cli(a->fd,
" Busy Detector Helper: BUSYDETECT_TONEONLY\n");
16137 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
16138 ast_cli(a->fd,
" Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
16140 #ifdef BUSYDETECT_DEBUG
16141 ast_cli(a->fd,
" Busy Detector Debug: Enabled\n");
16143 ast_cli(a->fd,
" Busy Count: %d\n", tmp->
busycount);
16146 ast_cli(a->fd,
"TDD: %s\n", tmp->
tdd ?
"yes" :
"no");
16147 ast_cli(a->fd,
"Relax DTMF: %s\n", tmp->
dtmfrelax ?
"yes" :
"no");
16149 ast_cli(a->fd,
"Default law: %s\n", tmp->
law_default == DAHDI_LAW_MULAW ?
"ulaw" : tmp->
law_default == DAHDI_LAW_ALAW ?
"alaw" :
"unknown");
16150 ast_cli(a->fd,
"Fax Handled: %s\n", tmp->
faxhandled ?
"yes" :
"no");
16151 ast_cli(a->fd,
"Pulse phone: %s\n", tmp->
pulsedial ?
"yes" :
"no");
16153 snprintf(hwrxgain,
sizeof(hwrxgain),
"%.1f", tmp->
hwrxgain);
16158 snprintf(hwtxgain,
sizeof(hwtxgain),
"%.1f", tmp->
hwtxgain);
16162 ast_cli(a->fd,
"HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
16163 ast_cli(a->fd,
"SW Gains (RX/TX): %.2f/%.2f\n", tmp->
rxgain, tmp->
txgain);
16164 ast_cli(a->fd,
"Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->
txdrc);
16165 ast_cli(a->fd,
"DND: %s\n",
dahdi_dnd(tmp, -1) ?
"yes" :
"no");
16166 ast_cli(a->fd,
"Echo Cancellation:\n");
16169 ast_cli(a->fd,
"\t%u taps\n", tmp->
echocancel.head.tap_length);
16170 for (x = 0; x < tmp->
echocancel.head.param_count; x++) {
16171 ast_cli(a->fd,
"\t\t%s: %dd\n", tmp->
echocancel.params[x].name, tmp->
echocancel.params[x].value);
16173 ast_cli(a->fd,
"\t%scurrently %s\n", tmp->
echocanbridged ?
"" :
"(unless TDM bridged) ", tmp->
echocanon ?
"ON" :
"OFF");
16175 ast_cli(a->fd,
"\tnone\n");
16179 ast_cli(a->fd,
"Master Channel: %d\n", tmp->
master->
channel);
16180 for (x = 0; x < MAX_SLAVES; x++) {
16182 ast_cli(a->fd,
"Slave Channel: %d\n", tmp->
slaves[x]->
channel);
16186 char calldir[OR2_MAX_PATH];
16187 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
16188 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
16189 ast_cli(a->fd,
"MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
16190 ast_cli(a->fd,
"MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
16191 ast_cli(a->fd,
"MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
16192 ast_cli(a->fd,
"MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
16193 ast_cli(a->fd,
"MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ?
"Yes" :
"No");
16194 ast_cli(a->fd,
"MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
16195 ast_cli(a->fd,
"MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
16196 ast_cli(a->fd,
"MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
16197 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
16198 ast_cli(a->fd,
"MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ?
"Yes" :
"No");
16199 ast_cli(a->fd,
"MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ?
"Yes" :
"No");
16201 ast_cli(a->fd,
"MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ?
"Yes" :
"No");
16202 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16203 ast_cli(a->fd,
"MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ?
"Yes" :
"No");
16205 ast_cli(a->fd,
"MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ?
"Yes" :
"No");
16206 ast_cli(a->fd,
"MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ?
"Yes" :
"No");
16207 ast_cli(a->fd,
"MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ?
"Yes" :
"No");
16208 ast_cli(a->fd,
"MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ?
"Yes" :
"No");
16209 ast_cli(a->fd,
"MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ?
"Yes" :
"No");
16210 ast_cli(a->fd,
"MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
16211 ast_cli(a->fd,
"MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
16212 ast_cli(a->fd,
"MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
16213 ast_cli(a->fd,
"MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
16214 ast_cli(a->fd,
"MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
16215 ast_cli(a->fd,
"MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
16216 ast_cli(a->fd,
"MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir,
sizeof(calldir)));
16219 #if defined(HAVE_SS7)
16223 ast_cli(a->fd,
"CIC: %d\n", chan->
cic);
16230 ast_cli(a->fd,
"PRI Flags: ");
16232 ast_cli(a->fd,
"Resetting=%u ", chan->
resetting);
16235 ast_cli(a->fd,
"Call ");
16237 ast_cli(a->fd,
"Allocated ");
16239 ast_cli(a->fd,
"\n");
16240 if (tmp->logicalspan)
16241 ast_cli(a->fd,
"PRI Logical Span: %d\n", tmp->logicalspan);
16243 ast_cli(a->fd,
"PRI Logical Span: Implicit\n");
16246 memset(&ci, 0,
sizeof(ci));
16249 memset(&ci, 0,
sizeof(ci));
16250 if (!ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
16251 ast_cli(a->fd,
"Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (
unsigned)ci.confmode);
16253 if (!ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
16254 ast_cli(a->fd,
"Actual Confmute: %s\n", x ?
"Yes" :
"No");
16256 memset(&ps, 0,
sizeof(ps));
16257 if (ioctl(tmp->
subs[
SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
16258 ast_log(LOG_WARNING,
"Failed to get parameters on channel %d: %s\n", tmp->
channel, strerror(errno));
16260 ast_cli(a->fd,
"Hookstate (FXS only): %s\n", ps.rxisoffhook ?
"Offhook" :
"Onhook");
16263 ast_mutex_unlock(&
iflock);
16264 return CLI_SUCCESS;
16267 ast_mutex_unlock(&
iflock);
16269 ast_cli(a->fd,
"Unable to find given channel %d\n", channel);
16270 return CLI_FAILURE;
16278 e->
command =
"dahdi show cadences";
16280 "Usage: dahdi show cadences\n"
16281 " Shows all cadences currently defined\n";
16286 for (i = 0; i < num_cadence; i++) {
16288 char tmp[16], tmp2[64];
16289 snprintf(tmp,
sizeof(tmp),
"r%d: ", i + 1);
16290 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK,
sizeof(output));
16292 for (j = 0; j < 16; j++) {
16293 if (cadences[i].ringcadence[j] == 0)
16295 snprintf(tmp,
sizeof(tmp),
"%d", cadences[i].ringcadence[j]);
16297 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK,
sizeof(tmp2) - 1);
16299 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK,
sizeof(tmp2) - 1);
16301 strncat(output,
",",
sizeof(output) - strlen(output) - 1);
16302 strncat(output, tmp2,
sizeof(output) - strlen(output) - 1);
16304 ast_cli(a->fd,
"%s\n",output);
16306 return CLI_SUCCESS;
16309 static void build_alarm_info(
char *restrict alarmstr,
struct dahdi_spaninfo *spaninfo)
16311 alarmstr[0] =
'\0';
16312 if (spaninfo->alarms > 0) {
16313 if (spaninfo->alarms & DAHDI_ALARM_BLUE) {
16314 strcat(alarmstr,
"BLU/");
16316 if (spaninfo->alarms & DAHDI_ALARM_YELLOW) {
16317 strcat(alarmstr,
"YEL/");
16319 if (spaninfo->alarms & DAHDI_ALARM_RED) {
16320 strcat(alarmstr,
"RED/");
16322 if (spaninfo->alarms & DAHDI_ALARM_LOOPBACK) {
16323 strcat(alarmstr,
"LB/");
16325 if (spaninfo->alarms & DAHDI_ALARM_RECOVER) {
16326 strcat(alarmstr,
"REC/");
16328 if (spaninfo->alarms & DAHDI_ALARM_NOTOPEN) {
16329 strcat(alarmstr,
"NOP/");
16331 if (!strlen(alarmstr)) {
16332 strcat(alarmstr,
"UUU/");
16334 if (strlen(alarmstr)) {
16336 alarmstr[strlen(alarmstr) - 1] =
'\0';
16339 if (spaninfo->numchans) {
16340 strcpy(alarmstr,
"OK");
16342 strcpy(alarmstr,
"UNCONFIGURED");
16350 #define FORMAT "%4d %-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
16351 #define FORMAT2 "%4s %-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
16357 struct dahdi_spaninfo s;
16361 e->
command =
"dahdi show status";
16363 "Usage: dahdi show status\n"
16364 " Shows a list of DAHDI cards with status\n";
16369 ctl = open(
"/dev/dahdi/ctl", O_RDWR);
16371 ast_cli(a->fd,
"No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
16372 return CLI_FAILURE;
16374 ast_cli(a->fd, FORMAT2,
"Span",
"Description",
"Alarms",
"IRQ",
"bpviol",
"CRC",
"Framing",
"Coding",
"Options",
"LBO");
16376 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
16378 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
16382 build_alarm_info(alarmstr, &s);
16383 ast_cli(a->fd, FORMAT, span, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16384 s.lineconfig & DAHDI_CONFIG_D4 ?
"D4" :
16385 s.lineconfig & DAHDI_CONFIG_ESF ?
"ESF" :
16386 s.lineconfig & DAHDI_CONFIG_CCS ?
"CCS" :
16388 s.lineconfig & DAHDI_CONFIG_B8ZS ?
"B8ZS" :
16389 s.lineconfig & DAHDI_CONFIG_HDB3 ?
"HDB3" :
16390 s.lineconfig & DAHDI_CONFIG_AMI ?
"AMI" :
16392 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16393 s.lineconfig & DAHDI_CONFIG_NOTOPEN ?
"CRC4/YEL" :
"CRC4" :
16394 s.lineconfig & DAHDI_CONFIG_NOTOPEN ?
"YEL" :
"",
16400 return CLI_SUCCESS;
16407 int pseudo_fd = -1;
16408 struct dahdi_versioninfo vi;
16412 e->
command =
"dahdi show version";
16414 "Usage: dahdi show version\n"
16415 " Shows the DAHDI version in use\n";
16420 if ((pseudo_fd = open(
"/dev/dahdi/ctl", O_RDONLY)) < 0) {
16421 ast_cli(a->fd,
"Failed to open control file to get version.\n");
16422 return CLI_SUCCESS;
16425 strcpy(vi.version,
"Unknown");
16426 strcpy(vi.echo_canceller,
"Unknown");
16428 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16429 ast_cli(a->fd,
"Failed to get DAHDI version: %s\n", strerror(errno));
16431 ast_cli(a->fd,
"DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16435 return CLI_SUCCESS;
16447 e->
command =
"dahdi set hwgain {rx|tx}";
16449 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16450 " Sets the hardware gain on a given channel and overrides the\n"
16451 " value provided at module loadtime. Changes take effect\n"
16452 " immediately whether the channel is in use or not.\n"
16454 " <rx|tx> which direction do you want to change (relative to our module)\n"
16455 " <chan num> is the channel number relative to the device\n"
16456 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16459 " * hwgain is only supportable by hardware with analog ports because\n"
16460 " hwgain works on the analog side of an analog-digital conversion.\n";
16467 return CLI_SHOWUSAGE;
16469 if (!strcasecmp(
"rx", a->argv[3]))
16471 else if (!strcasecmp(
"tx", a->argv[3]))
16474 return CLI_SHOWUSAGE;
16476 channel = atoi(a->argv[4]);
16477 gain = atof(a->argv[5]);
16479 ast_mutex_lock(&
iflock);
16481 for (tmp = iflist; tmp; tmp = tmp->
next) {
16490 ast_cli(a->fd,
"Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16491 ast_mutex_unlock(&
iflock);
16492 return CLI_FAILURE;
16494 ast_cli(a->fd,
"Hardware %s gain set to %.1f dB on channel %d.\n",
16495 tx ?
"tx" :
"rx", gain, channel);
16507 ast_mutex_unlock(&
iflock);
16510 return CLI_SUCCESS;
16512 ast_cli(a->fd,
"Unable to find given channel %d\n", channel);
16513 return CLI_FAILURE;
16527 e->
command =
"dahdi set swgain {rx|tx}";
16529 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16530 " Sets the software gain on a given channel and overrides the\n"
16531 " value provided at module loadtime. Changes take effect\n"
16532 " immediately whether the channel is in use or not.\n"
16534 " <rx|tx> which direction do you want to change (relative to our module)\n"
16535 " <chan num> is the channel number relative to the device\n"
16536 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16543 return CLI_SHOWUSAGE;
16545 if (!strcasecmp(
"rx", a->argv[3]))
16547 else if (!strcasecmp(
"tx", a->argv[3]))
16550 return CLI_SHOWUSAGE;
16552 channel = atoi(a->argv[4]);
16553 gain = atof(a->argv[5]);
16555 ast_mutex_lock(&
iflock);
16556 for (tmp = iflist; tmp; tmp = tmp->
next) {
16567 res = set_actual_rxgain(tmp->
subs[
SUB_REAL].dfd, gain, tmp->rxdrc, tmp->
law);
16570 ast_cli(a->fd,
"Unable to set the software gain for channel %d\n", channel);
16571 ast_mutex_unlock(&
iflock);
16572 return CLI_FAILURE;
16575 ast_cli(a->fd,
"Software %s gain set to %.2f dB on channel %d.\n",
16576 tx ?
"tx" :
"rx", gain, channel);
16585 ast_mutex_unlock(&
iflock);
16588 return CLI_SUCCESS;
16590 ast_cli(a->fd,
"Unable to find given channel %d\n", channel);
16591 return CLI_FAILURE;
16603 e->
command =
"dahdi set dnd";
16605 "Usage: dahdi set dnd <chan#> <on|off>\n"
16606 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16607 " Changes take effect immediately.\n"
16608 " <chan num> is the channel number\n"
16609 " <on|off> Enable or disable DND mode?\n"
16617 return CLI_SHOWUSAGE;
16619 if ((channel = atoi(a->argv[3])) <= 0) {
16620 ast_cli(a->fd,
"Expected channel number, got '%s'\n", a->argv[3]);
16621 return CLI_SHOWUSAGE;
16629 ast_cli(a->fd,
"Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16630 return CLI_SHOWUSAGE;
16633 ast_mutex_lock(&
iflock);
16634 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->
next) {
16635 if (dahdi_chan->
channel != channel)
16642 ast_mutex_unlock(&
iflock);
16645 ast_cli(a->fd,
"Unable to find given channel %d\n", channel);
16646 return CLI_FAILURE;
16649 return CLI_SUCCESS;
16661 e->
command =
"dahdi set mwi";
16663 "Usage: dahdi set mwi <chan#> <on|off|reset>\n"
16664 " Sets/unsets MWI (Message Waiting Indicator) manually on a channel.\n"
16665 " This may be used regardless of whether the channel is assigned any mailboxes.\n"
16666 " When active, this setting will override the voicemail status to set MWI.\n"
16667 " Once cleared, the voicemail status will resume control of MWI.\n"
16668 " Changes are queued for when the channel is idle and persist until cleared.\n"
16669 " <chan num> is the channel number\n"
16670 " <on|off|reset> Enable, disable, or reset Message Waiting Indicator override?\n"
16678 return CLI_SHOWUSAGE;
16680 if ((channel = atoi(a->argv[3])) <= 0) {
16681 ast_cli(a->fd,
"Expected channel number, got '%s'\n", a->argv[3]);
16682 return CLI_SHOWUSAGE;
16689 }
else if (!strcmp(a->argv[4],
"reset")) {
16692 ast_cli(a->fd,
"Expected 'on' or 'off' or 'reset', got '%s'\n", a->argv[4]);
16693 return CLI_SHOWUSAGE;
16696 ast_mutex_lock(&
iflock);
16697 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->
next) {
16698 if (dahdi_chan->
channel != channel)
16704 ast_cli(a->fd,
"MWI '%s' queued for channel %d\n", on ?
"enable" :
"disable", channel);
16711 ast_mutex_unlock(&
iflock);
16714 ast_cli(a->fd,
"Unable to find given channel %d\n", channel);
16715 return CLI_FAILURE;
16718 return CLI_SUCCESS;
16722 AST_CLI_DEFINE(handle_dahdi_show_cadences,
"List cadences"),
16723 AST_CLI_DEFINE(dahdi_show_channels,
"Show active DAHDI channels"),
16724 AST_CLI_DEFINE(dahdi_show_channel,
"Show information on a channel"),
16725 AST_CLI_DEFINE(dahdi_destroy_channels,
"Destroy channels"),
16726 AST_CLI_DEFINE(dahdi_create_channels,
"Create channels"),
16727 AST_CLI_DEFINE(dahdi_restart_cmd,
"Fully restart DAHDI channels"),
16728 AST_CLI_DEFINE(dahdi_show_status,
"Show all DAHDI cards status"),
16729 AST_CLI_DEFINE(dahdi_show_version,
"Show the DAHDI version in use"),
16730 AST_CLI_DEFINE(dahdi_set_hwgain,
"Set hardware gain on a channel"),
16731 AST_CLI_DEFINE(dahdi_set_swgain,
"Set software gain on a channel"),
16732 AST_CLI_DEFINE(dahdi_set_dnd,
"Sets/resets DND (Do Not Disturb) mode on a channel"),
16733 AST_CLI_DEFINE(dahdi_set_mwi,
"Sets/unsets MWI (Message Waiting Indicator) manually on a channel"),
16739 static int dahdi_fake_event(
struct dahdi_pvt *p,
int mode)
16750 ast_log(LOG_WARNING,
"I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->
owner));
16755 static struct dahdi_pvt *find_channel(
int channel)
16759 ast_mutex_lock(&
iflock);
16760 for (p = iflist; p; p = p->
next) {
16765 ast_mutex_unlock(&
iflock);
16778 static struct dahdi_pvt *find_channel_from_str(
const char *channel)
16782 if (sscanf(channel,
"%30d", &chan_num) != 1) {
16787 return find_channel(chan_num);
16795 if (ast_strlen_zero(channel)) {
16799 p = find_channel_from_str(channel);
16814 if (ast_strlen_zero(channel)) {
16818 p = find_channel_from_str(channel);
16833 if (ast_strlen_zero(channel)) {
16837 p = find_channel_from_str(channel);
16842 if (!dahdi_analog_lib_handles(p->
sig, 0, 0)) {
16846 dahdi_fake_event(p,TRANSFER);
16851 static int action_transferhangup(
struct mansession *s,
const struct message *m)
16856 if (ast_strlen_zero(channel)) {
16860 p = find_channel_from_str(channel);
16865 if (!dahdi_analog_lib_handles(p->
sig, 0, 0)) {
16869 dahdi_fake_event(p,HANGUP);
16874 static int action_dahdidialoffhook(
struct mansession *s,
const struct message *m)
16881 if (ast_strlen_zero(channel)) {
16885 if (ast_strlen_zero(number)) {
16889 p = find_channel_from_str(channel);
16898 for (i = 0; i < strlen(number); i++) {
16899 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16900 dahdi_queue_frame(p, &f);
16906 static int action_dahdishowchannels(
struct mansession *s,
const struct message *m)
16913 int dahdichanquery;
16915 if (!dahdichannel || sscanf(dahdichannel,
"%30d", &dahdichanquery) != 1) {
16917 dahdichanquery = -1;
16921 if (!ast_strlen_zero(
id)) {
16922 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
16927 ast_mutex_lock(&
iflock);
16929 for (tmp = iflist; tmp; tmp = tmp->
next) {
16934 if (dahdichanquery > 0 && tmp->
channel != dahdichanquery)
16942 "Event: DAHDIShowChannels\r\n"
16943 "DAHDIChannel: %d\r\n"
16946 "AccountCode: %s\r\n"
16947 "Signalling: %s\r\n"
16948 "SignallingCode: %d\r\n"
16952 "Description: %s\r\n"
16956 ast_channel_name(tmp->
owner),
16957 ast_channel_uniqueid(tmp->
owner),
16958 ast_channel_accountcode(tmp->
owner),
16962 dahdi_dnd(tmp, -1) ?
"Enabled" :
"Disabled",
16967 "Event: DAHDIShowChannels\r\n"
16968 "DAHDIChannel: %d\r\n"
16969 "Signalling: %s\r\n"
16970 "SignallingCode: %d\r\n"
16974 "Description: %s\r\n"
16979 dahdi_dnd(tmp, -1) ?
"Enabled" :
"Disabled",
16986 ast_mutex_unlock(&
iflock);
16994 static int action_dahdishowstatus(
struct mansession *s,
const struct message *m)
17003 struct dahdi_spaninfo spaninfo;
17005 ctl = open(
"/dev/dahdi/ctl", O_RDWR);
17012 if (!ast_strlen_zero(
id)) {
17013 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
17017 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17018 spaninfo.spanno = span;
17019 res = ioctl(ctl, DAHDI_SPANSTAT, &spaninfo);
17024 build_alarm_info(alarmstr, &spaninfo);
17026 "Event: DAHDIShowStatus\r\n"
17028 "Description: %s\r\n"
17039 span, spaninfo.desc, alarmstr, spaninfo.irqmisses, spaninfo.bpvcount, spaninfo.crc4count,
17040 spaninfo.lineconfig & DAHDI_CONFIG_D4 ?
"D4" :
17041 spaninfo.lineconfig & DAHDI_CONFIG_ESF ?
"ESF" :
17042 spaninfo.lineconfig & DAHDI_CONFIG_CCS ?
"CCS" :
17044 spaninfo.lineconfig & DAHDI_CONFIG_B8ZS ?
"B8ZS" :
17045 spaninfo.lineconfig & DAHDI_CONFIG_HDB3 ?
"HDB3" :
17046 spaninfo.lineconfig & DAHDI_CONFIG_AMI ?
"AMI" :
17048 spaninfo.lineconfig & DAHDI_CONFIG_CRC4 ?
17049 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ?
"CRC4/YEL" :
"CRC4" :
17050 spaninfo.lineconfig & DAHDI_CONFIG_NOTOPEN ?
"YEL" :
"",
17051 lbostr[spaninfo.lbo],
17062 #if defined(HAVE_PRI)
17068 struct dahdi_pri *dspan;
17071 char action_id[256];
17072 const char *show_cmd =
"PRIShowSpans";
17075 if (!ast_strlen_zero(span_str)) {
17076 span_query = atoi(span_str);
17081 if (!ast_strlen_zero(
id)) {
17082 snprintf(action_id,
sizeof(action_id),
"ActionID: %s\r\n",
id);
17084 action_id[0] =
'\0';
17090 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
17091 dspan = &pris[idx];
17094 if (0 < span_query && dspan->pri.
span != span_query) {
17098 if (dspan->pri.
pri) {
17111 #if defined(HAVE_SS7)
17112 static int linkset_addsigchan(
int sigchan)
17114 struct dahdi_ss7 *link;
17117 struct dahdi_params params;
17118 struct dahdi_bufferinfo bi;
17119 struct dahdi_spaninfo si;
17122 ast_log(LOG_ERROR,
"Invalid sigchan!\n");
17125 if (cur_ss7type < 0) {
17126 ast_log(LOG_ERROR,
"Unspecified or invalid ss7type\n");
17129 if (cur_pointcode < 0) {
17130 ast_log(LOG_ERROR,
"Unspecified pointcode!\n");
17133 if (cur_adjpointcode < 0) {
17134 ast_log(LOG_ERROR,
"Unspecified adjpointcode!\n");
17137 if (cur_defaultdpc < 0) {
17138 ast_log(LOG_ERROR,
"Unspecified defaultdpc!\n");
17141 if (cur_networkindicator < 0) {
17142 ast_log(LOG_ERROR,
"Invalid networkindicator!\n");
17145 link = ss7_resolve_linkset(cur_linkset);
17147 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17150 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
17151 ast_log(LOG_ERROR,
"Too many sigchans on linkset %d\n", cur_linkset);
17155 curfd = link->ss7.numsigchans;
17158 link->ss7.fds[curfd] = open(
"/dev/dahdi/channel", O_RDWR, 0600);
17159 if (link->ss7.fds[curfd] < 0) {
17160 ast_log(LOG_ERROR,
"Unable to open SS7 sigchan %d (%s)\n", sigchan,
17164 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
17165 dahdi_close_ss7_fd(link, curfd);
17166 ast_log(LOG_ERROR,
"Unable to specify SS7 sigchan %d (%s)\n", sigchan,
17172 memset(¶ms, 0,
sizeof(params));
17173 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
17175 dahdi_close_ss7_fd(link, curfd);
17176 ast_log(LOG_ERROR,
"Unable to get parameters for sigchan %d (%s)\n", sigchan,
17180 if (params.sigtype != DAHDI_SIG_HDLCFCS
17181 && params.sigtype != DAHDI_SIG_HARDHDLC
17182 && params.sigtype != DAHDI_SIG_MTP2) {
17183 dahdi_close_ss7_fd(link, curfd);
17184 ast_log(LOG_ERROR,
"sigchan %d is not in HDLC/FCS mode.\n", sigchan);
17189 memset(&bi, 0,
sizeof(bi));
17190 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
17191 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
17194 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
17195 ast_log(LOG_ERROR,
"Unable to set appropriate buffering on channel %d: %s\n",
17196 sigchan, strerror(errno));
17197 dahdi_close_ss7_fd(link, curfd);
17202 memset(&si, 0,
sizeof(si));
17203 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
17205 dahdi_close_ss7_fd(link, curfd);
17206 ast_log(LOG_ERROR,
"Unable to get span state for sigchan %d (%s)\n", sigchan,
17210 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
17211 (params.sigtype == DAHDI_SIG_MTP2)
17212 ? SS7_TRANSPORT_DAHDIMTP2
17213 : SS7_TRANSPORT_DAHDIDCHAN,
17214 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
17216 dahdi_close_ss7_fd(link, curfd);
17220 ++link->ss7.numsigchans;
17226 #if defined(HAVE_SS7)
17232 e->
command =
"ss7 set debug {on|off} linkset";
17234 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
17235 " Enables debugging on a given SS7 linkset\n";
17242 return CLI_SHOWUSAGE;
17245 span = atoi(a->argv[5]);
17246 if ((span < 1) || (span > NUM_SPANS)) {
17247 ast_cli(a->fd,
"Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
17248 return CLI_SUCCESS;
17250 if (!linksets[span-1].ss7.ss7) {
17251 ast_cli(a->fd,
"No SS7 running on linkset %d\n", span);
17253 if (!strcasecmp(a->argv[3],
"on")) {
17254 linksets[span - 1].ss7.debug = 1;
17256 ast_cli(a->fd,
"Enabled debugging on linkset %d\n", span);
17258 linksets[span - 1].ss7.debug = 0;
17259 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
17260 ast_cli(a->fd,
"Disabled debugging on linkset %d\n", span);
17264 return CLI_SUCCESS;
17268 #if defined(HAVE_SS7)
17278 e->
command =
"ss7 {block|unblock} cic";
17280 "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
17281 " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
17287 if (a->argc == 6) {
17288 linkset = atoi(a->argv[3]);
17290 return CLI_SHOWUSAGE;
17293 if (!strcasecmp(a->argv[1],
"block")) {
17295 }
else if (strcasecmp(a->argv[1],
"unblock")) {
17296 return CLI_SHOWUSAGE;
17299 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17300 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17301 return CLI_SUCCESS;
17304 if (!linksets[linkset-1].ss7.ss7) {
17305 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17306 return CLI_SUCCESS;
17309 cic = atoi(a->argv[5]);
17311 ast_cli(a->fd,
"Invalid CIC specified!\n");
17312 return CLI_SUCCESS;
17315 dpc = atoi(a->argv[4]);
17317 ast_cli(a->fd,
"Invalid DPC specified!\n");
17318 return CLI_SUCCESS;
17321 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
17322 if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
17323 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
17324 if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
17325 if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
17326 ast_cli(a->fd,
"Unable to allocate new ss7call\n");
17328 ast_cli(a->fd,
"Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ?
"" :
"un", linkset, cic, dpc);
17330 }
else if (!do_block && blocked) {
17331 ast_cli(a->fd,
"CIC %d is hardware locally blocked!\n", cic);
17333 ast_cli(a->fd,
"CIC %d %s locally blocked\n", cic, do_block ?
"already" :
"is not");
17335 return CLI_SUCCESS;
17339 ast_cli(a->fd,
"Invalid CIC specified!\n");
17340 return CLI_SUCCESS;
17344 #if defined(HAVE_SS7)
17356 e->
command =
"ss7 {reset|block|unblock} linkset";
17358 "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
17359 " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
17365 if (a->argc == 4) {
17366 linkset = atoi(a->argv[3]);
17368 return CLI_SHOWUSAGE;
17371 if (!strcasecmp(a->argv[1],
"block")) {
17372 do_what = DO_BLOCK;
17373 }
else if (!strcasecmp(a->argv[1],
"unblock")) {
17374 do_what = DO_UNBLOCK;
17375 }
else if (!strcasecmp(a->argv[1],
"reset")) {
17376 do_what = DO_RESET;
17378 return CLI_SHOWUSAGE;
17381 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17382 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17383 return CLI_SUCCESS;
17386 if (!linksets[linkset - 1].ss7.ss7) {
17387 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17388 return CLI_SUCCESS;
17391 for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
17393 if (linksets[linkset - 1].ss7.pvts[i]) {
17397 if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
17398 ast_cli(a->fd,
"Sent remote %s request on CIC %d\n",
17399 (do_what == DO_BLOCK) ?
"blocking" :
"unblocking",
17400 linksets[linkset - 1].ss7.pvts[i]->cic);
17404 if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
17405 linksets[linkset - 1].ss7.pvts[i]->cic,
17406 linksets[linkset - 1].ss7.pvts[i]->dpc)) {
17407 ast_cli(a->fd,
"Sent reset request on CIC %d\n",
17408 linksets[linkset - 1].ss7.pvts[i]->cic);
17415 return CLI_SUCCESS;
17419 #if defined(HAVE_SS7)
17422 int linkset, cic, range, chanpos;
17423 int i, dpc, orient = 0;
17425 unsigned char state[255];
17429 e->
command =
"ss7 {block|unblock} group";
17431 "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
17432 " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
17438 if (a->argc == 7 || a->argc == 8) {
17439 linkset = atoi(a->argv[3]);
17441 return CLI_SHOWUSAGE;
17444 if (!strcasecmp(a->argv[1],
"block")) {
17446 }
else if (strcasecmp(a->argv[1],
"unblock")) {
17447 return CLI_SHOWUSAGE;
17450 if (a->argc == 8) {
17451 if (!strcasecmp(a->argv[7],
"H")) {
17454 return CLI_SHOWUSAGE;
17458 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17459 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17460 return CLI_SUCCESS;
17463 if (!linksets[linkset-1].ss7.ss7) {
17464 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17465 return CLI_SUCCESS;
17468 cic = atoi(a->argv[5]);
17470 ast_cli(a->fd,
"Invalid CIC specified!\n");
17471 return CLI_SUCCESS;
17474 range = atoi(a->argv[6]);
17476 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17477 ast_cli(a->fd,
"Invalid range specified!\n");
17478 return CLI_SUCCESS;
17481 dpc = atoi(a->argv[4]);
17483 ast_cli(a->fd,
"Invalid DPC specified!\n");
17484 return CLI_SUCCESS;
17487 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17488 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17489 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17490 ast_cli(a->fd,
"Invalid CIC/RANGE\n");
17491 return CLI_SHOWUSAGE;
17494 memset(state, 0,
sizeof(state));
17495 for (i = 0; i <= range; ++i) {
17500 chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
17501 if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
17502 ast_cli(a->fd,
"Unable allocate new ss7call\n");
17504 ast_cli(a->fd,
"Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
17505 orient ?
" hardware" :
"", do_block ?
"" :
"un", linkset, cic, range);
17508 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17511 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17512 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17514 return CLI_SUCCESS;
17518 #if defined(HAVE_SS7)
17521 int linkset, cic, range;
17526 e->
command =
"ss7 reset group";
17528 "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
17529 " Send a GRS for the given CIC range on the specified linkset\n";
17535 if (a->argc == 7) {
17536 linkset = atoi(a->argv[3]);
17538 return CLI_SHOWUSAGE;
17541 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17542 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
17543 return CLI_SUCCESS;
17546 if (!linksets[linkset-1].ss7.ss7) {
17547 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17548 return CLI_SUCCESS;
17551 cic = atoi(a->argv[5]);
17554 ast_cli(a->fd,
"Invalid CIC specified!\n");
17555 return CLI_SUCCESS;
17558 range = atoi(a->argv[6]);
17559 if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
17560 ast_cli(a->fd,
"Invalid range specified!\n");
17561 return CLI_SUCCESS;
17564 dpc = atoi(a->argv[4]);
17566 ast_cli(a->fd,
"Invalid DPC specified!\n");
17567 return CLI_SUCCESS;
17570 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17571 if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17572 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17573 ast_cli(a->fd,
"Invalid CIC/RANGE\n");
17574 return CLI_SHOWUSAGE;
17577 if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17578 ast_cli(a->fd,
"Unable to allocate new ss7call\n");
17580 ast_cli(a->fd,
"GRS sent ... \n");
17583 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17586 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17587 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17589 return CLI_SUCCESS;
17593 #if defined(HAVE_SS7)
17600 e->
command =
"ss7 show calls";
17602 "Usage: ss7 show calls <linkset>\n"
17603 " Show SS7 calls on the specified linkset\n";
17609 if (a->argc == 4) {
17610 linkset = atoi(a->argv[3]);
17612 return CLI_SHOWUSAGE;
17615 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17616 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17617 return CLI_SUCCESS;
17620 if (!linksets[linkset-1].ss7.ss7) {
17621 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17622 return CLI_SUCCESS;
17625 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17626 isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17627 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17629 return CLI_SUCCESS;
17633 #if defined(HAVE_SS7)
17636 int linkset, cic, res;
17641 e->
command =
"ss7 reset cic";
17643 "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17644 " Send a RSC for the given CIC on the specified linkset\n";
17650 if (a->argc == 6) {
17651 linkset = atoi(a->argv[3]);
17653 return CLI_SHOWUSAGE;
17656 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17657 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17658 return CLI_SUCCESS;
17661 if (!linksets[linkset-1].ss7.ss7) {
17662 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17663 return CLI_SUCCESS;
17666 cic = atoi(a->argv[5]);
17669 ast_cli(a->fd,
"Invalid CIC specified!\n");
17670 return CLI_SUCCESS;
17673 dpc = atoi(a->argv[4]);
17675 ast_cli(a->fd,
"Invalid DPC specified!\n");
17676 return CLI_SUCCESS;
17679 res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17681 ast_cli(a->fd,
"%s RSC for linkset %d on CIC %d DPC %d\n", res ?
"Sent" :
"Failed", linkset, cic, dpc);
17683 return CLI_SUCCESS;
17687 #if defined(HAVE_SS7)
17692 unsigned int arg = 0;
17699 "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17700 " Send a NET MNG message\n"
17701 " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17708 return CLI_SHOWUSAGE;
17711 linkset = atoi(a->argv[2]);
17712 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17713 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17714 return CLI_SUCCESS;
17716 if (!linksets[linkset-1].ss7.ss7) {
17717 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17718 return CLI_SUCCESS;
17721 slc = atoi(a->argv[3]);
17723 if (a->argc == 6) {
17724 arg = atoi(a->argv[5]);
17727 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17728 res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17729 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17732 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17733 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17736 ast_cli(a->fd,
"%s", res);
17738 return CLI_SUCCESS;
17742 #if defined(HAVE_SS7)
17746 unsigned int slc = 0;
17750 e->
command =
"ss7 restart mtp3";
17752 "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17760 return CLI_SHOWUSAGE;
17763 linkset = atoi(a->argv[3]);
17764 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17765 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17766 return CLI_SUCCESS;
17768 if (!linksets[linkset-1].ss7.ss7) {
17769 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17770 return CLI_SUCCESS;
17773 slc = atoi(a->argv[4]);
17775 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17776 mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17777 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17780 if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17781 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17784 return CLI_SUCCESS;
17788 #if defined(HAVE_SS7)
17795 e->
command =
"ss7 show linkset";
17797 "Usage: ss7 show linkset <span>\n"
17798 " Shows the status of an SS7 linkset.\n";
17805 return CLI_SHOWUSAGE;
17808 linkset = atoi(a->argv[3]);
17809 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17810 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17811 return CLI_SUCCESS;
17813 ss7 = &linksets[linkset - 1].ss7;
17815 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17816 return CLI_SUCCESS;
17819 ast_cli(a->fd,
"SS7 flags: 0x%x\n", ss7->
flags);
17820 ast_cli(a->fd,
"SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ?
"Up" :
"Down");
17821 ast_cli(a->fd,
"SS7 calling nai: %i\n", ss7->
calling_nai);
17822 ast_cli(a->fd,
"SS7 called nai: %i\n", ss7->
called_nai);
17823 ast_cli(a->fd,
"SS7 nationalprefix: %s\n", ss7->
nationalprefix);
17825 ast_cli(a->fd,
"SS7 unknownprefix: %s\n", ss7->
unknownprefix);
17826 ast_cli(a->fd,
"SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17828 ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17830 return CLI_SUCCESS;
17834 #if defined(HAVE_SS7)
17841 e->
command =
"ss7 show channels";
17843 "Usage: ss7 show channels\n"
17844 " Displays SS7 channel information at a glance.\n";
17850 if (a->argc != 3) {
17851 return CLI_SHOWUSAGE;
17854 sig_ss7_cli_show_channels_header(a->fd);
17855 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17856 if (linksets[linkset].ss7.ss7) {
17857 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17860 return CLI_SUCCESS;
17864 #if defined(HAVE_SS7)
17867 #define FORMAT "%5s %5s %6s %12s %-12s\n"
17868 #define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17869 int i, linkset, dpc = 0;
17876 e->
command =
"ss7 show cics";
17878 "Usage: ss7 show cics <linkset> [dpc]\n"
17879 " Shows the cics of an SS7 linkset.\n";
17885 if (a->argc < 4 || a->argc > 5) {
17886 return CLI_SHOWUSAGE;
17889 linkset = atoi(a->argv[3]);
17891 if ((linkset < 1) || (linkset > NUM_SPANS)) {
17892 ast_cli(a->fd,
"Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17893 return CLI_SUCCESS;
17896 if (!linksets[linkset-1].ss7.ss7) {
17897 ast_cli(a->fd,
"No SS7 running on linkset %d\n", linkset);
17898 return CLI_SUCCESS;
17900 ss7 = &linksets[linkset-1].ss7;
17902 if (a->argc == 5) {
17903 dpc = atoi(a->argv[4]);
17905 ast_cli(a->fd,
"Invalid DPC specified!\n");
17906 return CLI_SUCCESS;
17910 ast_cli(a->fd, FORMAT,
"CIC",
"DPC",
"DAHDI",
"STATE",
"BLOCKING");
17912 for (i = 0; i < ss7->numchans; i++) {
17913 if (!dpc || (ss7->
pvts[i] && ss7->
pvts[i]->
dpc == dpc)) {
17916 if (ss7->
pvts[i]->owner) {
17921 state =
"NotInServ";
17927 strcpy(blocking,
"L:");
17929 strcat(blocking,
"M");
17931 strcat(blocking,
" ");
17935 strcat(blocking,
"H");
17937 strcat(blocking,
" ");
17940 strcpy(blocking,
" ");
17944 strcat(blocking,
" R:");
17946 strcat(blocking,
"M");
17948 strcat(blocking,
" ");
17952 strcat(blocking,
"H");
17954 strcat(blocking,
" ");
17962 return CLI_SUCCESS;
17968 #if defined(HAVE_SS7)
17973 e->
command =
"ss7 show version";
17975 "Usage: ss7 show version\n"
17976 " Show the libss7 version\n";
17982 ast_cli(a->fd,
"libss7 version: %s\n", ss7_get_version());
17984 return CLI_SUCCESS;
17988 #if defined(HAVE_SS7)
17990 AST_CLI_DEFINE(handle_ss7_debug,
"Enables SS7 debugging on a linkset"),
17991 AST_CLI_DEFINE(handle_ss7_cic_blocking,
"Blocks/Unblocks the given CIC"),
17992 AST_CLI_DEFINE(handle_ss7_linkset_mng,
"Resets/Blocks/Unblocks all CICs on a linkset"),
17993 AST_CLI_DEFINE(handle_ss7_group_blocking,
"Blocks/Unblocks the given CIC range"),
17994 AST_CLI_DEFINE(handle_ss7_reset_cic,
"Resets the given CIC"),
17995 AST_CLI_DEFINE(handle_ss7_group_reset,
"Resets the given CIC range"),
17996 AST_CLI_DEFINE(handle_ss7_mtp3_restart,
"Restart a link"),
17997 AST_CLI_DEFINE(handle_ss7_net_mng,
"Send an NET MNG message"),
17998 AST_CLI_DEFINE(handle_ss7_show_linkset,
"Shows the status of a linkset"),
17999 AST_CLI_DEFINE(handle_ss7_show_channels,
"Displays SS7 channel information"),
18000 AST_CLI_DEFINE(handle_ss7_show_calls,
"Show ss7 calls"),
18001 AST_CLI_DEFINE(handle_ss7_show_cics,
"Show cics on a linkset"),
18002 AST_CLI_DEFINE(handle_ss7_version,
"Displays libss7 version"),
18006 #if defined(HAVE_PRI)
18007 #if defined(HAVE_PRI_CCSS)
18033 pvt = ast_channel_tech_pvt(chan);
18034 if (dahdi_sig_pri_lib_handles(pvt->
sig)) {
18035 pvt_chan = pvt->sig_pvt;
18054 #if defined(HAVE_PRI)
18055 #if defined(HAVE_PRI_CCSS)
18067 static void dahdi_pri_cc_agent_destructor(
struct ast_cc_agent *agent)
18076 #if defined(HAVE_PRI)
18077 #if defined(HAVE_PRI_CCSS)
18080 .init = dahdi_pri_cc_agent_init,
18089 .destructor = dahdi_pri_cc_agent_destructor,
18094 #if defined(HAVE_PRI)
18095 #if defined(HAVE_PRI_CCSS)
18108 static int __unload_module(
void)
18111 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18116 for (i = 0; i < NUM_SPANS; i++) {
18117 if (pris[i].pri.
master != AST_PTHREADT_NULL) {
18118 pthread_cancel(pris[i].pri.
master);
18119 pthread_kill(pris[i].pri.
master, SIGURG);
18124 #ifdef HAVE_PRI_PROG_W_CAUSE
18128 #if defined(HAVE_SS7)
18129 for (i = 0; i < NUM_SPANS; i++) {
18130 if (linksets[i].ss7.
master != AST_PTHREADT_NULL) {
18131 pthread_cancel(linksets[i].ss7.
master);
18132 pthread_kill(linksets[i].ss7.
master, SIGURG);
18137 #if defined(HAVE_OPENR2)
18138 dahdi_r2_destroy_links();
18154 #if defined(HAVE_PRI)
18163 ast_mutex_lock(&
iflock);
18164 for (p = iflist; p; p = p->
next) {
18168 ast_mutex_unlock(&
iflock);
18179 destroy_all_channels();
18181 #if defined(HAVE_PRI)
18182 for (i = 0; i < NUM_SPANS; i++) {
18183 if (pris[i].pri.
master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
18184 pthread_join(pris[i].pri.
master, NULL);
18187 dahdi_close_pri_fd(&(pris[i]), j);
18191 #if defined(HAVE_PRI_CCSS)
18198 #if defined(HAVE_SS7)
18199 for (i = 0; i < NUM_SPANS; i++) {
18200 if (linksets[i].ss7.
master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
18201 pthread_join(linksets[i].ss7.
master, NULL);
18204 dahdi_close_ss7_fd(&(linksets[i]), j);
18206 if (linksets[i].ss7.ss7) {
18207 ss7_destroy(linksets[i].ss7.ss7);
18208 linksets[i].ss7.ss7 = NULL;
18212 ast_cond_destroy(&ss_thread_complete);
18214 dahdi_native_unload();
18222 static int unload_module(
void)
18224 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18228 for (y = 0; y < NUM_SPANS; y++)
18229 ast_mutex_destroy(&pris[y].pri.
lock);
18231 #if defined(HAVE_SS7)
18232 for (y = 0; y < NUM_SPANS; y++)
18233 ast_mutex_destroy(&linksets[y].ss7.
lock);
18235 return __unload_module();
18238 static int build_channels(
struct dahdi_chan_conf *conf,
const char *value,
int reload,
int lineno)
18241 int x, start, finish;
18244 if ((reload == 0) && (conf->chan.
sig < 0) && !conf->
is_sig_auto) {
18245 ast_log(LOG_ERROR,
"Signalling must be specified before any channels are.\n");
18251 while ((chan = strsep(&c,
","))) {
18252 if (sscanf(chan,
"%30d-%30d", &start, &finish) == 2) {
18254 }
else if (sscanf(chan,
"%30d", &start)) {
18257 }
else if (!strcasecmp(chan,
"pseudo")) {
18258 finish = start = CHAN_PSEUDO;
18260 ast_log(LOG_ERROR,
"Syntax error parsing '%s' at '%s'\n", value, chan);
18263 if (finish < start) {
18264 ast_log(LOG_WARNING,
"Silliness: %d < %d\n", start, finish);
18270 for (x = start; x <= finish; x++) {
18272 (x < conf->wanted_channels_start ||
18277 tmp =
mkintf(x, conf, reload);
18280 ast_verb(3,
"%s channel %d, %s signalling\n", reload ?
"Reconfigured" :
"Registered", x, sig2str(tmp->
sig));
18282 ast_log(LOG_ERROR,
"Unable to %s channel '%s'\n",
18283 (reload == 1) ?
"reconfigure" :
"register", value);
18286 if (x == CHAN_PSEUDO) {
18297 #define MAX_CHANLIST_LEN 80
18299 static void process_echocancel(
struct dahdi_chan_conf *confp,
const char *data,
unsigned int line)
18302 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
18303 unsigned int param_count;
18306 if (!(param_count = ast_app_separate_args(parse,
',', params, ARRAY_LEN(params))))
18313 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
18315 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
18318 confp->chan.
echocancel.head.tap_length = 128;
18322 for (x = 1; x < param_count; x++) {
18328 if (ast_app_separate_args(params[x],
'=', (
char **) ¶m, 2) < 1) {
18329 ast_log(LOG_WARNING,
"Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
18333 if (ast_strlen_zero(param.name) || (strlen(param.name) >
sizeof(confp->chan.
echocancel.params[0].name)-1)) {
18334 ast_log(LOG_WARNING,
"Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
18338 strcpy(confp->chan.
echocancel.params[confp->chan.
echocancel.head.param_count].name, param.name);
18341 if (sscanf(param.value,
"%30d", &confp->chan.
echocancel.params[confp->chan.
echocancel.head.param_count].value) != 1) {
18342 ast_log(LOG_WARNING,
"Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
18350 #if defined(HAVE_PRI)
18351 #if defined(HAVE_PRI_DISPLAY_TEXT)
18361 static unsigned long dahdi_display_text_option(
const char *value)
18365 unsigned long options;
18371 opt_str = strsep(&val_str,
",");
18380 if (!strcasecmp(opt_str,
"block")) {
18381 options |= PRI_DISPLAY_OPTION_BLOCK;
18382 }
else if (!strcasecmp(opt_str,
"name_initial")) {
18383 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
18384 }
else if (!strcasecmp(opt_str,
"name_update")) {
18385 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
18386 }
else if (!strcasecmp(opt_str,
"name")) {
18387 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
18388 }
else if (!strcasecmp(opt_str,
"text")) {
18389 options |= PRI_DISPLAY_OPTION_TEXT;
18397 #if defined(HAVE_PRI)
18398 #if defined(HAVE_PRI_DATETIME_SEND)
18408 static int dahdi_datetime_send_option(
const char *value)
18412 option = PRI_DATE_TIME_SEND_DEFAULT;
18415 option = PRI_DATE_TIME_SEND_NO;
18416 }
else if (!strcasecmp(value,
"date")) {
18417 option = PRI_DATE_TIME_SEND_DATE;
18418 }
else if (!strcasecmp(value,
"date_hh")) {
18419 option = PRI_DATE_TIME_SEND_DATE_HH;
18420 }
else if (!strcasecmp(value,
"date_hhmm")) {
18421 option = PRI_DATE_TIME_SEND_DATE_HHMM;
18422 }
else if (!strcasecmp(value,
"date_hhmmss")) {
18423 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
18432 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
18434 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
18438 int count_pattern = 0;
18444 if (!sscanf(v->
value,
"%30d", &norval) && count_pattern == 0) {
18445 ast_log(LOG_ERROR,
"busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18449 busy_cadence->
pattern[count_pattern] = norval;
18452 if (count_pattern == 4) {
18456 temp = strchr(v->
value,
',');
18457 if (temp == NULL) {
18460 v->
value = temp + 1;
18462 busy_cadence->
length = count_pattern;
18464 if (count_pattern % 2 != 0) {
18466 ast_log(LOG_ERROR,
"busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
18478 user_has_defined_cadences = 0;
18480 for (; v; v = v->
next) {
18485 if (!strcasecmp(v->
name,
"channel") || !strcasecmp(v->
name,
"channels")) {
18487 ast_log(LOG_WARNING,
"Channel '%s' ignored.\n", v->
value);
18490 if (build_channels(confp, v->
value, reload, v->lineno)) {
18492 ast_log(LOG_WARNING,
"Channel '%s' failure ignored: ignore_failed_channels.\n", v->
value);
18499 }
else if (!strcasecmp(v->
name,
"ignore_failed_channels")) {
18501 }
else if (!strcasecmp(v->
name,
"buffers")) {
18503 ast_log(LOG_WARNING,
"Using default buffer policy.\n");
18504 confp->chan.
buf_no = numbufs;
18505 confp->chan.
buf_policy = DAHDI_POLICY_IMMEDIATE;
18507 }
else if (!strcasecmp(v->
name,
"faxbuffers")) {
18511 }
else if (!strcasecmp(v->
name,
"dahdichan")) {
18514 }
else if (!strcasecmp(v->
name,
"usedistinctiveringdetection")) {
18516 }
else if (!strcasecmp(v->
name,
"distinctiveringaftercid")) {
18518 }
else if (!strcasecmp(v->
name,
"dring1context")) {
18520 }
else if (!strcasecmp(v->
name,
"dring2context")) {
18522 }
else if (!strcasecmp(v->
name,
"dring3context")) {
18524 }
else if (!strcasecmp(v->
name,
"dring1range")) {
18525 confp->chan.
drings.ringnum[0].range = atoi(v->
value);
18526 }
else if (!strcasecmp(v->
name,
"dring2range")) {
18527 confp->chan.
drings.ringnum[1].range = atoi(v->
value);
18528 }
else if (!strcasecmp(v->
name,
"dring3range")) {
18529 confp->chan.
drings.ringnum[2].range = atoi(v->
value);
18530 }
else if (!strcasecmp(v->
name,
"dring1")) {
18531 sscanf(v->
value,
"%30d,%30d,%30d", &confp->chan.
drings.ringnum[0].ring[0], &confp->chan.
drings.ringnum[0].ring[1], &confp->chan.
drings.ringnum[0].ring[2]);
18532 }
else if (!strcasecmp(v->
name,
"dring2")) {
18533 sscanf(v->
value,
"%30d,%30d,%30d", &confp->chan.
drings.ringnum[1].ring[0], &confp->chan.
drings.ringnum[1].ring[1], &confp->chan.
drings.ringnum[1].ring[2]);
18534 }
else if (!strcasecmp(v->
name,
"dring3")) {
18535 sscanf(v->
value,
"%30d,%30d,%30d", &confp->chan.
drings.ringnum[2].ring[0], &confp->chan.
drings.ringnum[2].ring[1], &confp->chan.
drings.ringnum[2].ring[2]);
18536 }
else if (!strcasecmp(v->
name,
"usecallerid")) {
18538 }
else if (!strcasecmp(v->
name,
"cidsignalling")) {
18539 if (!strcasecmp(v->
value,
"bell"))
18541 else if (!strcasecmp(v->
value,
"v23"))
18543 else if (!strcasecmp(v->
value,
"dtmf"))
18545 else if (!strcasecmp(v->
value,
"smdi"))
18547 else if (!strcasecmp(v->
value,
"v23_jp"))
18551 }
else if (!strcasecmp(v->
name,
"cidstart")) {
18552 if (!strcasecmp(v->
value,
"ring"))
18553 confp->chan.
cid_start = CID_START_RING;
18554 else if (!strcasecmp(v->
value,
"polarity_in"))
18555 confp->chan.
cid_start = CID_START_POLARITY_IN;
18556 else if (!strcasecmp(v->
value,
"polarity"))
18557 confp->chan.
cid_start = CID_START_POLARITY;
18558 else if (!strcasecmp(v->
value,
"dtmf"))
18559 confp->chan.
cid_start = CID_START_DTMF_NOALERT;
18561 confp->chan.
cid_start = CID_START_RING;
18562 }
else if (!strcasecmp(v->
name,
"threewaycalling")) {
18564 }
else if (!strcasecmp(v->
name,
"threewaysilenthold")) {
18566 }
else if (!strcasecmp(v->
name,
"cancallforward")) {
18568 }
else if (!strcasecmp(v->
name,
"relaxdtmf")) {
18573 }
else if (!strcasecmp(v->
name,
"mailbox")) {
18575 }
else if (!strcasecmp(v->
name,
"description")) {
18577 }
else if (!strcasecmp(v->
name,
"hasvoicemail")) {
18583 if (strchr(cat,
'@')) {
18587 "%s@default", cat);
18590 }
else if (!strcasecmp(v->
name,
"adsi")) {
18592 }
else if (!strcasecmp(v->
name,
"usesmdi")) {
18594 }
else if (!strcasecmp(v->
name,
"smdiport")) {
18596 }
else if (!strcasecmp(v->
name,
"transfer")) {
18598 }
else if (!strcasecmp(v->
name,
"canpark")) {
18600 }
else if (!strcasecmp(v->
name,
"echocancelwhenbridged")) {
18602 }
else if (!strcasecmp(v->
name,
"busydetect")) {
18604 }
else if (!strcasecmp(v->
name,
"busycount")) {
18606 }
else if (!strcasecmp(v->
name,
"busypattern")) {
18608 }
else if (!strcasecmp(v->
name,
"calledsubscriberheld")) {
18610 }
else if (!strcasecmp(v->
name,
"callprogress")) {
18614 }
else if (!strcasecmp(v->
name,
"waitfordialtone")) {
18616 }
else if (!strcasecmp(v->
name,
"dialtone_detect")) {
18617 if (!strcasecmp(v->
value,
"always")) {
18626 }
else if (!strcasecmp(v->
name,
"faxdetect")) {
18628 if (!strcasecmp(v->
value,
"incoming")) {
18629 confp->chan.
callprogress |= CALLPROGRESS_FAX_INCOMING;
18630 }
else if (!strcasecmp(v->
value,
"outgoing")) {
18631 confp->chan.
callprogress |= CALLPROGRESS_FAX_OUTGOING;
18633 confp->chan.
callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
18634 }
else if (!strcasecmp(v->
name,
"faxdetect_timeout")) {
18638 }
else if (!strcasecmp(v->
name,
"firstdigit_timeout")) {
18643 }
else if (!strcasecmp(v->
name,
"interdigit_timeout")) {
18648 }
else if (!strcasecmp(v->
name,
"matchdigit_timeout")) {
18653 }
else if (!strcasecmp(v->
name,
"echocancel")) {
18654 process_echocancel(confp, v->
value, v->lineno);
18655 }
else if (!strcasecmp(v->
name,
"echotraining")) {
18656 if (sscanf(v->
value,
"%30d", &y) == 1) {
18657 if ((y < 10) || (y > 4000)) {
18658 ast_log(LOG_WARNING,
"Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18666 }
else if (!strcasecmp(v->
name,
"hidecallerid")) {
18668 }
else if (!strcasecmp(v->
name,
"hidecalleridname")) {
18670 }
else if (!strcasecmp(v->
name,
"pulsedial")) {
18672 }
else if (!strcasecmp(v->
name,
"callreturn")) {
18674 }
else if (!strcasecmp(v->
name,
"callwaiting")) {
18676 }
else if (!strcasecmp(v->
name,
"callwaitingcallerid")) {
18678 }
else if (!strcasecmp(v->
name,
"context")) {
18680 }
else if (!strcasecmp(v->
name,
"language")) {
18682 }
else if (!strcasecmp(v->
name,
"progzone")) {
18684 }
else if (!strcasecmp(v->
name,
"mohinterpret")
18685 ||!strcasecmp(v->
name,
"musiconhold") || !strcasecmp(v->
name,
"musicclass")) {
18687 }
else if (!strcasecmp(v->
name,
"mohsuggest")) {
18689 }
else if (!strcasecmp(v->
name,
"parkinglot")) {
18691 }
else if (!strcasecmp(v->
name,
"stripmsd")) {
18692 ast_log(LOG_NOTICE,
"Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->
name);
18694 }
else if (!strcasecmp(v->
name,
"jitterbuffers")) {
18695 numbufs = atoi(v->
value);
18696 }
else if (!strcasecmp(v->
name,
"group")) {
18697 confp->chan.
group = ast_get_group(v->
value);
18698 }
else if (!strcasecmp(v->
name,
"callgroup")) {
18699 if (!((confp->chan.
sig == SIG_FXOKS) || (confp->chan.
sig == SIG_FXOGS) || (confp->chan.
sig == SIG_FXOLS))) {
18700 ast_log(LOG_WARNING,
"Only FXO signalled channels may belong to a call group\n");
18702 if (!strcasecmp(v->
value,
"none"))
18706 }
else if (!strcasecmp(v->
name,
"pickupgroup")) {
18707 if (!((confp->chan.
sig == SIG_FXOKS) || (confp->chan.
sig == SIG_FXOGS) || (confp->chan.
sig == SIG_FXOLS))) {
18708 ast_log(LOG_WARNING,
"Only FXO signalled channels may belong to a pickup group\n");
18710 if (!strcasecmp(v->
value,
"none"))
18714 }
else if (!strcasecmp(v->
name,
"namedcallgroup")) {
18715 if (!((confp->chan.
sig == SIG_FXOKS) || (confp->chan.
sig == SIG_FXOGS) || (confp->chan.
sig == SIG_FXOLS))) {
18716 ast_log(LOG_WARNING,
"Only FXO signalled channels may belong to a named call group\n");
18719 }
else if (!strcasecmp(v->
name,
"namedpickupgroup")) {
18720 if (!((confp->chan.
sig == SIG_FXOKS) || (confp->chan.
sig == SIG_FXOGS) || (confp->chan.
sig == SIG_FXOLS))) {
18721 ast_log(LOG_WARNING,
"Only FXO signalled channels may belong to a named pickup group\n");
18724 }
else if (!strcasecmp(v->
name,
"setvar")) {
18726 char *varval = NULL;
18728 char varname[strlen(v->
value) + 1];
18729 strcpy(varname, v->
value);
18730 if ((varval = strchr(varname,
'='))) {
18732 if ((tmpvar = ast_variable_new(varname, varval,
""))) {
18735 confp->chan.
vars = tmpvar;
18740 }
else if (!strcasecmp(v->
name,
"immediate")) {
18742 }
else if (!strcasecmp(v->
name,
"immediatering")) {
18744 }
else if (!strcasecmp(v->
name,
"transfertobusy")) {
18746 }
else if (!strcasecmp(v->
name,
"dialmode")) {
18747 if (!strcasecmp(v->
value,
"pulse")) {
18748 confp->chan.
dialmode = ANALOG_DIALMODE_PULSE;
18749 }
else if (!strcasecmp(v->
value,
"dtmf") || !strcasecmp(v->
value,
"tone")) {
18750 confp->chan.
dialmode = ANALOG_DIALMODE_DTMF;
18751 }
else if (!strcasecmp(v->
value,
"none")) {
18752 confp->chan.
dialmode = ANALOG_DIALMODE_NONE;
18754 confp->chan.
dialmode = ANALOG_DIALMODE_BOTH;
18756 }
else if (!strcasecmp(v->
name,
"mwimonitor")) {
18760 if (strcasestr(v->
value,
"fsk")) {
18763 if (strcasestr(v->
value,
"rpas")) {
18766 if (strcasestr(v->
value,
"neon")) {
18773 }
else if (!strcasecmp(v->
name,
"hwrxgain")) {
18775 if (strcasecmp(v->
value,
"disabled")) {
18776 if (sscanf(v->
value,
"%30f", &confp->chan.
hwrxgain) == 1) {
18779 ast_log(LOG_WARNING,
"Invalid hwrxgain: %s at line %d.\n", v->
value, v->lineno);
18782 }
else if (!strcasecmp(v->
name,
"hwtxgain")) {
18784 if (strcasecmp(v->
value,
"disabled")) {
18785 if (sscanf(v->
value,
"%30f", &confp->chan.
hwtxgain) == 1) {
18788 ast_log(LOG_WARNING,
"Invalid hwtxgain: %s at line %d.\n", v->
value, v->lineno);
18791 }
else if (!strcasecmp(v->
name,
"cid_rxgain")) {
18793 ast_log(LOG_WARNING,
"Invalid cid_rxgain: %s at line %d.\n", v->
value, v->lineno);
18795 }
else if (!strcasecmp(v->
name,
"rxgain")) {
18796 if (sscanf(v->
value,
"%30f", &confp->chan.
rxgain) != 1) {
18797 ast_log(LOG_WARNING,
"Invalid rxgain: %s at line %d.\n", v->
value, v->lineno);
18799 }
else if (!strcasecmp(v->
name,
"txgain")) {
18800 if (sscanf(v->
value,
"%30f", &confp->chan.
txgain) != 1) {
18801 ast_log(LOG_WARNING,
"Invalid txgain: %s at line %d.\n", v->
value, v->lineno);
18803 }
else if (!strcasecmp(v->
name,
"txdrc")) {
18804 if (sscanf(v->
value,
"%f", &confp->chan.
txdrc) != 1) {
18805 ast_log(LOG_WARNING,
"Invalid txdrc: %s\n", v->
value);
18807 }
else if (!strcasecmp(v->
name,
"rxdrc")) {
18808 if (sscanf(v->
value,
"%f", &confp->chan.rxdrc) != 1) {
18809 ast_log(LOG_WARNING,
"Invalid rxdrc: %s\n", v->
value);
18811 }
else if (!strcasecmp(v->
name,
"tonezone")) {
18812 if (sscanf(v->
value,
"%30d", &confp->chan.
tonezone) != 1) {
18813 ast_log(LOG_WARNING,
"Invalid tonezone: %s at line %d.\n", v->
value, v->lineno);
18815 }
else if (!strcasecmp(v->
name,
"callerid")) {
18816 if (!strcasecmp(v->
value,
"asreceived")) {
18817 confp->chan.
cid_num[0] =
'\0';
18822 }
else if (!strcasecmp(v->
name,
"fullname")) {
18824 }
else if (!strcasecmp(v->
name,
"cid_number")) {
18826 }
else if (!strcasecmp(v->
name,
"cid_tag")) {
18828 }
else if (!strcasecmp(v->
name,
"useincomingcalleridondahditransfer")) {
18830 }
else if (!strcasecmp(v->
name,
"restrictcid")) {
18832 }
else if (!strcasecmp(v->
name,
"usecallingpres")) {
18834 }
else if (!strcasecmp(v->
name,
"accountcode")) {
18836 }
else if (!strcasecmp(v->
name,
"amaflags")) {
18839 ast_log(LOG_WARNING,
"Invalid AMA flags: %s at line %d.\n", v->
value, v->lineno);
18842 }
else if (!strcasecmp(v->
name,
"polarityonanswerdelay")) {
18844 }
else if (!strcasecmp(v->
name,
"answeronpolarityswitch")) {
18846 }
else if (!strcasecmp(v->
name,
"ani_info_digits")) {
18848 }
else if (!strcasecmp(v->
name,
"ani_wink_time")) {
18850 }
else if (!strcasecmp(v->
name,
"ani_timeout")) {
18852 }
else if (!strcasecmp(v->
name,
"hanguponpolarityswitch")) {
18854 }
else if (!strcasecmp(v->
name,
"autoreoriginate")) {
18856 }
else if (!strcasecmp(v->
name,
"sendcalleridafter")) {
18858 }
else if (!strcasecmp(v->
name,
"mwimonitornotify")) {
18862 }
else if (!strcasecmp(v->
name,
"mwisendtype")) {
18863 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
18864 if (!strcasecmp(v->
value,
"rpas")) {
18872 if (strcasestr(v->
value,
"nofsk")) {
18873 confp->chan.mwisend_fsk = 0;
18875 confp->chan.mwisend_fsk = 1;
18877 if (strcasestr(v->
value,
"rpas")) {
18882 if (strcasestr(v->
value,
"lrev")) {
18885 if (strcasestr(v->
value,
"hvdc")) {
18888 if ( (strcasestr(v->
value,
"neon")) || (strcasestr(v->
value,
"hvac")) ) {
18892 }
else if (reload != 1) {
18893 if (!strcasecmp(v->
name,
"signalling") || !strcasecmp(v->
name,
"signaling")) {
18894 int orig_radio = confp->chan.
radio;
18895 int orig_outsigmod = confp->chan.
outsigmod;
18898 confp->chan.
radio = 0;
18901 if (!strcasecmp(v->
value,
"em")) {
18902 confp->chan.
sig = SIG_EM;
18903 }
else if (!strcasecmp(v->
value,
"em_e1")) {
18904 confp->chan.
sig = SIG_EM_E1;
18905 }
else if (!strcasecmp(v->
value,
"em_w")) {
18906 confp->chan.
sig = SIG_EMWINK;
18907 }
else if (!strcasecmp(v->
value,
"fxs_ls")) {
18908 confp->chan.
sig = SIG_FXSLS;
18909 }
else if (!strcasecmp(v->
value,
"fxs_gs")) {
18910 confp->chan.
sig = SIG_FXSGS;
18911 }
else if (!strcasecmp(v->
value,
"fxs_ks")) {
18912 confp->chan.
sig = SIG_FXSKS;
18913 }
else if (!strcasecmp(v->
value,
"fxo_ls")) {
18914 confp->chan.
sig = SIG_FXOLS;
18915 }
else if (!strcasecmp(v->
value,
"fxo_gs")) {
18916 confp->chan.
sig = SIG_FXOGS;
18917 }
else if (!strcasecmp(v->
value,
"fxo_ks")) {
18918 confp->chan.
sig = SIG_FXOKS;
18919 }
else if (!strcasecmp(v->
value,
"fxs_rx")) {
18920 confp->chan.
sig = SIG_FXSKS;
18921 confp->chan.
radio = 1;
18922 }
else if (!strcasecmp(v->
value,
"fxo_rx")) {
18923 confp->chan.
sig = SIG_FXOLS;
18924 confp->chan.
radio = 1;
18925 }
else if (!strcasecmp(v->
value,
"fxs_tx")) {
18926 confp->chan.
sig = SIG_FXSLS;
18927 confp->chan.
radio = 1;
18928 }
else if (!strcasecmp(v->
value,
"fxo_tx")) {
18929 confp->chan.
sig = SIG_FXOGS;
18930 confp->chan.
radio = 1;
18931 }
else if (!strcasecmp(v->
value,
"em_rx")) {
18932 confp->chan.
sig = SIG_EM;
18933 confp->chan.
radio = 1;
18934 }
else if (!strcasecmp(v->
value,
"em_tx")) {
18935 confp->chan.
sig = SIG_EM;
18936 confp->chan.
radio = 1;
18937 }
else if (!strcasecmp(v->
value,
"em_rxtx")) {
18938 confp->chan.
sig = SIG_EM;
18939 confp->chan.
radio = 2;
18940 }
else if (!strcasecmp(v->
value,
"em_txrx")) {
18941 confp->chan.
sig = SIG_EM;
18942 confp->chan.
radio = 2;
18943 }
else if (!strcasecmp(v->
value,
"sf")) {
18944 confp->chan.
sig = SIG_SF;
18945 }
else if (!strcasecmp(v->
value,
"sf_w")) {
18946 confp->chan.
sig = SIG_SFWINK;
18947 }
else if (!strcasecmp(v->
value,
"sf_featd")) {
18948 confp->chan.
sig = SIG_FEATD;
18949 }
else if (!strcasecmp(v->
value,
"sf_featdmf")) {
18950 confp->chan.
sig = SIG_FEATDMF;
18951 }
else if (!strcasecmp(v->
value,
"sf_featb")) {
18952 confp->chan.
sig = SIG_SF_FEATB;
18953 }
else if (!strcasecmp(v->
value,
"sf")) {
18954 confp->chan.
sig = SIG_SF;
18955 }
else if (!strcasecmp(v->
value,
"sf_rx")) {
18956 confp->chan.
sig = SIG_SF;
18957 confp->chan.
radio = 1;
18958 }
else if (!strcasecmp(v->
value,
"sf_tx")) {
18959 confp->chan.
sig = SIG_SF;
18960 confp->chan.
radio = 1;
18961 }
else if (!strcasecmp(v->
value,
"sf_rxtx")) {
18962 confp->chan.
sig = SIG_SF;
18963 confp->chan.
radio = 2;
18964 }
else if (!strcasecmp(v->
value,
"sf_txrx")) {
18965 confp->chan.
sig = SIG_SF;
18966 confp->chan.
radio = 2;
18967 }
else if (!strcasecmp(v->
value,
"featd")) {
18968 confp->chan.
sig = SIG_FEATD;
18969 }
else if (!strcasecmp(v->
value,
"featdmf")) {
18970 confp->chan.
sig = SIG_FEATDMF;
18971 }
else if (!strcasecmp(v->
value,
"featdmf_ta")) {
18972 confp->chan.
sig = SIG_FEATDMF_TA;
18973 }
else if (!strcasecmp(v->
value,
"e911")) {
18974 confp->chan.
sig = SIG_E911;
18975 }
else if (!strcasecmp(v->
value,
"fgccama")) {
18976 confp->chan.
sig = SIG_FGC_CAMA;
18977 }
else if (!strcasecmp(v->
value,
"fgccamamf")) {
18978 confp->chan.
sig = SIG_FGC_CAMAMF;
18979 }
else if (!strcasecmp(v->
value,
"featb")) {
18980 confp->chan.
sig = SIG_FEATB;
18982 }
else if (!strcasecmp(v->
value,
"pri_net")) {
18983 confp->chan.
sig = SIG_PRI;
18984 confp->pri.pri.
nodetype = PRI_NETWORK;
18985 }
else if (!strcasecmp(v->
value,
"pri_cpe")) {
18986 confp->chan.
sig = SIG_PRI;
18987 confp->pri.pri.
nodetype = PRI_CPE;
18988 }
else if (!strcasecmp(v->
value,
"bri_cpe")) {
18989 confp->chan.
sig = SIG_BRI;
18990 confp->pri.pri.
nodetype = PRI_CPE;
18991 }
else if (!strcasecmp(v->
value,
"bri_net")) {
18992 confp->chan.
sig = SIG_BRI;
18993 confp->pri.pri.
nodetype = PRI_NETWORK;
18994 }
else if (!strcasecmp(v->
value,
"bri_cpe_ptmp")) {
18995 confp->chan.
sig = SIG_BRI_PTMP;
18996 confp->pri.pri.
nodetype = PRI_CPE;
18997 }
else if (!strcasecmp(v->
value,
"bri_net_ptmp")) {
18998 #if defined(HAVE_PRI_CALL_HOLD)
18999 confp->chan.
sig = SIG_BRI_PTMP;
19000 confp->pri.pri.
nodetype = PRI_NETWORK;
19002 ast_log(LOG_WARNING,
"How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
19005 #if defined(HAVE_SS7)
19006 }
else if (!strcasecmp(v->
value,
"ss7")) {
19007 confp->chan.
sig = SIG_SS7;
19010 }
else if (!strcasecmp(v->
value,
"mfcr2")) {
19011 confp->chan.
sig = SIG_MFCR2;
19013 }
else if (!strcasecmp(v->
value,
"auto")) {
19016 confp->chan.
outsigmod = orig_outsigmod;
19017 confp->chan.
radio = orig_radio;
19019 ast_log(LOG_ERROR,
"Unknown signalling method '%s' at line %d.\n", v->
value, v->lineno);
19021 }
else if (!strcasecmp(v->
name,
"outsignalling") || !strcasecmp(v->
name,
"outsignaling")) {
19022 if (!strcasecmp(v->
value,
"em")) {
19024 }
else if (!strcasecmp(v->
value,
"em_e1")) {
19026 }
else if (!strcasecmp(v->
value,
"em_w")) {
19028 }
else if (!strcasecmp(v->
value,
"sf")) {
19030 }
else if (!strcasecmp(v->
value,
"sf_w")) {
19032 }
else if (!strcasecmp(v->
value,
"sf_featd")) {
19034 }
else if (!strcasecmp(v->
value,
"sf_featdmf")) {
19036 }
else if (!strcasecmp(v->
value,
"sf_featb")) {
19038 }
else if (!strcasecmp(v->
value,
"sf")) {
19040 }
else if (!strcasecmp(v->
value,
"featd")) {
19042 }
else if (!strcasecmp(v->
value,
"featdmf")) {
19044 }
else if (!strcasecmp(v->
value,
"featdmf_ta")) {
19045 confp->chan.
outsigmod = SIG_FEATDMF_TA;
19046 }
else if (!strcasecmp(v->
value,
"e911")) {
19048 }
else if (!strcasecmp(v->
value,
"fgccama")) {
19050 }
else if (!strcasecmp(v->
value,
"fgccamamf")) {
19051 confp->chan.
outsigmod = SIG_FGC_CAMAMF;
19052 }
else if (!strcasecmp(v->
value,
"featb")) {
19055 ast_log(LOG_ERROR,
"Unknown signalling method '%s' at line %d.\n", v->
value, v->lineno);
19058 }
else if (!strcasecmp(v->
name,
"pridialplan")) {
19059 if (!strcasecmp(v->
value,
"national")) {
19060 confp->pri.pri.
dialplan = PRI_NATIONAL_ISDN + 1;
19061 }
else if (!strcasecmp(v->
value,
"unknown")) {
19062 confp->pri.pri.
dialplan = PRI_UNKNOWN + 1;
19063 }
else if (!strcasecmp(v->
value,
"private")) {
19064 confp->pri.pri.
dialplan = PRI_PRIVATE + 1;
19065 }
else if (!strcasecmp(v->
value,
"international")) {
19066 confp->pri.pri.
dialplan = PRI_INTERNATIONAL_ISDN + 1;
19067 }
else if (!strcasecmp(v->
value,
"local")) {
19068 confp->pri.pri.
dialplan = PRI_LOCAL_ISDN + 1;
19069 }
else if (!strcasecmp(v->
value,
"dynamic")) {
19071 }
else if (!strcasecmp(v->
value,
"redundant")) {
19074 ast_log(LOG_WARNING,
"Unknown PRI dialplan '%s' at line %d.\n", v->
value, v->lineno);
19076 }
else if (!strcasecmp(v->
name,
"prilocaldialplan")) {
19077 if (!strcasecmp(v->
value,
"national")) {
19079 }
else if (!strcasecmp(v->
value,
"unknown")) {
19081 }
else if (!strcasecmp(v->
value,
"private")) {
19083 }
else if (!strcasecmp(v->
value,
"international")) {
19085 }
else if (!strcasecmp(v->
value,
"local")) {
19087 }
else if (!strcasecmp(v->
value,
"from_channel")) {
19089 }
else if (!strcasecmp(v->
value,
"dynamic")) {
19091 }
else if (!strcasecmp(v->
value,
"redundant")) {
19094 ast_log(LOG_WARNING,
"Unknown PRI localdialplan '%s' at line %d.\n", v->
value, v->lineno);
19096 }
else if (!strcasecmp(v->
name,
"pricpndialplan")) {
19097 if (!strcasecmp(v->
value,
"national")) {
19098 confp->pri.pri.
cpndialplan = PRI_NATIONAL_ISDN + 1;
19099 }
else if (!strcasecmp(v->
value,
"unknown")) {
19101 }
else if (!strcasecmp(v->
value,
"private")) {
19103 }
else if (!strcasecmp(v->
value,
"international")) {
19104 confp->pri.pri.
cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
19105 }
else if (!strcasecmp(v->
value,
"local")) {
19107 }
else if (!strcasecmp(v->
value,
"from_channel")) {
19109 }
else if (!strcasecmp(v->
value,
"dynamic")) {
19111 }
else if (!strcasecmp(v->
value,
"redundant")) {
19114 ast_log(LOG_WARNING,
"Unknown PRI cpndialplan '%s' at line %d.\n", v->
value, v->lineno);
19116 }
else if (!strcasecmp(v->
name,
"switchtype")) {
19117 if (!strcasecmp(v->
value,
"national"))
19119 else if (!strcasecmp(v->
value,
"ni1"))
19121 else if (!strcasecmp(v->
value,
"dms100"))
19122 confp->pri.pri.
switchtype = PRI_SWITCH_DMS100;
19123 else if (!strcasecmp(v->
value,
"4ess"))
19124 confp->pri.pri.
switchtype = PRI_SWITCH_ATT4ESS;
19125 else if (!strcasecmp(v->
value,
"5ess"))
19126 confp->pri.pri.
switchtype = PRI_SWITCH_LUCENT5E;
19127 else if (!strcasecmp(v->
value,
"euroisdn"))
19128 confp->pri.pri.
switchtype = PRI_SWITCH_EUROISDN_E1;
19129 else if (!strcasecmp(v->
value,
"qsig"))
19130 confp->pri.pri.
switchtype = PRI_SWITCH_QSIG;
19132 ast_log(LOG_ERROR,
"Unknown switchtype '%s' at line %d.\n", v->
value, v->lineno);
19135 }
else if (!strcasecmp(v->
name,
"msn")) {
19138 }
else if (!strcasecmp(v->
name,
"nsf")) {
19139 if (!strcasecmp(v->
value,
"sdn"))
19140 confp->pri.pri.
nsf = PRI_NSF_SDN;
19141 else if (!strcasecmp(v->
value,
"megacom"))
19142 confp->pri.pri.
nsf = PRI_NSF_MEGACOM;
19143 else if (!strcasecmp(v->
value,
"tollfreemegacom"))
19144 confp->pri.pri.
nsf = PRI_NSF_TOLL_FREE_MEGACOM;
19145 else if (!strcasecmp(v->
value,
"accunet"))
19146 confp->pri.pri.
nsf = PRI_NSF_ACCUNET;
19147 else if (!strcasecmp(v->
value,
"none"))
19148 confp->pri.pri.
nsf = PRI_NSF_NONE;
19150 ast_log(LOG_WARNING,
"Unknown network-specific facility '%s' at line %d.\n", v->
value, v->lineno);
19151 confp->pri.pri.
nsf = PRI_NSF_NONE;
19153 }
else if (!strcasecmp(v->
name,
"priindication")) {
19154 if (!strcasecmp(v->
value,
"outofband"))
19156 else if (!strcasecmp(v->
value,
"inband"))
19159 ast_log(LOG_WARNING,
"'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
19160 v->
value, v->lineno);
19161 }
else if (!strcasecmp(v->
name,
"priexclusive")) {
19163 }
else if (!strcasecmp(v->
name,
"internationalprefix")) {
19165 }
else if (!strcasecmp(v->
name,
"nationalprefix")) {
19167 }
else if (!strcasecmp(v->
name,
"localprefix")) {
19169 }
else if (!strcasecmp(v->
name,
"privateprefix")) {
19171 }
else if (!strcasecmp(v->
name,
"unknownprefix")) {
19173 }
else if (!strcasecmp(v->
name,
"resetinterval")) {
19174 if (!strcasecmp(v->
value,
"never"))
19176 else if (atoi(v->
value) >= 60)
19179 ast_log(LOG_WARNING,
"'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
19180 v->
value, v->lineno);
19181 }
else if (!strcasecmp(v->
name,
"force_restart_unavailable_chans")) {
19183 }
else if (!strcasecmp(v->
name,
"minunused")) {
19185 }
else if (!strcasecmp(v->
name,
"minidle")) {
19187 }
else if (!strcasecmp(v->
name,
"idleext")) {
19189 }
else if (!strcasecmp(v->
name,
"idledial")) {
19191 }
else if (!strcasecmp(v->
name,
"overlapdial")) {
19193 confp->pri.pri.
overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19194 }
else if (!strcasecmp(v->
value,
"incoming")) {
19195 confp->pri.pri.
overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
19196 }
else if (!strcasecmp(v->
value,
"outgoing")) {
19197 confp->pri.pri.
overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
19199 confp->pri.pri.
overlapdial = DAHDI_OVERLAPDIAL_BOTH;
19201 confp->pri.pri.
overlapdial = DAHDI_OVERLAPDIAL_NONE;
19203 #ifdef HAVE_PRI_PROG_W_CAUSE
19204 }
else if (!strcasecmp(v->
name,
"qsigchannelmapping")) {
19205 if (!strcasecmp(v->
value,
"logical")) {
19207 }
else if (!strcasecmp(v->
value,
"physical")) {
19213 }
else if (!strcasecmp(v->
name,
"discardremoteholdretrieval")) {
19215 #if defined(HAVE_PRI_SERVICE_MESSAGES)
19216 }
else if (!strcasecmp(v->
name,
"service_message_support")) {
19218 if ((confp->pri.pri.
switchtype == PRI_SWITCH_ATT4ESS
19219 || confp->pri.pri.
switchtype == PRI_SWITCH_LUCENT5E
19226 #ifdef HAVE_PRI_INBANDDISCONNECT
19227 }
else if (!strcasecmp(v->
name,
"inbanddisconnect")) {
19230 }
else if (!strcasecmp(v->
name,
"pritimer")) {
19231 #ifdef PRI_GETSET_TIMERS
19240 timerc = strsep(&c,
",");
19241 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
19242 timeridx = pri_timer2idx(timerc);
19244 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
19245 ast_log(LOG_WARNING,
19246 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
19248 }
else if (!timer) {
19249 ast_log(LOG_WARNING,
19250 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
19251 c, timerc, v->lineno);
19253 confp->pri.pri.pritimers[timeridx] = timer;
19256 ast_log(LOG_WARNING,
19257 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
19258 v->
value, v->lineno);
19261 }
else if (!strcasecmp(v->
name,
"facilityenable")) {
19263 #if defined(HAVE_PRI_AOC_EVENTS)
19264 }
else if (!strcasecmp(v->
name,
"aoc_enable")) {
19266 if (strchr(v->
value,
's') || strchr(v->
value,
'S')) {
19269 if (strchr(v->
value,
'd') || strchr(v->
value,
'D')) {
19272 if (strchr(v->
value,
'e') || strchr(v->
value,
'E')) {
19275 }
else if (!strcasecmp(v->
name,
"aoce_delayhangup")) {
19278 #if defined(HAVE_PRI_CALL_HOLD)
19279 }
else if (!strcasecmp(v->
name,
"hold_disconnect_transfer")) {
19282 }
else if (!strcasecmp(v->
name,
"moh_signaling")
19283 || !strcasecmp(v->
name,
"moh_signalling")) {
19284 if (!strcasecmp(v->
value,
"moh")) {
19286 }
else if (!strcasecmp(v->
value,
"notify")) {
19288 #if defined(HAVE_PRI_CALL_HOLD)
19289 }
else if (!strcasecmp(v->
value,
"hold")) {
19295 #if defined(HAVE_PRI_CCSS)
19296 }
else if (!strcasecmp(v->
name,
"cc_ptmp_recall_mode")) {
19297 if (!strcasecmp(v->
value,
"global")) {
19299 }
else if (!strcasecmp(v->
value,
"specific")) {
19304 }
else if (!strcasecmp(v->
name,
"cc_qsig_signaling_link_req")) {
19305 if (!strcasecmp(v->
value,
"release")) {
19307 }
else if (!strcasecmp(v->
value,
"retain")) {
19309 }
else if (!strcasecmp(v->
value,
"do_not_care")) {
19314 }
else if (!strcasecmp(v->
name,
"cc_qsig_signaling_link_rsp")) {
19315 if (!strcasecmp(v->
value,
"release")) {
19317 }
else if (!strcasecmp(v->
value,
"retain")) {
19323 #if defined(HAVE_PRI_CALL_WAITING)
19324 }
else if (!strcasecmp(v->
name,
"max_call_waiting_calls")) {
19330 }
else if (!strcasecmp(v->
name,
"allow_call_waiting_calls")) {
19333 #if defined(HAVE_PRI_MWI)
19334 }
else if (!strcasecmp(v->
name,
"mwi_mailboxes")) {
19337 }
else if (!strcasecmp(v->
name,
"mwi_vm_boxes")) {
19340 }
else if (!strcasecmp(v->
name,
"mwi_vm_numbers")) {
19344 }
else if (!strcasecmp(v->
name,
"append_msn_to_cid_tag")) {
19346 }
else if (!strcasecmp(v->
name,
"inband_on_setup_ack")) {
19348 }
else if (!strcasecmp(v->
name,
"inband_on_proceeding")) {
19350 #if defined(HAVE_PRI_DISPLAY_TEXT)
19351 }
else if (!strcasecmp(v->
name,
"display_send")) {
19353 }
else if (!strcasecmp(v->
name,
"display_receive")) {
19356 #if defined(HAVE_PRI_MCID)
19357 }
else if (!strcasecmp(v->
name,
"mcid_send")) {
19360 #if defined(HAVE_PRI_DATETIME_SEND)
19361 }
else if (!strcasecmp(v->
name,
"datetime_send")) {
19364 }
else if (!strcasecmp(v->
name,
"layer1_presence")) {
19365 if (!strcasecmp(v->
value,
"required")) {
19367 }
else if (!strcasecmp(v->
value,
"ignore")) {
19373 #if defined(HAVE_PRI_L2_PERSISTENCE)
19374 }
else if (!strcasecmp(v->
name,
"layer2_persistence")) {
19375 if (!strcasecmp(v->
value,
"keep_up")) {
19377 }
else if (!strcasecmp(v->
value,
"leave_down")) {
19383 }
else if (!strcasecmp(v->
name,
"colp_send")) {
19384 if (!strcasecmp(v->
value,
"block")) {
19386 }
else if (!strcasecmp(v->
value,
"connect")) {
19388 }
else if (!strcasecmp(v->
value,
"update")) {
19394 #if defined(HAVE_SS7)
19395 }
else if (!strcasecmp(v->
name,
"ss7type")) {
19396 if (!strcasecmp(v->
value,
"itu")) {
19397 cur_ss7type = SS7_ITU;
19398 }
else if (!strcasecmp(v->
value,
"ansi")) {
19399 cur_ss7type = SS7_ANSI;
19401 ast_log(LOG_WARNING,
"'%s' is an unknown ss7 switch type at line %d.!\n", v->
value, v->lineno);
19403 }
else if (!strcasecmp(v->
name,
"slc")) {
19404 cur_slc = atoi(v->
value);
19405 }
else if (!strcasecmp(v->
name,
"linkset")) {
19406 cur_linkset = atoi(v->
value);
19407 }
else if (!strcasecmp(v->
name,
"pointcode")) {
19408 cur_pointcode = parse_pointcode(v->
value);
19409 }
else if (!strcasecmp(v->
name,
"adjpointcode")) {
19410 cur_adjpointcode = parse_pointcode(v->
value);
19411 }
else if (!strcasecmp(v->
name,
"defaultdpc")) {
19412 cur_defaultdpc = parse_pointcode(v->
value);
19413 }
else if (!strcasecmp(v->
name,
"cicbeginswith")) {
19414 cur_cicbeginswith = atoi(v->
value);
19415 }
else if (!strcasecmp(v->
name,
"networkindicator")) {
19416 if (!strcasecmp(v->
value,
"national")) {
19417 cur_networkindicator = SS7_NI_NAT;
19418 }
else if (!strcasecmp(v->
value,
"national_spare")) {
19419 cur_networkindicator = SS7_NI_NAT_SPARE;
19420 }
else if (!strcasecmp(v->
value,
"international")) {
19421 cur_networkindicator = SS7_NI_INT;
19422 }
else if (!strcasecmp(v->
value,
"international_spare")) {
19423 cur_networkindicator = SS7_NI_INT_SPARE;
19425 cur_networkindicator = -1;
19427 }
else if (!strcasecmp(v->
name,
"ss7_internationalprefix")) {
19428 ast_copy_string(confp->ss7.ss7.internationalprefix, v->
value,
sizeof(confp->ss7.ss7.internationalprefix));
19429 }
else if (!strcasecmp(v->
name,
"ss7_nationalprefix")) {
19430 ast_copy_string(confp->ss7.ss7.nationalprefix, v->
value,
sizeof(confp->ss7.ss7.nationalprefix));
19431 }
else if (!strcasecmp(v->
name,
"ss7_subscriberprefix")) {
19432 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->
value,
sizeof(confp->ss7.ss7.subscriberprefix));
19433 }
else if (!strcasecmp(v->
name,
"ss7_unknownprefix")) {
19434 ast_copy_string(confp->ss7.ss7.unknownprefix, v->
value,
sizeof(confp->ss7.ss7.unknownprefix));
19435 }
else if (!strcasecmp(v->
name,
"ss7_networkroutedprefix")) {
19436 ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->
value,
sizeof(confp->ss7.ss7.networkroutedprefix));
19437 }
else if (!strcasecmp(v->
name,
"ss7_called_nai")) {
19438 if (!strcasecmp(v->
value,
"national")) {
19439 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
19440 }
else if (!strcasecmp(v->
value,
"international")) {
19441 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
19442 }
else if (!strcasecmp(v->
value,
"subscriber")) {
19443 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
19444 }
else if (!strcasecmp(v->
value,
"unknown")) {
19445 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
19446 }
else if (!strcasecmp(v->
value,
"dynamic")) {
19447 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
19449 ast_log(LOG_WARNING,
"Unknown SS7 called_nai '%s' at line %d.\n", v->
value, v->lineno);
19451 }
else if (!strcasecmp(v->
name,
"ss7_calling_nai")) {
19452 if (!strcasecmp(v->
value,
"national")) {
19453 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
19454 }
else if (!strcasecmp(v->
value,
"international")) {
19455 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
19456 }
else if (!strcasecmp(v->
value,
"subscriber")) {
19457 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
19458 }
else if (!strcasecmp(v->
value,
"unknown")) {
19459 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
19460 }
else if (!strcasecmp(v->
value,
"dynamic")) {
19461 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
19463 ast_log(LOG_WARNING,
"Unknown SS7 calling_nai '%s' at line %d.\n", v->
value, v->lineno);
19465 }
else if (!strcasecmp(v->
name,
"sigchan")) {
19467 sigchan = atoi(v->
value);
19468 res = linkset_addsigchan(sigchan);
19472 }
else if (!strcasecmp(v->
name,
"ss7_explicitacm")) {
19473 struct dahdi_ss7 *link;
19474 link = ss7_resolve_linkset(cur_linkset);
19476 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19480 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
19482 link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
19484 }
else if (!strcasecmp(v->
name,
"ss7_autoacm")) {
19485 struct dahdi_ss7 *link;
19486 link = ss7_resolve_linkset(cur_linkset);
19488 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19492 link->ss7.flags |= LINKSET_FLAG_AUTOACM;
19494 link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
19496 }
else if (!strcasecmp(v->
name,
"ss7_initialhwblo")) {
19497 struct dahdi_ss7 *link;
19498 link = ss7_resolve_linkset(cur_linkset);
19500 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19504 link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
19506 link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
19508 }
else if (!strcasecmp(v->
name,
"ss7_use_echocontrol")) {
19509 struct dahdi_ss7 *link;
19510 link = ss7_resolve_linkset(cur_linkset);
19512 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19516 link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
19518 link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
19520 }
else if (!strcasecmp(v->
name,
"ss7_default_echocontrol")) {
19521 struct dahdi_ss7 *link;
19522 link = ss7_resolve_linkset(cur_linkset);
19524 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19528 link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
19530 link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
19532 }
else if (!strncasecmp(v->
name,
"isup_timer.", 11)) {
19533 struct dahdi_ss7 *link;
19534 link = ss7_resolve_linkset(cur_linkset);
19536 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19539 if (!link->ss7.ss7) {
19540 ast_log(LOG_ERROR,
"Please specify isup timers after sigchan!\n");
19541 }
else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->
name,
".") + 1, atoi(v->
value))) {
19542 ast_log(LOG_ERROR,
"Invalid isup timer %s\n", v->
name);
19544 }
else if (!strncasecmp(v->
name,
"mtp3_timer.", 11)) {
19545 struct dahdi_ss7 *link;
19546 link = ss7_resolve_linkset(cur_linkset);
19548 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19551 if (!link->ss7.ss7) {
19552 ast_log(LOG_ERROR,
"Please specify mtp3 timers after sigchan!\n");
19553 }
else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->
name,
".") + 1, atoi(v->
value))) {
19554 ast_log(LOG_ERROR,
"Invalid mtp3 timer %s\n", v->
name);
19556 }
else if (!strcasecmp(v->
name,
"inr_if_no_calling")) {
19557 struct dahdi_ss7 *link;
19558 link = ss7_resolve_linkset(cur_linkset);
19560 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19563 if (!link->ss7.ss7) {
19564 ast_log(LOG_ERROR,
"Please specify inr_if_no_calling after sigchan!\n");
19566 ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19568 ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
19570 }
else if (!strcasecmp(v->
name,
"non_isdn_access")) {
19571 struct dahdi_ss7 *link;
19572 link = ss7_resolve_linkset(cur_linkset);
19574 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19577 if (!link->ss7.ss7) {
19578 ast_log(LOG_ERROR,
"Please specify non_isdn_access after sigchan!\n");
19580 ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19582 ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
19584 }
else if (!strcasecmp(v->
name,
"sls_shift")) {
19585 struct dahdi_ss7 *link;
19586 int sls_shift = atoi(v->
value);
19588 if (sls_shift < 0 || sls_shift > 7) {
19589 ast_log(LOG_ERROR,
"Invalid sls_shift value. Must be between 0 and 7\n");
19593 link = ss7_resolve_linkset(cur_linkset);
19595 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19598 if (!link->ss7.ss7) {
19599 ast_log(LOG_ERROR,
"Please specify sls_shift after sigchan!\n");
19601 ss7_set_sls_shift(link->ss7.ss7, sls_shift);
19603 }
else if (!strcasecmp(v->
name,
"cause_location")) {
19604 struct dahdi_ss7 *link;
19605 int cause_location = atoi(v->
value);
19607 if (cause_location < 0 || cause_location > 15) {
19608 ast_log(LOG_ERROR,
"Invalid cause_location value. Must be between 0 and 15\n");
19611 link = ss7_resolve_linkset(cur_linkset);
19613 ast_log(LOG_ERROR,
"Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19616 if (!link->ss7.ss7) {
19617 ast_log(LOG_ERROR,
"Please specify cause_location after sigchan!\n");
19619 ss7_set_cause_location(link->ss7.ss7, cause_location);
19623 }
else if (!strcasecmp(v->
name,
"mfcr2_advanced_protocol_file")) {
19625 ast_log(LOG_WARNING,
"MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
19626 }
else if (!strcasecmp(v->
name,
"mfcr2_logdir")) {
19628 }
else if (!strcasecmp(v->
name,
"mfcr2_variant")) {
19629 confp->mfcr2.variant = openr2_proto_get_variant(v->
value);
19630 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19631 ast_log(LOG_WARNING,
"Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->
value, v->lineno);
19632 confp->mfcr2.variant = OR2_VAR_ITU;
19634 }
else if (!strcasecmp(v->
name,
"mfcr2_mfback_timeout")) {
19635 confp->mfcr2.mfback_timeout = atoi(v->
value);
19636 if (!confp->mfcr2.mfback_timeout) {
19637 ast_log(LOG_WARNING,
"MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19638 confp->mfcr2.mfback_timeout = -1;
19639 }
else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19640 ast_log(LOG_WARNING,
"MF timeout less than 500ms is not recommended, you have been warned!\n");
19642 }
else if (!strcasecmp(v->
name,
"mfcr2_metering_pulse_timeout")) {
19643 confp->mfcr2.metering_pulse_timeout = atoi(v->
value);
19644 if (confp->mfcr2.metering_pulse_timeout > 500) {
19645 ast_log(LOG_WARNING,
"Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19647 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19648 }
else if (!strcasecmp(v->
name,
"mfcr2_dtmf_detection")) {
19650 }
else if (!strcasecmp(v->
name,
"mfcr2_dtmf_dialing")) {
19652 }
else if (!strcasecmp(v->
name,
"mfcr2_dtmf_time_on")) {
19653 confp->mfcr2.dtmf_time_on = atoi(v->
value);
19654 }
else if (!strcasecmp(v->
name,
"mfcr2_dtmf_time_off")) {
19655 confp->mfcr2.dtmf_time_off = atoi(v->
value);
19657 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19658 }
else if (!strcasecmp(v->
name,
"mfcr2_dtmf_end_timeout")) {
19659 confp->mfcr2.dtmf_end_timeout = atoi(v->
value);
19661 }
else if (!strcasecmp(v->
name,
"mfcr2_get_ani_first")) {
19663 }
else if (!strcasecmp(v->
name,
"mfcr2_double_answer")) {
19665 }
else if (!strcasecmp(v->
name,
"mfcr2_charge_calls")) {
19667 }
else if (!strcasecmp(v->
name,
"mfcr2_accept_on_offer")) {
19669 }
else if (!strcasecmp(v->
name,
"mfcr2_allow_collect_calls")) {
19670 confp->mfcr2.allow_collect_calls =
ast_true(v->
value) ? 1 : 0;
19671 }
else if (!strcasecmp(v->
name,
"mfcr2_forced_release")) {
19673 }
else if (!strcasecmp(v->
name,
"mfcr2_immediate_accept")) {
19674 confp->mfcr2.immediate_accept =
ast_true(v->
value) ? 1 : 0;
19675 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19676 }
else if (!strcasecmp(v->
name,
"mfcr2_skip_category")) {
19677 confp->mfcr2.skip_category_request =
ast_true(v->
value) ? 1 : 0;
19679 }
else if (!strcasecmp(v->
name,
"mfcr2_call_files")) {
19681 }
else if (!strcasecmp(v->
name,
"mfcr2_max_ani")) {
19682 confp->mfcr2.max_ani = atoi(v->
value);
19686 }
else if (!strcasecmp(v->
name,
"mfcr2_max_dnis")) {
19687 confp->mfcr2.max_dnis = atoi(v->
value);
19691 }
else if (!strcasecmp(v->
name,
"mfcr2_category")) {
19692 confp->mfcr2.category = openr2_proto_get_category(v->
value);
19693 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19694 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19695 ast_log(LOG_WARNING,
"Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19696 v->
value, v->lineno);
19698 }
else if (!strcasecmp(v->
name,
"mfcr2_logging")) {
19699 openr2_log_level_t tmplevel;
19703 strcpy(copy, v->
value);
19706 clevel = strsep(&logval,
",");
19707 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19708 ast_log(LOG_WARNING,
"Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19711 confp->mfcr2.loglevel |= tmplevel;
19714 }
else if (!strcasecmp(v->
name,
"cadence")) {
19716 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19718 struct dahdi_ring_cadence new_cadence;
19719 int cid_location = -1;
19720 int firstcadencepos = 0;
19721 char original_args[80];
19722 int cadence_is_ok = 1;
19726 element_count = sscanf(v->
value,
"%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
19729 if (element_count % 2 == 1) {
19730 ast_log(LOG_ERROR,
"Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19735 if (element_count > ARRAY_LEN(c)) {
19736 element_count = ARRAY_LEN(c);
19740 for (i = 0; i < element_count; i++) {
19742 ast_log(LOG_ERROR,
"Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19745 }
else if (c[i] < 0) {
19748 if (cid_location == -1) {
19752 ast_log(LOG_ERROR,
"CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19757 if (firstcadencepos == 0) {
19758 firstcadencepos = i;
19761 ast_log(LOG_ERROR,
"First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19770 for (i = 0; i < 16; i++) {
19771 new_cadence.ringcadence[i] = c[i];
19774 if (cadence_is_ok) {
19776 if (element_count < 2) {
19777 ast_log(LOG_ERROR,
"Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19779 if (cid_location == -1) {
19784 cid_location = (cid_location + 1) / 2;
19787 if (!user_has_defined_cadences++)
19790 if ((num_cadence+1) >= NUM_CADENCE_MAX)
19791 ast_log(LOG_ERROR,
"Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19793 cadences[num_cadence] = new_cadence;
19794 cidrings[num_cadence++] = cid_location;
19795 ast_verb(3,
"cadence 'r%d' added: %s\n",num_cadence,original_args);
19799 }
else if (!strcasecmp(v->
name,
"ringtimeout")) {
19801 }
else if (!strcasecmp(v->
name,
"prewink")) {
19802 confp->timing.prewinktime = atoi(v->
value);
19803 }
else if (!strcasecmp(v->
name,
"preflash")) {
19804 confp->timing.preflashtime = atoi(v->
value);
19805 }
else if (!strcasecmp(v->
name,
"wink")) {
19806 confp->timing.winktime = atoi(v->
value);
19807 }
else if (!strcasecmp(v->
name,
"flash")) {
19808 confp->timing.flashtime = atoi(v->
value);
19809 }
else if (!strcasecmp(v->
name,
"start")) {
19810 confp->timing.starttime = atoi(v->
value);
19811 }
else if (!strcasecmp(v->
name,
"rxwink")) {
19812 confp->timing.rxwinktime = atoi(v->
value);
19813 }
else if (!strcasecmp(v->
name,
"rxflash")) {
19814 confp->timing.rxflashtime = atoi(v->
value);
19815 }
else if (!strcasecmp(v->
name,
"debounce")) {
19816 confp->timing.debouncetime = atoi(v->
value);
19817 }
else if (!strcasecmp(v->
name,
"toneduration")) {
19821 struct dahdi_dialparams dps;
19823 ctlfd = open(
"/dev/dahdi/ctl", O_RDWR);
19825 ast_log(LOG_ERROR,
"Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19829 toneduration = atoi(v->
value);
19830 if (toneduration > -1) {
19831 memset(&dps, 0,
sizeof(dps));
19833 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19834 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19836 ast_log(LOG_ERROR,
"Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19842 }
else if (!strcasecmp(v->
name,
"defaultcic")) {
19844 }
else if (!strcasecmp(v->
name,
"defaultozz")) {
19846 }
else if (!strcasecmp(v->
name,
"mwilevel")) {
19847 mwilevel = atoi(v->
value);
19848 }
else if (!strcasecmp(v->
name,
"dtmfcidlevel")) {
19849 dtmfcid_level = atoi(v->
value);
19850 }
else if (!strcasecmp(v->
name,
"reportalarms")) {
19851 if (!strcasecmp(v->
value,
"all"))
19852 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
19853 if (!strcasecmp(v->
value,
"none"))
19855 else if (!strcasecmp(v->
value,
"channels"))
19856 report_alarms = REPORT_CHANNEL_ALARMS;
19857 else if (!strcasecmp(v->
value,
"spans"))
19858 report_alarms = REPORT_SPAN_ALARMS;
19861 ast_log(LOG_NOTICE,
"Ignoring any changes to '%s' (on reload) at line %d.\n", v->
name, v->lineno);
19866 if (build_channels(confp, dahdichan->
value, reload, dahdichan->lineno)) {
19868 ast_log(LOG_WARNING,
19869 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19881 if (confp->chan.
vars) {
19883 confp->chan.
vars = NULL;
19887 for (tmp = iflist, y=-1; tmp; tmp = tmp->
next) {
19888 if (!tmp->destroy && tmp->span != y) {
19889 tmp->manages_span_alarms = 1;
19892 tmp->manages_span_alarms = 0;
19898 if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19905 if (conf.chan.cc_params) {
19906 tmp =
mkintf(CHAN_PSEUDO, &conf, reload);
19911 ast_verb(3,
"Automatically generated pseudo channel\n");
19914 ast_log(LOG_WARNING,
"Unable to register pseudo channel!\n");
19938 cc_params = dest->chan.cc_params;
19940 dest->chan.cc_params = cc_params;
19975 static int had_cfg_before = 1;
19978 have_cfg_now = !!cfg;
19981 if (had_cfg_before) {
19982 ast_log(LOG_ERROR,
"Unable to load config %s\n", config);
19990 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19994 if (ucfg == CONFIG_STATUS_FILEINVALID) {
19995 ast_log(LOG_ERROR,
"File users.conf cannot be parsed. Aborting.\n");
19999 }
else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
20001 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
20004 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20005 ast_log(LOG_ERROR,
"File users.conf cannot be parsed. Aborting.\n");
20010 have_cfg_now = !!cfg;
20012 if (had_cfg_before) {
20014 ast_log(LOG_ERROR,
"Bad. Unable to load config %s\n", config);
20023 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
20024 ast_log(LOG_ERROR,
"File %s cannot be parsed. Aborting.\n", config);
20028 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
20029 ast_log(LOG_ERROR,
"File %s cannot be parsed. Aborting.\n", config);
20034 if (ucfg == CONFIG_STATUS_FILEINVALID) {
20035 ast_log(LOG_ERROR,
"File users.conf cannot be parsed. Aborting.\n");
20040 had_cfg_before = have_cfg_now;
20043 ast_mutex_lock(&
iflock);
20047 v = ast_variable_browse(cfg,
"trunkgroups");
20049 if (!strcasecmp(v->
name,
"trunkgroup")) {
20050 trunkgroup = atoi(v->
value);
20051 if (trunkgroup > 0) {
20052 if ((c = strchr(v->
value,
','))) {
20054 memset(dchannels, 0,
sizeof(dchannels));
20055 while (c && (i < SIG_PRI_NUM_DCHANS)) {
20056 dchannels[i] = atoi(c + 1);
20057 if (dchannels[i] < 0) {
20058 ast_log(LOG_WARNING,
"D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20061 c = strchr(c + 1,
',');
20064 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
20065 ast_log(LOG_WARNING,
"Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
20067 ast_verb(2,
"Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ?
"" :
"s");
20069 ast_log(LOG_WARNING,
"Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20071 ast_log(LOG_WARNING,
"Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
20073 ast_log(LOG_WARNING,
"Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
20074 }
else if (!strcasecmp(v->
name,
"spanmap")) {
20075 spanno = atoi(v->
value);
20077 if ((c = strchr(v->
value,
','))) {
20078 trunkgroup = atoi(c + 1);
20079 if (trunkgroup > 0) {
20080 if ((c = strchr(c + 1,
',')))
20081 logicalspan = atoi(c + 1);
20084 if (logicalspan >= 0) {
20085 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
20086 ast_log(LOG_WARNING,
"Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20088 ast_verb(2,
"Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
20090 ast_log(LOG_WARNING,
"Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
20092 ast_log(LOG_WARNING,
"Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
20094 ast_log(LOG_WARNING,
"Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
20096 ast_log(LOG_WARNING,
"Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
20098 ast_log(LOG_NOTICE,
"Ignoring unknown keyword '%s' in trunkgroups\n", v->
name);
20106 memcpy(&global_jbconf, &default_jbconf,
sizeof(global_jbconf));
20110 v = ast_variable_browse(cfg,
"channels");
20111 if ((res = process_dahdi(base_conf,
20114 ast_mutex_unlock(&
iflock);
20127 if (!strcasecmp(cat,
"general") ||
20128 !strcasecmp(cat,
"trunkgroups") ||
20129 !strcasecmp(cat,
"globals") ||
20130 !strcasecmp(cat,
"channels")) {
20134 chans = ast_variable_retrieve(cfg, cat,
"dahdichan");
20135 if (ast_strlen_zero(chans)) {
20141 deep_copy_dahdi_chan_conf(conf, base_conf);
20143 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
20144 ast_mutex_unlock(&
iflock);
20157 deep_copy_dahdi_chan_conf(base_conf, default_conf);
20158 process_dahdi(base_conf,
20160 ast_variable_browse(ucfg,
"general"), 1, 0);
20163 if (!strcasecmp(cat,
"general")) {
20167 chans = ast_variable_retrieve(ucfg, cat,
"dahdichan");
20168 if (ast_strlen_zero(chans)) {
20174 deep_copy_dahdi_chan_conf(conf, base_conf);
20176 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN |
PROC_DAHDI_OPT_NOWARN))) {
20178 ast_mutex_unlock(&
iflock);
20184 ast_mutex_unlock(&
iflock);
20189 for (x = 0; x < NUM_SPANS; x++) {
20190 if (pris[x].pri.
pvts[0] &&
20191 pris[x].pri.
master == AST_PTHREADT_NULL) {
20192 prepare_pri(pris + x);
20193 if (sig_pri_start_pri(&pris[x].pri)) {
20194 ast_log(LOG_ERROR,
"Unable to start D-channel on span %d\n", x + 1);
20197 ast_verb(2,
"Starting D-Channel on span %d\n", x + 1);
20202 #if defined(HAVE_SS7)
20205 for (x = 0; x < NUM_SPANS; x++) {
20206 if (linksets[x].ss7.ss7) {
20207 if (ast_pthread_create(&linksets[x].ss7.
master, NULL, ss7_linkset, &linksets[x].ss7)) {
20208 ast_log(LOG_ERROR,
"Unable to start SS7 linkset on span %d\n", x + 1);
20211 ast_verb(2,
"Starting SS7 linkset on span %d\n", x + 1);
20218 struct r2link_entry *cur;
20222 struct dahdi_mfcr2 *r2 = &cur->mfcr2;
20223 if (r2->r2master == AST_PTHREADT_NULL) {
20224 if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
20225 ast_log(LOG_ERROR,
"Unable to start R2 monitor on channel group %d\n", x + 1);
20228 ast_verb(2,
"Starting R2 monitor on channel group %d\n", x + 1);
20250 static int setup_dahdi(
int reload)
20257 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
20258 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
20282 #if defined(HAVE_PRI) || defined(HAVE_SS7)
20297 if (dahdi_native_load(&dahdi_tech)) {
20303 memset(pris, 0,
sizeof(pris));
20304 for (y = 0; y < NUM_SPANS; y++) {
20305 sig_pri_init_pri(&pris[y].pri);
20307 pri_set_error(dahdi_pri_error);
20308 pri_set_message(dahdi_pri_message);
20310 #ifdef HAVE_PRI_PROG_W_CAUSE
20313 #if defined(HAVE_PRI_CCSS)
20321 #
if defined(HAVE_PRI_CCSS)
20331 #if defined(HAVE_SS7)
20332 memset(linksets, 0,
sizeof(linksets));
20333 for (y = 0; y < NUM_SPANS; y++) {
20334 sig_ss7_init_linkset(&linksets[y].ss7);
20336 ss7_set_error(dahdi_ss7_error);
20337 ss7_set_message(dahdi_ss7_message);
20338 ss7_set_hangup(sig_ss7_cb_hangup);
20339 ss7_set_notinservice(sig_ss7_cb_notinservice);
20340 ss7_set_call_null(sig_ss7_cb_call_null);
20342 res = setup_dahdi(0);
20349 ast_log(LOG_ERROR,
"Unable to register channel class 'DAHDI'\n");
20356 #if defined(HAVE_SS7)
20367 memset(round_robin, 0,
sizeof(round_robin));
20376 #if defined(HAVE_PRI)
20383 ast_cond_init(&ss_thread_complete, NULL);
20388 static int dahdi_sendtext(
struct ast_channel *c,
const char *text)
20390 #define END_SILENCE_LEN 400
20391 #define HEADER_MS 50
20392 #define TRAILER_MS 5
20393 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
20394 #define ASCII_BYTES_PER_CHAR 80
20396 unsigned char *buf,*mybuf;
20397 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
20398 struct pollfd fds[1];
20399 int size,res,fd,len,x;
20416 idx = dahdi_get_index(c, p, 0);
20418 ast_log(LOG_WARNING,
"Huh? I don't exist?\n");
20421 if ((!p->
tdd) && (!p->
mate)) {
20422 #if defined(HAVE_PRI)
20423 #if defined(HAVE_PRI_DISPLAY_TEXT)
20424 ast_mutex_lock(&p->
lock);
20425 if (dahdi_sig_pri_lib_handles(p->
sig)) {
20428 ast_mutex_unlock(&p->
lock);
20434 buf =
ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
20436 buf =
ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
20444 for (x = 0; x < HEADER_MS; x++) {
20448 for (x = 0; text[x]; x++) {
20451 for (x = 0; x < TRAILER_MS; x++) {
20459 ast_log(LOG_ERROR,
"TDD generate (len %d) failed!!\n", (
int)strlen(text));
20464 memset(buf + len, 0x7f, END_SILENCE_LEN);
20465 len += END_SILENCE_LEN;
20466 fd = p->
subs[idx].dfd;
20473 if (size > READ_SIZE)
20476 fds[0].events = POLLOUT | POLLPRI;
20477 fds[0].revents = 0;
20478 res = poll(fds, 1, -1);
20484 if (fds[0].revents & POLLPRI) {
20488 if (!(fds[0].revents & POLLOUT)) {
20492 res = write(fd, buf, size);
20498 ast_debug(1,
"Write returned %d (%s) on channel %d\n", res, strerror(errno), p->
channel);
20509 static int reload(
void)
20513 res = setup_dahdi(1);
20515 ast_log(LOG_WARNING,
"Reload of chan_dahdi.so is unsuccessful!\n");
20526 .support_level = AST_MODULE_SUPPORT_CORE,
20528 .unload = unload_module,
20531 .requires =
"ccss",
20532 .optional_modules =
"res_smdi",
int cidpos
Position in the cidspill buffer to send out next.
int max_call_waiting_calls
Number of extra outgoing calls to allow on a span before considering that span congested.
void(* ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
Callback made from ast_cc_callback for certain channel types.
A-Law to Signed linear conversion.
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
unsigned int outgoing
TRUE if we originated the call leg.
unsigned int digital
TRUE if the transfer capability of the call is digital.
static void pri_queue_for_destruction(struct sig_pri_span *pri)
Queue a span for destruction.
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
struct ast_variable * next
int dialtone_scanning_time_elapsed
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
enum analog_dialmode dialmode
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
char description[32]
A description for the channel configuration.
Struct containing info for an AMI event to send out.
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
int presentation
Q.931 encoded presentation-indicator encoded field.
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
int dchan_logical_span[SIG_PRI_NUM_DCHANS]
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
unsigned int use_callerid
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Main Channel structure associated with a channel.
unsigned long display_flags_send
ast_device_state
Device States.
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
const char * type
Type of monitor the callbacks belong to.
char * str
Subscriber phone number (Malloced)
#define CIDCW_EXPIRE_SAMPLES
General Asterisk channel transcoding definitions.
#define PROC_DAHDI_OPT_NOWARN
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
#define AST_LIST_LOCK(head)
Locks a list.
unsigned int priexclusive
static struct ast_jb_conf default_jbconf
Asterisk locking-related definitions:
int cc_qsig_signaling_link_req
void astman_append(struct mansession *s, const char *fmt,...)
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
DTMF dial string complete.
unsigned int reoriginate
TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call.
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
struct sig_pri_callback sig_pri_callbacks
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
int congestion_devstate
Congestion device state of the span.
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
char * str
Subscriber phone number (Malloced)
char chan_name[AST_CHANNEL_NAME]
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
static const char dahdi_db[]
The AstDB family.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
#define AST_OPTION_TXGAIN
struct dahdi_subchannel subs[3]
unsigned int use_callingpres
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
int callwaitrings
Number of call waiting rings.
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
struct ast_party_id id
Connected party ID.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
int sig_pri_cc_agent_start_offer_timer(struct ast_cc_agent *agent)
Start the offer timer.
#define ast_channel_unref(c)
Decrease channel reference count.
#define SIG_PRI_DEBUG_NORMAL
char parkinglot[AST_MAX_EXTENSION]
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
static struct dahdi_pvt * fxo_pvt(struct ast_channel *chan)
Return DAHDI pivot if channel is FXO signalled.
unsigned int use_callerid
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
char idleext[AST_MAX_EXTENSION]
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_party_name name
Subscriber name.
#define DSP_DIGITMODE_DTMF
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
unsigned int hold_disconnect_transfer
TRUE if held calls are transferred on disconnect.
int ringt
Ring timeout timer??
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
struct ast_channel_snapshot * snapshot
Convenient Signal Processing routines.
unsigned int firstradio
TRUE if over a radio and dahdi_read() has been called.
#define CALLWAITING_SUPPRESS_SAMPLES
char mwi_vm_boxes[SIG_PRI_MAX_MWI_VM_NUMBER_STR]
Comma separated list of mailbox numbers sent over ISDN span for MWI.
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
unsigned int transfer
TRUE if call transfer is enabled for the span.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
unsigned int allow_call_waiting_calls
TRUE if we will allow incoming ISDN call waiting calls.
#define DSP_DIGITMODE_MUTECONF
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
struct dahdi_pvt * master
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
descriptor for a cli entry.
Interface header for PRI signaling module.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
int sig_pri_cc_monitor_status_rsp(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
Status response to an ast_cc_monitor_status_request().
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int sig_pri_cc_agent_callee_available(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
static int debug
Global debug status.
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
#define DSP_PROGRESS_TALK
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Native DAHDI bridging support.
void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update)
Set the caller information based on another caller source.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
unsigned int inservice
TRUE if channel is out of reset and ready.
struct ast_channel * owner
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
#define SRVST_TYPE_OOS
The out-of-service SERVICE state.
Structure for variables, used for configurations and for channel variables.
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
unsigned int mcid_send
TRUE if allow sending MCID request on this span.
struct ast_cc_config_params * cc_params
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
unsigned int hidecalleridname
int sig_pri_cc_agent_status_req(struct ast_cc_agent *agent)
Request the status of the agent's device.
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
unsigned int usefaxbuffers
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
struct analog_callback analog_callbacks
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) ...
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits...
Structure to pass both assignedid values to channel drivers.
unsigned int enable_service_message_support
struct sig_ss7_callback sig_ss7_callbacks
unsigned int aoce_delayhangup
Interface header for SS7 signaling module.
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
char * str
Subscriber name (Malloced)
unsigned int immediatering
TRUE if audible ringback should be provided when immediate = yes.
float cid_rxgain
Amount of gain to increase during caller id.
#define ANALOG_MATCH_DIGIT_TIMEOUT
Default time (ms) to wait, in case of ambiguous match.
enum sig_pri_reset_state resetting
Channel reset/restart state.
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
unsigned int ani_wink_time
INTEGER, length of time to wait before sending ANI wink in ms.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
unsigned char valid
TRUE if the subaddress information is valid/present.
unsigned int no_b_channel
TRUE if this interface has no B channel. (call hold and call waiting)
unsigned int inalarm
TRUE if channel is associated with a link that is down.
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
#define AST_OPTION_CC_AGENT_TYPE
The channel is not being RESTARTed.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
int sig_pri_cc_agent_party_b_free(struct ast_cc_agent *agent)
Let the caller know that the callee has become free but that the caller cannot attempt to call back b...
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
unsigned int transfertobusy
unsigned int ani_info_digits
INTEGER, number of ANI INFO digits on a CAMA trunk. older switches use 1 INFO digit, newer switches use 2 INFO digits.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define CID_MWI_TYPE_MDMF_FULL
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
int dchannels[SIG_PRI_NUM_DCHANS]
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
DAHDI internal API definitions.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
char * str
Malloced subaddress string.
unsigned int mwioverride_active
TRUE if a manual MWI override is active for a channel.
char mwi_vm_numbers[SIG_PRI_MAX_MWI_VM_NUMBER_STR]
Comma separated list of voicemail access controlling numbers for MWI.
int sig_pri_load(const char *cc_type_name)
Load the sig_pri submodule.
enum sig_pri_colp_signaling colp_send
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Common implementation-independent jitterbuffer stuff.
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
ADSI Support (built upon Caller*ID)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
unsigned int restartpending
const char * ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
Convert redirecting reason value to text code.
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
Delete the sig_pri private channel structure.
unsigned int inband_on_setup_ack
struct dahdi_pvt * oprpeer
int ast_unregister_application(const char *app)
Unregister an application.
int ringt_base
Ring timeout base.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) ...
float txgain
Software Tx gain set by chan_dahdi.conf.
static struct dahdi_pvt * ifend
struct timeval dtmfcid_delay
int code
enum AST_REDIRECTING_REASON value for redirection
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
struct ast_smdi_md_message * ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
Get the next SMDI message from the queue.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags)
Extract info out of callerID state machine. Flags are listed above.
struct ast_frame_subclass subclass
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
unsigned int pulse
TRUE if we will pulse dial.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Blob of data associated with a channel.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
All configuration options for http media cache.
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
struct ast_channel * owner
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
int cc_qsig_signaling_link_rsp
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
struct ast_party_id id
Caller party ID.
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
unsigned int answeronpolarityswitch
TRUE if we can use a polarity reversal to mark when an outgoing call is answered by the remote party...
Configuration File Parser.
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
#define DSP_DIGITMODE_RELAXDTMF
int dtmfcid_holdoff_state
unsigned int bufferoverrideinuse
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing some...
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
void sig_pri_cc_agent_destructor(struct ast_cc_agent *agent)
Destroy private data on the agent.
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn't catch this first)
u-Law to Signed linear conversion
unsigned int transfer
TRUE if call transfer is enabled.
#define ast_config_load(filename, flags)
Load a config file.
unsigned int use_callerid
TRUE if caller ID is used on this channel.
unsigned int echobreak
XXX BOOLEAN Purpose???
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Callback made when dial failed to get a channel out of dahdi_request().
struct ast_party_id ani
Automatic Number Identification (ANI)
General Asterisk PBX channel definitions.
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
struct dahdi_pvt * slaves[MAX_SLAVES]
unsigned int inband_on_proceeding
int sig_pri_cc_monitor_unsuspend(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
struct dahdi_pvt::@112 echocancel
Echo cancel parameters.
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Asterisk file paths, configured in asterisk.conf.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
#define AST_OPTION_RELAXDTMF
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
Replace a variable in the given list with a new value.
char echorest[20]
Filled with 'w'. XXX Purpose??
int cidlen
Length of the cidspill buffer containing samples.
#define SRVST_DBKEY
Persistent Service State.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
struct dahdi_confinfo saveconf
int sig_pri_is_chan_available(struct sig_pri_chan *pvt)
Determine if a private channel structure is available.
Data structure associated with a custom dialplan function.
static struct dahdi_pvt * round_robin[64]
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
int echotraining
Echo training time. 0 = disabled.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Caller Party information.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
int cid_ani2
Automatic Number Identification code from PRI.
static int cidrings[NUM_CADENCE_MAX]
cidrings says in which pause to transmit the cid information, where the first pause is 1...
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static int ringt_base
Configured ring timeout base.
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
#define MIN_MS_SINCE_FLASH
unsigned int immediatering
struct dahdi_vmwi_info mwisend_setting
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt's)
unsigned char * cidspill
Analog caller ID waveform sample buffer.
unsigned int permcallwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) ...
char internationalprefix[10]
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
int ast_cc_set_param(struct ast_cc_config_params *params, const char *const name, const char *value)
set a CCSS configuration parameter, given its name
void sig_pri_cc_monitor_destructor(void *monitor_pvt)
Destroy PRI private data on the monitor.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
#define ast_malloc(len)
A wrapper for malloc()
int sig_pri_cc_agent_start_monitoring(struct ast_cc_agent *agent)
Begin monitoring a busy device.
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int inservice
TRUE if channel is in service.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
An SMDI message desk message.
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
void sig_pri_cc_agent_req_rsp(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Response to a CC request.
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
char subscriberprefix[20]
Structure to describe a channel "technology", ie a channel driver See for examples: ...
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Core PBX routines and definitions.
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)
Determine if layer 1 alarms are ignored.
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
#define AST_CC_GENERIC_MONITOR_TYPE
static int load_module(void)
Load the module.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
unsigned int calledsubscriberheld
TRUE if Called Subscriber held is enabled. This allows a single incoming call to hold a DAHDI channel...
unsigned int use_callingpres
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_OPTION_ECHOCAN
unsigned int threewaysilenthold
TRUE if a three way dial tone should time out to silence.
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_party_subaddress subaddress
Subscriber subaddress.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
int waitfordialtoneduration
Transient variable. Stored off waitfordialtone duration at runtime.
struct timeval waitingfordt
const char * type
Type of agent the callbacks belong to.
#define AST_OPTION_DIGIT_DETECT
void sig_pri_stop_pri(struct sig_pri_span *pri)
Stop PRI span.
#define DSP_DIGITMODE_MUTEMAX
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
struct ast_dsp * dsp
Opaque DSP configuration structure.
int busycount
Number of times to see "busy" tone before hanging up.
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
unsigned int faxhandled
TRUE if a fax tone has already been handled.
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define PROC_DAHDI_OPT_NOCHAN
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Support for dynamic strings.
enum DAHDI_IFLIST which_iflist
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
unsigned int force_restart_unavailable_chans
TRUE if forcing RESTART when receive cause 44 on this span.
#define AST_OPTION_RXGAIN
struct tdd_state * tdd_new(void)
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
TTY/TDD Generation support.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
void sig_pri_unload(void)
Unload the sig_pri submodule.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define SIG_SS7_NUM_DCHANS
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
unsigned int use_callerid
TRUE if caller ID is used on this channel.
int ani2
Automatic Number Identification 2 (Info Digits)
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
unsigned int inbanddisconnect
#define SIG_PRI_NUM_DCHANS
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
const ast_string_field name
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
struct sig_pri_chan * pvts[SIG_PRI_MAX_CHANNELS]
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
char idledial[AST_MAX_EXTENSION]
void ast_log_callid(int level, const char *file, int line, const char *function, ast_callid callid, const char *fmt,...)
Used for sending a log message with a known call_id This is a modified logger function which is funct...
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
#define ast_module_ref(mod)
Hold a reference to the module.
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
struct ast_format_cap * capabilities
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
int muting
TRUE if confrence is muted.
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
unsigned long display_flags_receive
void stasis_subscription_cb_noop(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback function that does nothing.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
union ast_frame::@224 data
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
int sig_pri_ami_show_spans(struct mansession *s, const char *show_cmd, struct sig_pri_span *pri, const int *dchannels, const char *action_id)
Output AMI show spans response events for the given PRI span.
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
unsigned int hidecalleridname
#define ast_calloc(num, len)
A wrapper for calloc()
int sig_pri_cc_agent_stop_ringing(struct ast_cc_agent *agent)
Request for an agent's phone to stop ringing.
unsigned int append_msn_to_user_tag
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
unsigned int restrictcid
TRUE if caller ID is restricted.
char initial_user_tag[AST_MAX_EXTENSION]
Initial user tag for party id's sent from this device driver.
static int dahdi_answer(struct ast_channel *ast)
static int get_alarms(struct dahdi_pvt *p)
unsigned int dahditrcallerid
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
#define AST_OPTION_AUDIO_MODE
char mwi_mailboxes[SIG_PRI_MAX_MWI_MAILBOX_STR]
Comma separated list of mailboxes to indicate MWI.
Call Completion Supplementary Services API.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
unsigned int threewaycalling
TRUE if three way calling is enabled.
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
SMDI support for Asterisk.
unsigned int permhidecallerid
Module has failed to load, may be in an inconsistent state.
int wanted_channels_start
Don't create channels below this number.
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
char msn_list[AST_MAX_EXTENSION]
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
struct ast_party_redirecting_reason reason
Reason for the redirection.
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Structure used to handle boolean flags.
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
#define CALLWAITING_REPEAT_SAMPLES
int fake_event
Holding place for event injected from outside normal operation.
#define ast_module_unref(mod)
Release a reference to the module.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_frame ast_null_frame
unsigned int confirmanswer
TRUE if to wait for a DTMF digit to confirm answer.
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
int wanted_channels_end
Don't create channels above this number (infinity by default)
int sig_pri_cc_monitor_req_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
char * tag
User-set "tag".
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type)
A message type used to synchronize with the CDR topic.
int waitfordialtone
Number of milliseconds to wait for dialtone.
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Structure that contains information regarding a channel in a bridge.
int waitfordialtonetemp
Transient variable. Same as waitfordialtone, but temporarily set for a specific call, rather than permanently for the channel.
#define AST_OPTION_FAX_DETECT
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
#define ast_channel_ref(c)
Increase channel reference count.
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
int sig_pri_cc_agent_init(struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
PRI CC agent initialization.
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
Notify new alarm status.
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
unsigned int priexclusive
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
Extract info out of callerID state machine. Flags are listed above.
struct dahdi_distRings drings
Distinctive Ring data.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
unsigned int echocanon
TRUE if echo cancellation is turned on.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
unsigned int callwaitingcallerid
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
static struct dahdi_pvt * iflist
int num_call_waiting_calls
Number of outstanding call waiting calls.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
unsigned int call_qualifier
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
int ignore_failed_channels
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
void sig_pri_sendtext(struct sig_pri_chan *p, const char *text)
Send display text.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
int sig_pri_cc_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
struct ast_party_dialed::@206 number
Dialed/Called number.
int discardremoteholdretrieval
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Interface header for analog signaling module.
unsigned int use_callerid
unsigned int doreoriginate
Internal flag for if we should actually process a reorigination.
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Data structure associated with a single frame of data.
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Internal Asterisk hangup causes.
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
#define ANALOG_INTER_DIGIT_TIMEOUT
Default time (ms) to detect following digits.
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
char internationalprefix[10]
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Abstract JSON element (object, array, string, int, ...).
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
struct isup_call * ss7call
Opaque libss7 call control structure.
#define AST_OPTION_TONE_VERIFY
char cid_ani[AST_MAX_EXTENSION]
Automatic Number Identification number (Alternate PRI caller ID number)
unsigned int layer1_ignored
Handy terminal functions for vt* terms.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
float rxgain
Software Rx gain set by chan_dahdi.conf.
Callbacks defined by CC monitors.
unsigned char valid
TRUE if the name information is valid/present.
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct analog_subchannel subs[3]
void tdd_free(struct tdd_state *tdd)
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
struct ast_format * format
static const char dahdi_pri_cc_type[]
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
#define DSP_FEATURE_WAITDIALTONE
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
The structure that contains MWI state.
int radio
Nonzero if the signaling type is sent over a radio.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
unsigned int allocated
TRUE when this channel is allocated.
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
struct pri * dchans[SIG_PRI_NUM_DCHANS]
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
#define SRVST_NEAREND
SRVST_NEAREND is used to indicate that the near end was put out-of-service.
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
char language[MAX_LANGUAGE]
Language configured for calls.
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
ast_group_t group
Bitmapped groups this belongs to.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
int sig_pri_cc_agent_stop_offer_timer(struct ast_cc_agent *agent)
Stop the offer timer.
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
Extract the called number and subaddress from the dial string.
int ast_active_channels(void)
returns number of active/allocated channels
unsigned int inalarm
TRUE if in an alarm condition.
Persistent data storage (akin to *doze registry)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
int datetime_send
Configured date/time ie send policy option.
static char mwimonitornotify[PATH_MAX]
unsigned char valid
TRUE if the number information is valid/present.
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
General jitterbuffer configuration.
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
unsigned int calledsubscriberheld
ast_group_t callgroup
Bitmapped call groups this belongs to.
#define ast_custom_function_register(acf)
Register a custom function.
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
unsigned int permcallwaiting
unsigned int mate
TRUE if TDD in MATE mode.
char exten[AST_MAX_EXTENSION]
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
unsigned int canpark
TRUE if support for call parking is enabled.
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
int fds[SIG_PRI_NUM_DCHANS]
int sig_pri_cc_monitor_suspend(struct ast_cc_monitor *monitor)
Suspend monitoring.
unsigned int ani_timeout
INTEGER, length of ANI failure timeout in ms.
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
unsigned int mwisend_rpas
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
char begindigit
DTMF digit in progress. 0 when no digit in progress.
#define SRVST_FAREND
SRVST_FAREND is used to indicate that the far end was taken out-of-service.
Configuration relating to call pickup.
#define AST_APP_ARG(name)
Define an application argument.
int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for 'n' samples.
unsigned int mwioverride_disposition
Manual MWI disposition (on/off)
char accountcode[AST_MAX_ACCOUNT_CODE]
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
struct ast_party_number number
Subscriber phone number.
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
unsigned int mwimonitor_rpas
TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end...
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.