📄 chan_dahdi.c
字号:
unsigned int ignoredtmf:1; unsigned int immediate:1; /*!< Answer before getting digits? */ unsigned int inalarm:1; unsigned int unknown_alarm:1; unsigned int mate:1; /*!< flag to say its in MATE mode */ unsigned int outgoing:1; unsigned int overlapdial:1; unsigned int permcallwaiting:1; unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */ unsigned int priindication_oob:1; unsigned int priexclusive:1; unsigned int pulse:1; unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */ unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */ unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */ unsigned int threewaycalling:1; unsigned int transfer:1; unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */ unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */ unsigned int usedistinctiveringdetection:1; unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */ unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */#if defined(HAVE_PRI) unsigned int alerting:1; unsigned int alreadyhungup:1; unsigned int isidlecall:1; unsigned int proceeding:1; unsigned int progress:1; unsigned int resetting:1; unsigned int setup_ack:1;#endif unsigned int use_smdi:1; /* Whether to use SMDI on this channel */ struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */ struct dahdi_distRings drings; char context[AST_MAX_CONTEXT]; char defcontext[AST_MAX_CONTEXT]; char exten[AST_MAX_EXTENSION]; char language[MAX_LANGUAGE]; char mohinterpret[MAX_MUSICCLASS]; char mohsuggest[MAX_MUSICCLASS];#ifdef PRI_ANI char cid_ani[AST_MAX_EXTENSION];#endif char cid_num[AST_MAX_EXTENSION]; int cid_ton; /*!< Type Of Number (TON) */ char cid_name[AST_MAX_EXTENSION]; char lastcid_num[AST_MAX_EXTENSION]; char lastcid_name[AST_MAX_EXTENSION]; char *origcid_num; /*!< malloced original callerid */ char *origcid_name; /*!< malloced original callerid */ char callwait_num[AST_MAX_EXTENSION]; char callwait_name[AST_MAX_EXTENSION]; char rdnis[AST_MAX_EXTENSION]; char dnid[AST_MAX_EXTENSION]; ast_group_t group; int law; int confno; /*!< Our conference */ int confusers; /*!< Who is using our conference */ int propconfno; /*!< Propagated conference number */ ast_group_t callgroup; ast_group_t pickupgroup; int channel; /*!< Channel Number or CRV */ int span; /*!< Span number */ time_t guardtime; /*!< Must wait this much time before using for new call */ int cid_signalling; /*!< CID signalling type bell202 or v23 */ int cid_start; /*!< CID start indicator, polarity or ring */ int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */ int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */ int cidcwexpire; /*!< When to expire our muting for CID/CW */ unsigned char *cidspill; int cidpos; int cidlen; int ringt; int ringt_base; int stripmsd; int callwaitcas; int callwaitrings; int echocancel; int echotraining; char echorest[20]; int busycount; int busy_tonelength; int busy_quietlength; int callprogress; struct timeval flashtime; /*!< Last flash-hook time */ struct ast_dsp *dsp; int cref; /*!< Call reference number */ struct dahdi_dialoperation dop; int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */ char finaldial[64]; char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */ int amaflags; /*!< AMA Flags */ struct tdd_state *tdd; /*!< TDD flag */ char call_forward[AST_MAX_EXTENSION]; char mailbox[AST_MAX_EXTENSION]; char dialdest[256]; int onhooktime; int msgstate; int distinctivering; /*!< Which distinctivering to use */ int cidrings; /*!< Which ring to deliver CID on */ int dtmfrelax; /*!< whether to run in relaxed DTMF mode */ int fake_event; int polarityonanswerdelay; struct timeval polaritydelaytv; int sendcalleridafter;#ifdef HAVE_PRI struct dahdi_pri *pri; struct dahdi_pvt *bearer; struct dahdi_pvt *realcall; q931_call *call; int prioffset; int logicalspan;#endif int polarity; int dsp_features; char begindigit;} *iflist = NULL, *ifend = NULL;/*! \brief Channel configuration from chan_dahdi.conf . * This struct is used for parsing the [channels] section of chan_dahdi.conf. * Generally there is a field here for every possible configuration item. * * The state of fields is saved along the parsing and whenever a 'channel' * statement is reached, the current dahdi_chan_conf is used to configure the * channel (struct dahdi_pvt) * * @seealso dahdi_chan_init for the default values. */struct dahdi_chan_conf { struct dahdi_pvt chan;#ifdef HAVE_PRI struct dahdi_pri pri;#endif struct dahdi_params timing; char smdi_port[SMDI_MAX_FILENAME_LEN];};/** returns a new dahdi_chan_conf with default values (by-value) */static struct dahdi_chan_conf dahdi_chan_conf_default(void) { /* recall that if a field is not included here it is initialized * to 0 or equivalent */ struct dahdi_chan_conf conf = {#ifdef HAVE_PRI .pri = { .nsf = PRI_NSF_NONE, .switchtype = PRI_SWITCH_NI2, .dialplan = PRI_NATIONAL_ISDN + 1, .localdialplan = PRI_NATIONAL_ISDN + 1, .nodetype = PRI_CPE, .minunused = 2, .idleext = "", .idledial = "", .internationalprefix = "", .nationalprefix = "", .localprefix = "", .privateprefix = "", .unknownprefix = "", .resetinterval = 3600 },#endif .chan = { .context = "default", .cid_num = "", .cid_name = "", .mohinterpret = "default", .mohsuggest = "", .transfertobusy = 1, .cid_signalling = CID_SIG_BELL, .cid_start = CID_START_RING, .dahditrcallerid = 0, .use_callerid = 1, .sig = -1, .outsigmod = -1, .tonezone = -1, .echocancel = 1, .busycount = 3, .accountcode = "", .mailbox = "", .polarityonanswerdelay = 600, .sendcalleridafter = DEFAULT_CIDRINGS, .buf_policy = DAHDI_POLICY_IMMEDIATE, .buf_no = numbufs }, .timing = { .prewinktime = -1, .preflashtime = -1, .winktime = -1, .flashtime = -1, .starttime = -1, .rxwinktime = -1, .rxflashtime = -1, .debouncetime = -1 }, .smdi_port = "/dev/ttyS0", }; return conf;}static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);static int dahdi_digit_begin(struct ast_channel *ast, char digit);static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);static int dahdi_sendtext(struct ast_channel *c, const char *text);static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);static int dahdi_hangup(struct ast_channel *ast);static int dahdi_answer(struct ast_channel *ast);static struct ast_frame *dahdi_read(struct ast_channel *ast);static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);static struct ast_frame *dahdi_exception(struct ast_channel *ast);static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); static const struct ast_channel_tech dahdi_tech = { .type = "DAHDI", .description = tdesc, .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW, .requester = dahdi_request, .send_digit_begin = dahdi_digit_begin, .send_digit_end = dahdi_digit_end, .send_text = dahdi_sendtext, .call = dahdi_call, .hangup = dahdi_hangup, .answer = dahdi_answer, .read = dahdi_read, .write = dahdi_write, .bridge = dahdi_bridge, .exception = dahdi_exception, .indicate = dahdi_indicate, .fixup = dahdi_fixup, .setoption = dahdi_setoption, .func_channel_read = dahdi_func_read,};static const struct ast_channel_tech zap_tech = { .type = "Zap", .description = tdesc, .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW, .requester = dahdi_request, .send_digit_begin = dahdi_digit_begin, .send_digit_end = dahdi_digit_end, .send_text = dahdi_sendtext, .call = dahdi_call, .hangup = dahdi_hangup, .answer = dahdi_answer, .read = dahdi_read, .write = dahdi_write, .bridge = dahdi_bridge, .exception = dahdi_exception, .indicate = dahdi_indicate, .fixup = dahdi_fixup, .setoption = dahdi_setoption, .func_channel_read = dahdi_func_read,};static const struct ast_channel_tech *chan_tech;#ifdef HAVE_PRI#define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)#else#define GET_CHANNEL(p) ((p)->channel)#endifstruct dahdi_pvt *round_robin[32];#ifdef HAVE_PRIstatic inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri){ int res; /* Grab the lock first */ do { res = ast_mutex_trylock(&pri->lock); if (res) { DEADLOCK_AVOIDANCE(&pvt->lock); } } while (res); /* Then break the poll */ if (pri->master != AST_PTHREADT_NULL) pthread_kill(pri->master, SIGURG); return 0;}#endif#define NUM_CADENCE_MAX 25static int num_cadence = 4;static int user_has_defined_cadences = 0;static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = { { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */ { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */ { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */ { { 1000, 500, 2500, 5000 } }, /*!< Long ring */};/*! \brief cidrings says in which pause to transmit the cid information, where the first pause * is 1, the second pause is 2 and so on. */static int cidrings[NUM_CADENCE_MAX] = { 2, /*!< Right after first long ring */ 4, /*!< Right after long part */ 3, /*!< After third chirp */ 2, /*!< Second spell */};#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \ (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok){ int res; if (p->subs[SUB_REAL].owner == ast) res = 0; else if (p->subs[SUB_CALLWAIT].owner == ast) res = 1; else if (p->subs[SUB_THREEWAY].owner == ast) res = 2; else { res = -1; if (!nullok) ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); } return res;}#ifdef HAVE_PRIstatic void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)#elsestatic void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)#endif{#ifdef HAVE_PRI if (pri) ast_mutex_unlock(&pri->lock);#endif for (;;) { if (p->subs[a].owner) { if (ast_mutex_trylock(&p->subs[a].owner->lock)) { DEADLOCK_AVOIDANCE(&p->lock); } else { ast_queue_frame(p->subs[a].owner, &ast_null_frame); ast_mutex_unlock(&p->subs[a].owner->lock); break; } } else break; }#ifdef HAVE_PRI if (pri) ast_mutex_lock(&pri->lock);#endif }#ifdef HAVE_PRIstatic void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)#elsestatic void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)#endif{ /* We must unlock the PRI to avoid the possibility of a deadlock */#ifdef HAVE_PRI if (pri) ast_mutex_unlock(&pri->lock);#endif for (;;) { if (p->owner) { if (ast_mutex_trylock(&p->owner->lock)) { DEADLOCK_AVOIDANCE(&p->lock); } else { ast_queue_frame(p->owner, f); ast_mutex_unlock(&p->owner->lock); break; } } else break; }#ifdef HAVE_PRI if (pri) ast_mutex_lock(&pri->lock);#endif }static int restore_gains(struct dahdi_pvt *p);static void swap_subs(struct dahdi_pvt *p, int a, int b){ int tchan; int tinthreeway; struct ast_channel *towner; ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); tchan = p->subs[a].chan; towner = p->subs[a].owner; tinthreeway = p->subs[a].inthreeway; p->subs[a].chan = p->subs[b].chan; p->subs[a].owner = p->subs[b].owner; p->subs[a].inthreeway = p->subs[b].inthreeway; p->subs[b].chan = tchan; p->subs[b].owner = towner; p->subs[b].inthreeway = tinthreeway; if (p->subs[a].owner) p->subs[a].owner->fds[0] = p->subs[a].dfd; if (p->subs[b].owner) p->subs[b].owner->fds[0] = p->subs[b].dfd; wakeup_sub(p, a, NULL); wakeup_sub(p, b, NULL);}static int dahdi_open(char *fn){ int fd; int isnum; int chan = 0; int bs; int x; isnum = 1; for (x = 0; x < strlen(fn); x++) { if (!isdigit(fn[x])) { isnum = 0; break; } } if (isnum) { chan = atoi(fn); if (chan < 1) { ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); return -1; }#ifdef HAVE_ZAPTEL fn = "/dev/zap/channel";#else fn = "/dev/dahdi/channel";#endif } fd = open(fn, O_RDWR | O_NONBLOCK); if (fd < 0) { ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -