📄 chan_dahdi.c
字号:
set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); mysig = p->sig; if (p->outsigmod > -1) mysig = p->outsigmod; switch (mysig) { case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: if (p->owner == ast) { /* Normal ring, on hook */ /* Don't send audio while on hook, until the call is answered */ p->dialing = 1; if (p->use_callerid) { /* Generate the Caller-ID spill if desired */ if (p->cidspill) { ast_log(LOG_WARNING, "cidspill already exists??\n"); free(p->cidspill); } p->callwaitcas = 0; if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); p->cidpos = 0; send_callerid(p); } } /* Choose proper cadence */ if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); p->cidrings = cidrings[p->distinctivering - 1]; } else { if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); p->cidrings = p->sendcalleridafter; } /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ c = strchr(dest, '/'); if (c) c++; if (c && (strlen(c) < p->stripmsd)) { ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); c = NULL; } if (c) { p->dop.op = DAHDI_DIAL_OP_REPLACE; snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); } else { p->dop.dialstr[0] = '\0'; } x = DAHDI_RING; if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); ast_mutex_unlock(&p->lock); return -1; } p->dialing = 1; } else { /* Call waiting call */ p->callwaitrings = 0; if (ast->cid.cid_num) ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); else p->callwait_num[0] = '\0'; if (ast->cid.cid_name) ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); else p->callwait_name[0] = '\0'; /* Call waiting tone instead */ if (dahdi_callwait(ast)) { ast_mutex_unlock(&p->lock); return -1; } /* Make ring-back */ if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); } n = ast->cid.cid_name; l = ast->cid.cid_num; if (l) ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); else p->lastcid_num[0] = '\0'; if (n) ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); else p->lastcid_name[0] = '\0'; ast_setstate(ast, AST_STATE_RINGING); index = dahdi_get_index(ast, p, 0); if (index > -1) { p->subs[index].needringing = 1; } break; case SIG_FXSLS: case SIG_FXSGS: case SIG_FXSKS: case SIG_EMWINK: case SIG_EM: case SIG_EM_E1: case SIG_FEATD: case SIG_FEATDMF: case SIG_E911: case SIG_FGC_CAMA: case SIG_FGC_CAMAMF: case SIG_FEATB: case SIG_SFWINK: case SIG_SF: case SIG_SF_FEATD: case SIG_SF_FEATDMF: case SIG_FEATDMF_TA: case SIG_SF_FEATB: c = strchr(dest, '/'); if (c) c++; else c = ""; if (strlen(c) < p->stripmsd) { ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); ast_mutex_unlock(&p->lock); return -1; }#ifdef HAVE_PRI /* Start the trunk, if not GR-303 */ if (!p->pri) {#endif x = DAHDI_START; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); if (res < 0) { if (errno != EINPROGRESS) { ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); ast_mutex_unlock(&p->lock); return -1; } }#ifdef HAVE_PRI }#endif ast_log(LOG_DEBUG, "Dialing '%s'\n", c); p->dop.op = DAHDI_DIAL_OP_REPLACE; c += p->stripmsd; switch (mysig) { case SIG_FEATD: l = ast->cid.cid_num; if (l) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); else snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); break; case SIG_FEATDMF: l = ast->cid.cid_num; if (l) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); else snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); break; case SIG_FEATDMF_TA: { const char *cic, *ozz; /* If you have to go through a Tandem Access point you need to use this */ ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); if (!ozz) ozz = defaultozz; cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); if (!cic) cic = defaultcic; if (!ozz || !cic) { ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); ast_mutex_unlock(&p->lock); return -1; } snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); p->whichwink = 0; } break; case SIG_E911: ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); break; case SIG_FGC_CAMA: snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); break; case SIG_FGC_CAMAMF: case SIG_FEATB: snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); break; default: if (p->pulse) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); else snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); break; } if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { memset(p->echorest, 'w', sizeof(p->echorest) - 1); strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); p->echorest[sizeof(p->echorest) - 1] = '\0'; p->echobreak = 1; p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; } else p->echobreak = 0; if (!res) { if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { int saveerr = errno; x = DAHDI_ONHOOK; ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); ast_mutex_unlock(&p->lock); return -1; } } else ast_log(LOG_DEBUG, "Deferring dialing...\n"); p->dialing = 1; if (ast_strlen_zero(c)) p->dialednone = 1; ast_setstate(ast, AST_STATE_DIALING); break; case 0: /* Special pseudo -- automatically up*/ ast_setstate(ast, AST_STATE_UP); break; case SIG_PRI: /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ p->dialdest[0] = '\0'; break; default: ast_log(LOG_DEBUG, "not yet implemented\n"); ast_mutex_unlock(&p->lock); return -1; }#ifdef HAVE_PRI if (p->pri) { struct pri_sr *sr;#ifdef SUPPORT_USERUSER const char *useruser;#endif int pridialplan; int dp_strip; int prilocaldialplan; int ldp_strip; int exclusive; const char *rr_str; int redirect_reason; c = strchr(dest, '/'); if (c) c++; else c = dest; l = NULL; n = NULL; if (!p->hidecallerid) { l = ast->cid.cid_num; if (!p->hidecalleridname) { n = ast->cid.cid_name; } } if (strlen(c) < p->stripmsd) { ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); ast_mutex_unlock(&p->lock); return -1; } if (mysig != SIG_FXSKS) { p->dop.op = DAHDI_DIAL_OP_REPLACE; s = strchr(c + p->stripmsd, 'w'); if (s) { if (strlen(s) > 1) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); else p->dop.dialstr[0] = '\0'; *s = '\0'; } else { p->dop.dialstr[0] = '\0'; } } if (pri_grab(p, p->pri)) { ast_log(LOG_WARNING, "Failed to grab PRI!\n"); ast_mutex_unlock(&p->lock); return -1; } if (!(p->call = pri_new_call(p->pri->pri))) { ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); pri_rel(p->pri); ast_mutex_unlock(&p->lock); return -1; } if (!(sr = pri_sr_new())) { ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); pri_destroycall(p->pri->pri, p->call); p->call = NULL; pri_rel(p->pri); ast_mutex_unlock(&p->lock); return -1; } if (p->bearer || (mysig == SIG_FXSKS)) { if (p->bearer) { ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); p->bearer->call = p->call; } else ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); pri_set_crv(p->pri->pri, p->call, p->channel, 0); } p->digital = IS_DIGITAL(ast->transfercapability); /* Add support for exclusive override */ if (p->priexclusive) exclusive = 1; else { /* otherwise, traditional behavior */ if (p->pri->nodetype == PRI_NETWORK) exclusive = 0; else exclusive = 1; } pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, (p->digital ? -1 : ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); if (p->pri->facilityenable) pri_facility_enable(p->pri->pri); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); dp_strip = 0; pridialplan = p->pri->dialplan - 1; if (pridialplan == -2) { /* compute dynamically */ if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { dp_strip = strlen(p->pri->internationalprefix); pridialplan = PRI_INTERNATIONAL_ISDN; } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { dp_strip = strlen(p->pri->nationalprefix); pridialplan = PRI_NATIONAL_ISDN; } else { pridialplan = PRI_LOCAL_ISDN; } } pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); ldp_strip = 0; prilocaldialplan = p->pri->localdialplan - 1; if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { ldp_strip = strlen(p->pri->internationalprefix); prilocaldialplan = PRI_INTERNATIONAL_ISDN; } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { ldp_strip = strlen(p->pri->nationalprefix); prilocaldialplan = PRI_NATIONAL_ISDN; } else { prilocaldialplan = PRI_LOCAL_ISDN; } } pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { if (!strcasecmp(rr_str, "UNKNOWN")) redirect_reason = 0; else if (!strcasecmp(rr_str, "BUSY")) redirect_reason = 1; else if (!strcasecmp(rr_str, "NO_REPLY")) redirect_reason = 2; else if (!strcasecmp(rr_str, "UNCONDITIONAL")) redirect_reason = 15; else redirect_reason = PRI_REDIR_UNCONDITIONAL; } else redirect_reason = PRI_REDIR_UNCONDITIONAL; pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);#ifdef SUPPORT_USERUSER /* User-user info */ useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); if (useruser) pri_sr_set_useruser(sr, useruser);#endif if (pri_setup(p->pri->pri, p->call, sr)) { ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); pri_rel(p->pri); ast_mutex_unlock(&p->lock); pri_sr_free(sr); return -1; } pri_sr_free(sr); ast_setstate(ast, AST_STATE_DIALING); pri_rel(p->pri); }#endif ast_mutex_unlock(&p->lock); return 0;}static void destroy_dahdi_pvt(struct dahdi_pvt **pvt){ struct dahdi_pvt *p = *pvt; /* Remove channel from the list */ if (p->prev) p->prev->next = p->next; if (p->next) p->next->prev = p->prev; if (p->use_smdi) ast_smdi_interface_unref(p->smdi_iface); ast_mutex_destroy(&p->lock); dahdi_close_sub(p, SUB_REAL); if (p->owner) p->owner->tech_pvt = NULL; free(p); *pvt = NULL;}static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now){ int owned = 0; int i = 0; if (!now) { if (cur->owner) { owned = 1; } for (i = 0; i < 3; i++) { if (cur->subs[i].owner) { owned = 1; } } if (!owned) { if (prev) { prev->next = cur->next; if (prev->next) prev->next->prev = prev; else ifend = prev; } else { iflist = cur->next; if (iflist) iflist->prev = NULL; else ifend = NULL; } destroy_dahdi_pvt(&cur); } } else { if (prev) { prev->next = cur->next; if (prev->next) prev->next->prev = prev; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -