📄 chan_dahdi.c
字号:
if (chan) { if (ioctl(fd, DAHDI_SPECIFY, &chan)) { x = errno; close(fd); errno = x; ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); return -1; } } bs = READ_SIZE; if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); x = errno; close(fd); errno = x; return -1; } return fd;}static void dahdi_close(int fd){ if (fd > 0) close(fd);}static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num){ dahdi_close(chan_pvt->subs[sub_num].dfd); chan_pvt->subs[sub_num].dfd = -1;} #ifdef HAVE_PRIstatic void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num){ dahdi_close(pri->fds[fd_num]); pri->fds[fd_num] = -1;}#endifstatic int dahdi_setlinear(int dfd, int linear){ int res; res = ioctl(dfd, DAHDI_SETLINEAR, &linear); if (res) return res; return 0;}static int alloc_sub(struct dahdi_pvt *p, int x){ struct dahdi_bufferinfo bi; int res; if (p->subs[x].dfd < 0) {#ifdef HAVE_ZAPTEL p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");#else p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");#endif if (p->subs[x].dfd > -1) { res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); if (!res) { bi.txbufpolicy = p->buf_policy; bi.rxbufpolicy = p->buf_policy; bi.numbufs = p->buf_no; res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); if (res < 0) { ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); } } else ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); dahdi_close_sub(p, x); return -1; } if (option_debug) ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); return 0; } else ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); return -1; } ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); return -1;}static int unalloc_sub(struct dahdi_pvt *p, int x){ if (!x) { ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); return -1; } ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); dahdi_close_sub(p, x); p->subs[x].linear = 0; p->subs[x].chan = 0; p->subs[x].owner = NULL; p->subs[x].inthreeway = 0; p->polarity = POLARITY_IDLE; memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); return 0;}static int digit_to_dtmfindex(char digit){ if (isdigit(digit)) return DAHDI_TONE_DTMF_BASE + (digit - '0'); else if (digit >= 'A' && digit <= 'D') return DAHDI_TONE_DTMF_A + (digit - 'A'); else if (digit >= 'a' && digit <= 'd') return DAHDI_TONE_DTMF_A + (digit - 'a'); else if (digit == '*') return DAHDI_TONE_DTMF_s; else if (digit == '#') return DAHDI_TONE_DTMF_p; else return -1;}static int dahdi_digit_begin(struct ast_channel *chan, char digit){ struct dahdi_pvt *pvt; int index; int dtmf = -1; pvt = chan->tech_pvt; ast_mutex_lock(&pvt->lock); index = dahdi_get_index(chan, pvt, 0); if ((index != SUB_REAL) || !pvt->owner) goto out;#ifdef HAVE_PRI if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { if (pvt->setup_ack) { if (!pri_grab(pvt, pvt->pri)) { pri_information(pvt->pri->pri, pvt->call, digit); pri_rel(pvt->pri); } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { int res; ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); res = strlen(pvt->dialdest); pvt->dialdest[res++] = digit; pvt->dialdest[res] = '\0'; } goto out; }#endif if ((dtmf = digit_to_dtmfindex(digit)) == -1) goto out; if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { int res; struct dahdi_dialoperation zo = { .op = DAHDI_DIAL_OP_APPEND, .dialstr[0] = 'T', .dialstr[1] = digit, .dialstr[2] = 0, }; if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); else pvt->dialing = 1; } else { ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); pvt->dialing = 1; pvt->begindigit = digit; }out: ast_mutex_unlock(&pvt->lock); return 0;}static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration){ struct dahdi_pvt *pvt; int res = 0; int index; int x; pvt = chan->tech_pvt; ast_mutex_lock(&pvt->lock); index = dahdi_get_index(chan, pvt, 0); if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) goto out;#ifdef HAVE_PRI /* This means that the digit was already sent via PRI signalling */ if (pvt->sig == SIG_PRI && !pvt->begindigit) goto out;#endif if (pvt->begindigit) { x = -1; ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); pvt->dialing = 0; pvt->begindigit = 0; }out: ast_mutex_unlock(&pvt->lock); return res;}static char *events[] = { "No event", "On hook", "Ring/Answered", "Wink/Flash", "Alarm", "No more alarm", "HDLC Abort", "HDLC Overrun", "HDLC Bad FCS", "Dial Complete", "Ringer On", "Ringer Off", "Hook Transition Complete", "Bits Changed", "Pulse Start", "Timer Expired", "Timer Ping", "Polarity Reversal", "Ring Begin",};static struct { int alarm; char *name;} alarms[] = { { DAHDI_ALARM_RED, "Red Alarm" }, { DAHDI_ALARM_YELLOW, "Yellow Alarm" }, { DAHDI_ALARM_BLUE, "Blue Alarm" }, { DAHDI_ALARM_RECOVER, "Recovering" }, { DAHDI_ALARM_LOOPBACK, "Loopback" }, { DAHDI_ALARM_NOTOPEN, "Not Open" }, { DAHDI_ALARM_NONE, "None" },};static char *alarm2str(int alarm){ int x; for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { if (alarms[x].alarm & alarm) return alarms[x].name; } return alarm ? "Unknown Alarm" : "No Alarm";}static char *event2str(int event){ static char buf[256]; if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) return events[event]; sprintf(buf, "Event %d", event); /* safe */ return buf;}#ifdef HAVE_PRIstatic char *dialplan2str(int dialplan){ if (dialplan == -1) { return("Dynamically set dialplan in ISDN"); } return (pri_plan2str(dialplan));}#endifstatic char *dahdi_sig2str(int sig){ static char buf[256]; switch (sig) { case SIG_EM: return "E & M Immediate"; case SIG_EMWINK: return "E & M Wink"; case SIG_EM_E1: return "E & M E1"; case SIG_FEATD: return "Feature Group D (DTMF)"; case SIG_FEATDMF: return "Feature Group D (MF)"; case SIG_FEATDMF_TA: return "Feature Groud D (MF) Tandem Access"; case SIG_FEATB: return "Feature Group B (MF)"; case SIG_E911: return "E911 (MF)"; case SIG_FGC_CAMA: return "FGC/CAMA (Dialpulse)"; case SIG_FGC_CAMAMF: return "FGC/CAMA (MF)"; case SIG_FXSLS: return "FXS Loopstart"; case SIG_FXSGS: return "FXS Groundstart"; case SIG_FXSKS: return "FXS Kewlstart"; case SIG_FXOLS: return "FXO Loopstart"; case SIG_FXOGS: return "FXO Groundstart"; case SIG_FXOKS: return "FXO Kewlstart"; case SIG_PRI: return "ISDN PRI"; case SIG_SF: return "SF (Tone) Immediate"; case SIG_SFWINK: return "SF (Tone) Wink"; case SIG_SF_FEATD: return "SF (Tone) with Feature Group D (DTMF)"; case SIG_SF_FEATDMF: return "SF (Tone) with Feature Group D (MF)"; case SIG_SF_FEATB: return "SF (Tone) with Feature Group B (MF)"; case SIG_GR303FXOKS: return "GR-303 with FXOKS"; case SIG_GR303FXSKS: return "GR-303 with FXSKS"; case 0: return "Pseudo"; default: snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); return buf; }}#define sig2str dahdi_sig2strstatic int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel){ /* If the conference already exists, and we're already in it don't bother doing anything */ struct dahdi_confinfo zi; memset(&zi, 0, sizeof(zi)); zi.chan = 0; if (slavechannel > 0) { /* If we have only one slave, do a digital mon */ zi.confmode = DAHDI_CONF_DIGITALMON; zi.confno = slavechannel; } else { if (!index) { /* Real-side and pseudo-side both participate in conference */ zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; } else zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; zi.confno = p->confno; } if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) return 0; if (c->dfd < 0) return 0; if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); return -1; } if (slavechannel < 1) { p->confno = zi.confno; } memcpy(&c->curconf, &zi, sizeof(c->curconf)); ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); return 0;}static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c){ /* If they're listening to our channel, they're ours */ if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) return 1; /* If they're a talker on our (allocated) conference, they're ours */ if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) return 1; return 0;}static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index){ struct dahdi_confinfo zi; if (/* Can't delete if there's no dfd */ (c->dfd < 0) || /* Don't delete from the conference if it's not our conference */ !isourconf(p, c) /* Don't delete if we don't think it's conferenced at all (implied) */ ) return 0; memset(&zi, 0, sizeof(zi)); zi.chan = 0; zi.confno = 0; zi.confmode = 0; if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); return -1; } ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); memcpy(&c->curconf, &zi, sizeof(c->curconf)); return 0;}static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out){ int x; int useslavenative; struct dahdi_pvt *slave = NULL; /* Start out optimistic */ useslavenative = 1; /* Update conference state in a stateless fashion */ for (x = 0; x < 3; x++) { /* Any three-way calling makes slave native mode *definitely* out of the question */ if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) useslavenative = 0; } /* If we don't have any 3-way calls, check to see if we have precisely one slave */ if (useslavenative) { for (x = 0; x < MAX_SLAVES; x++) { if (p->slaves[x]) { if (slave) { /* Whoops already have a slave! No slave native and stop right away */ slave = NULL; useslavenative = 0; break; } else { /* We have one slave so far */ slave = p->slaves[x]; } } } } /* If no slave, slave native definitely out */ if (!slave) useslavenative = 0; else if (slave->law != p->law) { useslavenative = 0; slave = NULL; } if (out) *out = slave; return useslavenative;}static int reset_conf(struct dahdi_pvt *p){ struct dahdi_confinfo zi; memset(&zi, 0, sizeof(zi)); p->confno = -1; memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -