📄 chan_dahdi.c
字号:
if (p->subs[SUB_REAL].dfd > -1) { if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); } return 0;}static int update_conf(struct dahdi_pvt *p){ int needconf = 0; int x; int useslavenative; struct dahdi_pvt *slave = NULL; useslavenative = isslavenative(p, &slave); /* Start with the obvious, general stuff */ for (x = 0; x < 3; x++) { /* Look for three way calls */ if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { conf_add(p, &p->subs[x], x, 0); needconf++; } else { conf_del(p, &p->subs[x], x); } } /* If we have a slave, add him to our conference now. or DAX if this is slave native */ for (x = 0; x < MAX_SLAVES; x++) { if (p->slaves[x]) { if (useslavenative) conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); else { conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); needconf++; } } } /* If we're supposed to be in there, do so now */ if (p->inconference && !p->subs[SUB_REAL].inthreeway) { if (useslavenative) conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); else { conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); needconf++; } } /* If we have a master, add ourselves to his conference */ if (p->master) { if (isslavenative(p->master, NULL)) { conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); } else { conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); } } if (!needconf) { /* Nobody is left (or should be left) in our conference. Kill it. */ p->confno = -1; } if (option_debug) ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); return 0;}static void dahdi_enable_ec(struct dahdi_pvt *p){ int x; int res; if (!p) return; if (p->echocanon) { ast_log(LOG_DEBUG, "Echo cancellation already on\n"); return; } if (p->digital) { ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); return; } if (p->echocancel) { if (p->sig == SIG_PRI) { x = 1; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); if (res) ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); } x = p->echocancel; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); if (res) ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); else { p->echocanon = 1; if (option_debug) ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); } } else if (option_debug) ast_log(LOG_DEBUG, "No echo cancellation requested\n");}static void dahdi_train_ec(struct dahdi_pvt *p){ int x; int res; if (p && p->echocancel && p->echotraining) { x = p->echotraining; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); if (res) ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); else { ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); } } else ast_log(LOG_DEBUG, "No echo training requested\n");}static void dahdi_disable_ec(struct dahdi_pvt *p){ int x; int res; if (p->echocancel) { x = 0; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); if (res) ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); else if (option_debug) ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); } p->echocanon = 0;}static void fill_txgain(struct dahdi_gains *g, float gain, int law){ int j; int k; float linear_gain = pow(10.0, gain / 20.0); switch (law) { case DAHDI_LAW_ALAW: for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { if (gain) { k = (int) (((float) AST_ALAW(j)) * linear_gain); if (k > 32767) k = 32767; if (k < -32767) k = -32767; g->txgain[j] = AST_LIN2A(k); } else { g->txgain[j] = j; } } break; case DAHDI_LAW_MULAW: for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { if (gain) { k = (int) (((float) AST_MULAW(j)) * linear_gain); if (k > 32767) k = 32767; if (k < -32767) k = -32767; g->txgain[j] = AST_LIN2MU(k); } else { g->txgain[j] = j; } } break; }}static void fill_rxgain(struct dahdi_gains *g, float gain, int law){ int j; int k; float linear_gain = pow(10.0, gain / 20.0); switch (law) { case DAHDI_LAW_ALAW: for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { if (gain) { k = (int) (((float) AST_ALAW(j)) * linear_gain); if (k > 32767) k = 32767; if (k < -32767) k = -32767; g->rxgain[j] = AST_LIN2A(k); } else { g->rxgain[j] = j; } } break; case DAHDI_LAW_MULAW: for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { if (gain) { k = (int) (((float) AST_MULAW(j)) * linear_gain); if (k > 32767) k = 32767; if (k < -32767) k = -32767; g->rxgain[j] = AST_LIN2MU(k); } else { g->rxgain[j] = j; } } break; }}static int set_actual_txgain(int fd, int chan, float gain, int law){ struct dahdi_gains g; int res; memset(&g, 0, sizeof(g)); g.chan = chan; res = ioctl(fd, DAHDI_GETGAINS, &g); if (res) { if (option_debug) ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); return res; } fill_txgain(&g, gain, law); return ioctl(fd, DAHDI_SETGAINS, &g);}static int set_actual_rxgain(int fd, int chan, float gain, int law){ struct dahdi_gains g; int res; memset(&g, 0, sizeof(g)); g.chan = chan; res = ioctl(fd, DAHDI_GETGAINS, &g); if (res) { ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); return res; } fill_rxgain(&g, gain, law); return ioctl(fd, DAHDI_SETGAINS, &g);}static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law){ return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);}static int bump_gains(struct dahdi_pvt *p){ int res; /* Bump receive gain by 5.0db */ res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); if (res) { ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); return -1; } return 0;}static int restore_gains(struct dahdi_pvt *p){ int res; res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); if (res) { ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); return -1; } return 0;}static inline int dahdi_set_hook(int fd, int hs){ int x, res; x = hs; res = ioctl(fd, DAHDI_HOOK, &x); if (res < 0) { if (errno == EINPROGRESS) return 0; ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); /* will expectedly fail if phone is off hook during operation, such as during a restart */ } return res;}static inline int dahdi_confmute(struct dahdi_pvt *p, int muted){ int x, y, res; x = muted; if (p->sig == SIG_PRI) { y = 1; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); if (res) ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); } res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); if (res < 0) ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); return res;}static int save_conference(struct dahdi_pvt *p){ struct dahdi_confinfo c; int res; if (p->saveconf.confmode) { ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); return -1; } p->saveconf.chan = 0; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); if (res) { ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); p->saveconf.confmode = 0; return -1; } c.chan = 0; c.confno = 0; c.confmode = DAHDI_CONF_NORMAL; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); if (res) { ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); return -1; } if (option_debug) ast_log(LOG_DEBUG, "Disabled conferencing\n"); return 0;}static int restore_conference(struct dahdi_pvt *p){ int res; if (p->saveconf.confmode) { res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); p->saveconf.confmode = 0; if (res) { ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); return -1; } } if (option_debug) ast_log(LOG_DEBUG, "Restored conferencing\n"); return 0;}static int send_callerid(struct dahdi_pvt *p);static int send_cwcidspill(struct dahdi_pvt *p){ p->callwaitcas = 0; p->cidcwexpire = 0; if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) return -1; p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); /* Make sure we account for the end */ p->cidlen += READ_SIZE * 4; p->cidpos = 0; send_callerid(p); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); return 0;}static int has_voicemail(struct dahdi_pvt *p){ return ast_app_has_voicemail(p->mailbox, NULL);}static int send_callerid(struct dahdi_pvt *p){ /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ int res; /* Take out of linear mode if necessary */ if (p->subs[SUB_REAL].linear) { p->subs[SUB_REAL].linear = 0; dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); } while (p->cidpos < p->cidlen) { res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); if (res < 0) { if (errno == EAGAIN) return 0; else { ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); return -1; } } if (!res) return 0; p->cidpos += res; } free(p->cidspill); p->cidspill = NULL; if (p->callwaitcas) { /* Wait for CID/CW to expire */ p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; } else restore_conference(p); return 0;}static int dahdi_callwait(struct ast_channel *ast){ struct dahdi_pvt *p = ast->tech_pvt; p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; if (p->cidspill) { ast_log(LOG_WARNING, "Spill already exists?!?\n"); free(p->cidspill); } if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) return -1; save_conference(p); /* Silence */ memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); if (!p->callwaitrings && p->callwaitingcallerid) { ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); p->callwaitcas = 1; p->cidlen = 2400 + 680 + READ_SIZE * 4; } else { ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); p->callwaitcas = 0; p->cidlen = 2400 + READ_SIZE * 4; } p->cidpos = 0; send_callerid(p); return 0;}static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout){ struct dahdi_pvt *p = ast->tech_pvt; int x, res, index,mysig; char *c, *n, *l;#ifdef HAVE_PRI char *s = NULL;#endif char dest[256]; /* must be same length as p->dialdest */ ast_mutex_lock(&p->lock); ast_copy_string(dest, rdest, sizeof(dest)); ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); if ((ast->_state == AST_STATE_BUSY)) { p->subs[SUB_REAL].needbusy = 1; ast_mutex_unlock(&p->lock); return 0; } if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); ast_mutex_unlock(&p->lock); return -1; } p->dialednone = 0; if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ { /* Special pseudo -- automatically up */ ast_setstate(ast, AST_STATE_UP); ast_mutex_unlock(&p->lock); return 0; } x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); if (res) ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); p->outgoing = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -