00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "asterisk.h"
00049
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 166380 $")
00051
00052 #include <stdio.h>
00053 #include <string.h>
00054 #ifdef __NetBSD__
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdlib.h>
00062 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00063 #include <stdint.h>
00064 #endif
00065 #include <unistd.h>
00066 #include <sys/ioctl.h>
00067 #include <math.h>
00068 #include <ctype.h>
00069
00070 #ifdef HAVE_PRI
00071 #include <libpri.h>
00072 #endif
00073
00074 #include "asterisk/lock.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/config.h"
00077 #include "asterisk/logger.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/options.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/ulaw.h"
00083 #include "asterisk/alaw.h"
00084 #include "asterisk/callerid.h"
00085 #include "asterisk/adsi.h"
00086 #include "asterisk/cli.h"
00087 #include "asterisk/cdr.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/say.h"
00091 #include "asterisk/tdd.h"
00092 #include "asterisk/app.h"
00093 #include "asterisk/dsp.h"
00094 #include "asterisk/astdb.h"
00095 #include "asterisk/manager.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/term.h"
00098 #include "asterisk/utils.h"
00099 #include "asterisk/transcap.h"
00100 #include "asterisk/stringfields.h"
00101 #include "asterisk/abstract_jb.h"
00102 #include "asterisk/smdi.h"
00103 #include "asterisk/astobj.h"
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 #include "asterisk/dahdi_compat.h"
00107 #include "asterisk/tonezone_compat.h"
00108
00109
00110 static struct ast_jb_conf default_jbconf =
00111 {
00112 .flags = 0,
00113 .max_size = -1,
00114 .resync_threshold = -1,
00115 .impl = ""
00116 };
00117 static struct ast_jb_conf global_jbconf;
00118
00119 #ifndef DAHDI_TONEDETECT
00120
00121 #define DAHDI_EVENT_DTMFDOWN 0
00122 #define DAHDI_EVENT_DTMFUP 0
00123 #endif
00124
00125
00126 #undef SUPPORT_USERUSER
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 #define DEFAULT_CIDRINGS 1
00148
00149 #define CHANNEL_PSEUDO -12
00150
00151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00152
00153
00154 #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))
00155
00156 static const char tdesc[] = "DAHDI Telephony Driver"
00157 #ifdef HAVE_PRI
00158 " w/PRI"
00159 #endif
00160 ;
00161
00162 #define SIG_EM DAHDI_SIG_EM
00163 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00165 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00166 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00167 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00168 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00169 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00170 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00171 #define SIG_FXSLS DAHDI_SIG_FXSLS
00172 #define SIG_FXSGS DAHDI_SIG_FXSGS
00173 #define SIG_FXSKS DAHDI_SIG_FXSKS
00174 #define SIG_FXOLS DAHDI_SIG_FXOLS
00175 #define SIG_FXOGS DAHDI_SIG_FXOGS
00176 #define SIG_FXOKS DAHDI_SIG_FXOKS
00177 #define SIG_PRI DAHDI_SIG_CLEAR
00178 #define SIG_SF DAHDI_SIG_SF
00179 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00181 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00182 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00184 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00185 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00186
00187 #define NUM_SPANS 32
00188 #define NUM_DCHANS 4
00189 #define MAX_CHANNELS 672
00190
00191 #define CHAN_PSEUDO -2
00192
00193 #define DCHAN_PROVISIONED (1 << 0)
00194 #define DCHAN_NOTINALARM (1 << 1)
00195 #define DCHAN_UP (1 << 2)
00196
00197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00198
00199 static char defaultcic[64] = "";
00200 static char defaultozz[64] = "";
00201
00202 static char progzone[10] = "";
00203
00204 static int distinctiveringaftercid = 0;
00205
00206 static int numbufs = 4;
00207
00208 #ifdef HAVE_PRI
00209 static struct ast_channel inuse;
00210 #ifdef PRI_GETSET_TIMERS
00211 static int pritimers[PRI_MAX_TIMERS];
00212 #endif
00213 static int pridebugfd = -1;
00214 static char pridebugfilename[1024] = "";
00215 #endif
00216
00217
00218 static int firstdigittimeout = 16000;
00219
00220
00221 static int gendigittimeout = 8000;
00222
00223
00224 static int matchdigittimeout = 3000;
00225
00226
00227 AST_MUTEX_DEFINE_STATIC(iflock);
00228
00229
00230 static int ifcount = 0;
00231
00232 #ifdef HAVE_PRI
00233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00234 #endif
00235
00236
00237
00238 AST_MUTEX_DEFINE_STATIC(monlock);
00239
00240
00241
00242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00243 static ast_cond_t ss_thread_complete;
00244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00245 AST_MUTEX_DEFINE_STATIC(restart_lock);
00246 static int ss_thread_count = 0;
00247 static int num_restart_pending = 0;
00248
00249 static int restart_monitor(void);
00250
00251 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00252
00253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00254
00255
00256 static inline int dahdi_get_event(int fd)
00257 {
00258 int j;
00259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260 return -1;
00261 return j;
00262 }
00263
00264
00265 static inline int dahdi_wait_event(int fd)
00266 {
00267 int i, j = 0;
00268 i = DAHDI_IOMUX_SIGEVENT;
00269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270 return -1;
00271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272 return -1;
00273 return j;
00274 }
00275
00276
00277 #define READ_SIZE 160
00278
00279 #define MASK_AVAIL (1 << 0)
00280 #define MASK_INUSE (1 << 1)
00281
00282 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00283 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00284 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00285 #define MIN_MS_SINCE_FLASH ( (2000) )
00286 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00287
00288 struct dahdi_pvt;
00289
00290 static int ringt_base = DEFAULT_RINGT;
00291
00292 #ifdef HAVE_PRI
00293
00294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00295 #define PRI_CHANNEL(p) ((p) & 0xff)
00296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00298
00299 struct dahdi_pri {
00300 pthread_t master;
00301 ast_mutex_t lock;
00302 char idleext[AST_MAX_EXTENSION];
00303 char idlecontext[AST_MAX_CONTEXT];
00304 char idledial[AST_MAX_EXTENSION];
00305 int minunused;
00306 int minidle;
00307 int nodetype;
00308 int switchtype;
00309 int nsf;
00310 int dialplan;
00311 int localdialplan;
00312 char internationalprefix[10];
00313 char nationalprefix[10];
00314 char localprefix[20];
00315 char privateprefix[20];
00316 char unknownprefix[20];
00317 int dchannels[NUM_DCHANS];
00318 int trunkgroup;
00319 int mastertrunkgroup;
00320 int prilogicalspan;
00321 int numchans;
00322 int overlapdial;
00323 int facilityenable;
00324 struct pri *dchans[NUM_DCHANS];
00325 int dchanavail[NUM_DCHANS];
00326 struct pri *pri;
00327 int debug;
00328 int fds[NUM_DCHANS];
00329 int offset;
00330 int span;
00331 int resetting;
00332 int resetpos;
00333 #ifdef HAVE_PRI_INBANDDISCONNECT
00334 unsigned int inbanddisconnect:1;
00335 #endif
00336 time_t lastreset;
00337 long resetinterval;
00338 struct dahdi_pvt *pvts[MAX_CHANNELS];
00339 struct dahdi_pvt *crvs;
00340 struct dahdi_pvt *crvend;
00341 };
00342
00343
00344 static struct dahdi_pri pris[NUM_SPANS];
00345
00346 #if 0
00347 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00348 #else
00349 #define DEFAULT_PRI_DEBUG 0
00350 #endif
00351
00352 static inline void pri_rel(struct dahdi_pri *pri)
00353 {
00354 ast_mutex_unlock(&pri->lock);
00355 }
00356
00357 #else
00358
00359 struct dahdi_pri;
00360 #endif
00361
00362 #define SUB_REAL 0
00363 #define SUB_CALLWAIT 1
00364 #define SUB_THREEWAY 2
00365
00366
00367 #define POLARITY_IDLE 0
00368 #define POLARITY_REV 1
00369
00370
00371 static struct dahdi_distRings drings;
00372
00373 struct distRingData {
00374 int ring[3];
00375 };
00376 struct ringContextData {
00377 char contextData[AST_MAX_CONTEXT];
00378 };
00379 struct dahdi_distRings {
00380 struct distRingData ringnum[3];
00381 struct ringContextData ringContext[3];
00382 };
00383
00384 static char *subnames[] = {
00385 "Real",
00386 "Callwait",
00387 "Threeway"
00388 };
00389
00390 struct dahdi_subchannel {
00391 int dfd;
00392 struct ast_channel *owner;
00393 int chan;
00394 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00395 struct ast_frame f;
00396 unsigned int needringing:1;
00397 unsigned int needbusy:1;
00398 unsigned int needcongestion:1;
00399 unsigned int needcallerid:1;
00400 unsigned int needanswer:1;
00401 unsigned int needflash:1;
00402 unsigned int needhold:1;
00403 unsigned int needunhold:1;
00404 unsigned int linear:1;
00405 unsigned int inthreeway:1;
00406 struct dahdi_confinfo curconf;
00407 };
00408
00409 #define CONF_USER_REAL (1 << 0)
00410 #define CONF_USER_THIRDCALL (1 << 1)
00411
00412 #define MAX_SLAVES 4
00413
00414 static struct dahdi_pvt {
00415 ast_mutex_t lock;
00416 struct ast_channel *owner;
00417
00418
00419 struct dahdi_subchannel sub_unused;
00420 struct dahdi_subchannel subs[3];
00421 struct dahdi_confinfo saveconf;
00422
00423 struct dahdi_pvt *slaves[MAX_SLAVES];
00424 struct dahdi_pvt *master;
00425 int inconference;
00426
00427 int buf_no;
00428 int buf_policy;
00429 int sig;
00430 int radio;
00431 int outsigmod;
00432 int oprmode;
00433 struct dahdi_pvt *oprpeer;
00434 float rxgain;
00435 float txgain;
00436 int tonezone;
00437 struct dahdi_pvt *next;
00438 struct dahdi_pvt *prev;
00439
00440
00441 unsigned int adsi:1;
00442 unsigned int answeronpolarityswitch:1;
00443 unsigned int busydetect:1;
00444 unsigned int callreturn:1;
00445 unsigned int callwaiting:1;
00446 unsigned int callwaitingcallerid:1;
00447 unsigned int cancallforward:1;
00448 unsigned int canpark:1;
00449 unsigned int confirmanswer:1;
00450 unsigned int destroy:1;
00451 unsigned int didtdd:1;
00452 unsigned int dialednone:1;
00453 unsigned int dialing:1;
00454 unsigned int digital:1;
00455 unsigned int dnd:1;
00456 unsigned int echobreak:1;
00457 unsigned int echocanbridged:1;
00458 unsigned int echocanon:1;
00459 unsigned int faxhandled:1;
00460 unsigned int firstradio:1;
00461 unsigned int hanguponpolarityswitch:1;
00462 unsigned int hardwaredtmf:1;
00463 unsigned int hidecallerid:1;
00464 unsigned int hidecalleridname:1;
00465 unsigned int ignoredtmf:1;
00466 unsigned int immediate:1;
00467 unsigned int inalarm:1;
00468 unsigned int unknown_alarm:1;
00469 unsigned int mate:1;
00470 unsigned int outgoing:1;
00471 unsigned int overlapdial:1;
00472 unsigned int permcallwaiting:1;
00473 unsigned int permhidecallerid:1;
00474 unsigned int priindication_oob:1;
00475 unsigned int priexclusive:1;
00476 unsigned int pulse:1;
00477 unsigned int pulsedial:1;
00478 unsigned int restartpending:1;
00479 unsigned int restrictcid:1;
00480 unsigned int threewaycalling:1;
00481 unsigned int transfer:1;
00482 unsigned int use_callerid:1;
00483 unsigned int use_callingpres:1;
00484 unsigned int usedistinctiveringdetection:1;
00485 unsigned int dahditrcallerid:1;
00486 unsigned int transfertobusy:1;
00487 #if defined(HAVE_PRI)
00488 unsigned int alerting:1;
00489 unsigned int alreadyhungup:1;
00490 unsigned int isidlecall:1;
00491 unsigned int proceeding:1;
00492 unsigned int progress:1;
00493 unsigned int resetting:1;
00494 unsigned int setup_ack:1;
00495 #endif
00496 unsigned int use_smdi:1;
00497 struct ast_smdi_interface *smdi_iface;
00498
00499 struct dahdi_distRings drings;
00500
00501 char context[AST_MAX_CONTEXT];
00502 char defcontext[AST_MAX_CONTEXT];
00503 char exten[AST_MAX_EXTENSION];
00504 char language[MAX_LANGUAGE];
00505 char mohinterpret[MAX_MUSICCLASS];
00506 char mohsuggest[MAX_MUSICCLASS];
00507 #ifdef PRI_ANI
00508 char cid_ani[AST_MAX_EXTENSION];
00509 #endif
00510 char cid_num[AST_MAX_EXTENSION];
00511 int cid_ton;
00512 char cid_name[AST_MAX_EXTENSION];
00513 char lastcid_num[AST_MAX_EXTENSION];
00514 char lastcid_name[AST_MAX_EXTENSION];
00515 char *origcid_num;
00516 char *origcid_name;
00517 char callwait_num[AST_MAX_EXTENSION];
00518 char callwait_name[AST_MAX_EXTENSION];
00519 char rdnis[AST_MAX_EXTENSION];
00520 char dnid[AST_MAX_EXTENSION];
00521 ast_group_t group;
00522 int law;
00523 int confno;
00524 int confusers;
00525 int propconfno;
00526 ast_group_t callgroup;
00527 ast_group_t pickupgroup;
00528 int channel;
00529 int span;
00530 time_t guardtime;
00531 int cid_signalling;
00532 int cid_start;
00533 int callingpres;
00534 int callwaitingrepeat;
00535 int cidcwexpire;
00536 unsigned char *cidspill;
00537 int cidpos;
00538 int cidlen;
00539 int ringt;
00540 int ringt_base;
00541 int stripmsd;
00542 int callwaitcas;
00543 int callwaitrings;
00544 int echocancel;
00545 int echotraining;
00546 char echorest[20];
00547 int busycount;
00548 int busycompare;
00549 int busytonelength;
00550 int busyquietlength;
00551 int busyfuzziness;
00552 int silencethreshold;
00553 int callprogress;
00554 struct timeval flashtime;
00555 struct ast_dsp *dsp;
00556 int cref;
00557 struct dahdi_dialoperation dop;
00558 int whichwink;
00559 char finaldial[64];
00560 char accountcode[AST_MAX_ACCOUNT_CODE];
00561 int amaflags;
00562 struct tdd_state *tdd;
00563 char call_forward[AST_MAX_EXTENSION];
00564 char mailbox[AST_MAX_EXTENSION];
00565 char dialdest[256];
00566 int onhooktime;
00567 int msgstate;
00568 int distinctivering;
00569 int cidrings;
00570 int dtmfrelax;
00571 int fake_event;
00572 int polarityonanswerdelay;
00573 struct timeval polaritydelaytv;
00574 int sendcalleridafter;
00575 #ifdef HAVE_PRI
00576 struct dahdi_pri *pri;
00577 struct dahdi_pvt *bearer;
00578 struct dahdi_pvt *realcall;
00579 q931_call *call;
00580 int prioffset;
00581 int logicalspan;
00582 #endif
00583 int polarity;
00584 int dsp_features;
00585 char begindigit;
00586 } *iflist = NULL, *ifend = NULL;
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 struct dahdi_chan_conf {
00599 struct dahdi_pvt chan;
00600 #ifdef HAVE_PRI
00601 struct dahdi_pri pri;
00602 #endif
00603 struct dahdi_params timing;
00604
00605 char smdi_port[SMDI_MAX_FILENAME_LEN];
00606 };
00607
00608
00609 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00610
00611
00612
00613 struct dahdi_chan_conf conf = {
00614 #ifdef HAVE_PRI
00615 .pri = {
00616 .nsf = PRI_NSF_NONE,
00617 .switchtype = PRI_SWITCH_NI2,
00618 .dialplan = PRI_NATIONAL_ISDN + 1,
00619 .localdialplan = PRI_NATIONAL_ISDN + 1,
00620 .nodetype = PRI_CPE,
00621
00622 .minunused = 2,
00623 .idleext = "",
00624 .idledial = "",
00625 .internationalprefix = "",
00626 .nationalprefix = "",
00627 .localprefix = "",
00628 .privateprefix = "",
00629 .unknownprefix = "",
00630
00631 .resetinterval = 3600
00632 },
00633 #endif
00634 .chan = {
00635 .context = "default",
00636 .cid_num = "",
00637 .cid_name = "",
00638 .mohinterpret = "default",
00639 .mohsuggest = "",
00640 .transfertobusy = 1,
00641
00642 .cid_signalling = CID_SIG_BELL,
00643 .cid_start = CID_START_RING,
00644 .dahditrcallerid = 0,
00645 .use_callerid = 1,
00646 .sig = -1,
00647 .outsigmod = -1,
00648
00649 .tonezone = -1,
00650
00651 .echocancel = 1,
00652
00653 .busycount = 3,
00654 .busycompare = 0,
00655 .busytonelength = 0,
00656 .busyquietlength = 0,
00657 .busyfuzziness = 0,
00658 .silencethreshold = 0,
00659
00660 .accountcode = "",
00661
00662 .mailbox = "",
00663
00664
00665 .polarityonanswerdelay = 600,
00666
00667 .sendcalleridafter = DEFAULT_CIDRINGS,
00668
00669 .buf_policy = DAHDI_POLICY_IMMEDIATE,
00670 .buf_no = numbufs
00671 },
00672 .timing = {
00673 .prewinktime = -1,
00674 .preflashtime = -1,
00675 .winktime = -1,
00676 .flashtime = -1,
00677 .starttime = -1,
00678 .rxwinktime = -1,
00679 .rxflashtime = -1,
00680 .debouncetime = -1
00681 },
00682 .smdi_port = "/dev/ttyS0",
00683 };
00684
00685 return conf;
00686 }
00687
00688
00689 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
00690 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
00691 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00692 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00693 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
00694 static int dahdi_hangup(struct ast_channel *ast);
00695 static int dahdi_answer(struct ast_channel *ast);
00696 static struct ast_frame *dahdi_read(struct ast_channel *ast);
00697 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
00698 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
00699 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
00700 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00701 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
00702 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
00703
00704 static const struct ast_channel_tech dahdi_tech = {
00705 .type = "DAHDI",
00706 .description = tdesc,
00707 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00708 .requester = dahdi_request,
00709 .send_digit_begin = dahdi_digit_begin,
00710 .send_digit_end = dahdi_digit_end,
00711 .send_text = dahdi_sendtext,
00712 .call = dahdi_call,
00713 .hangup = dahdi_hangup,
00714 .answer = dahdi_answer,
00715 .read = dahdi_read,
00716 .write = dahdi_write,
00717 .bridge = dahdi_bridge,
00718 .exception = dahdi_exception,
00719 .indicate = dahdi_indicate,
00720 .fixup = dahdi_fixup,
00721 .setoption = dahdi_setoption,
00722 .func_channel_read = dahdi_func_read,
00723 };
00724
00725 static const struct ast_channel_tech zap_tech = {
00726 .type = "Zap",
00727 .description = tdesc,
00728 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00729 .requester = dahdi_request,
00730 .send_digit_begin = dahdi_digit_begin,
00731 .send_digit_end = dahdi_digit_end,
00732 .send_text = dahdi_sendtext,
00733 .call = dahdi_call,
00734 .hangup = dahdi_hangup,
00735 .answer = dahdi_answer,
00736 .read = dahdi_read,
00737 .write = dahdi_write,
00738 .bridge = dahdi_bridge,
00739 .exception = dahdi_exception,
00740 .indicate = dahdi_indicate,
00741 .fixup = dahdi_fixup,
00742 .setoption = dahdi_setoption,
00743 .func_channel_read = dahdi_func_read,
00744 };
00745
00746 static const struct ast_channel_tech *chan_tech;
00747
00748 #ifdef HAVE_PRI
00749 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
00750 #else
00751 #define GET_CHANNEL(p) ((p)->channel)
00752 #endif
00753
00754 struct dahdi_pvt *round_robin[32];
00755
00756 #ifdef HAVE_PRI
00757 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
00758 {
00759 int res;
00760
00761 do {
00762 res = ast_mutex_trylock(&pri->lock);
00763 if (res) {
00764 DEADLOCK_AVOIDANCE(&pvt->lock);
00765 }
00766 } while (res);
00767
00768 if (pri->master != AST_PTHREADT_NULL)
00769 pthread_kill(pri->master, SIGURG);
00770 return 0;
00771 }
00772 #endif
00773
00774 #define NUM_CADENCE_MAX 25
00775 static int num_cadence = 4;
00776 static int user_has_defined_cadences = 0;
00777
00778 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00779 { { 125, 125, 2000, 4000 } },
00780 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00781 { { 125, 125, 125, 125, 125, 4000 } },
00782 { { 1000, 500, 2500, 5000 } },
00783 };
00784
00785
00786
00787
00788
00789 static int cidrings[NUM_CADENCE_MAX] = {
00790 2,
00791 4,
00792 3,
00793 2,
00794 };
00795
00796 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00797 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00798
00799 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00800 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00801
00802 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
00803 {
00804 int res;
00805 if (p->subs[SUB_REAL].owner == ast)
00806 res = 0;
00807 else if (p->subs[SUB_CALLWAIT].owner == ast)
00808 res = 1;
00809 else if (p->subs[SUB_THREEWAY].owner == ast)
00810 res = 2;
00811 else {
00812 res = -1;
00813 if (!nullok)
00814 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00815 }
00816 return res;
00817 }
00818
00819 #ifdef HAVE_PRI
00820 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
00821 #else
00822 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
00823 #endif
00824 {
00825 #ifdef HAVE_PRI
00826 if (pri)
00827 ast_mutex_unlock(&pri->lock);
00828 #endif
00829 for (;;) {
00830 if (p->subs[a].owner) {
00831 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00832 DEADLOCK_AVOIDANCE(&p->lock);
00833 } else {
00834 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00835 ast_mutex_unlock(&p->subs[a].owner->lock);
00836 break;
00837 }
00838 } else
00839 break;
00840 }
00841 #ifdef HAVE_PRI
00842 if (pri)
00843 ast_mutex_lock(&pri->lock);
00844 #endif
00845 }
00846
00847 #ifdef HAVE_PRI
00848 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
00849 #else
00850 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
00851 #endif
00852 {
00853
00854 #ifdef HAVE_PRI
00855 if (pri)
00856 ast_mutex_unlock(&pri->lock);
00857 #endif
00858 for (;;) {
00859 if (p->owner) {
00860 if (ast_mutex_trylock(&p->owner->lock)) {
00861 DEADLOCK_AVOIDANCE(&p->lock);
00862 } else {
00863 ast_queue_frame(p->owner, f);
00864 ast_mutex_unlock(&p->owner->lock);
00865 break;
00866 }
00867 } else
00868 break;
00869 }
00870 #ifdef HAVE_PRI
00871 if (pri)
00872 ast_mutex_lock(&pri->lock);
00873 #endif
00874 }
00875
00876 static int restore_gains(struct dahdi_pvt *p);
00877
00878 static void swap_subs(struct dahdi_pvt *p, int a, int b)
00879 {
00880 int tchan;
00881 int tinthreeway;
00882 struct ast_channel *towner;
00883
00884 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00885
00886 tchan = p->subs[a].chan;
00887 towner = p->subs[a].owner;
00888 tinthreeway = p->subs[a].inthreeway;
00889
00890 p->subs[a].chan = p->subs[b].chan;
00891 p->subs[a].owner = p->subs[b].owner;
00892 p->subs[a].inthreeway = p->subs[b].inthreeway;
00893
00894 p->subs[b].chan = tchan;
00895 p->subs[b].owner = towner;
00896 p->subs[b].inthreeway = tinthreeway;
00897
00898 if (p->subs[a].owner)
00899 p->subs[a].owner->fds[0] = p->subs[a].dfd;
00900 if (p->subs[b].owner)
00901 p->subs[b].owner->fds[0] = p->subs[b].dfd;
00902 wakeup_sub(p, a, NULL);
00903 wakeup_sub(p, b, NULL);
00904 }
00905
00906 static int dahdi_open(char *fn)
00907 {
00908 int fd;
00909 int isnum;
00910 int chan = 0;
00911 int bs;
00912 int x;
00913 isnum = 1;
00914 for (x = 0; x < strlen(fn); x++) {
00915 if (!isdigit(fn[x])) {
00916 isnum = 0;
00917 break;
00918 }
00919 }
00920 if (isnum) {
00921 chan = atoi(fn);
00922 if (chan < 1) {
00923 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00924 return -1;
00925 }
00926 fn = DAHDI_FILE_CHANNEL;
00927 }
00928 fd = open(fn, O_RDWR | O_NONBLOCK);
00929 if (fd < 0) {
00930 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00931 return -1;
00932 }
00933 if (chan) {
00934 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
00935 x = errno;
00936 close(fd);
00937 errno = x;
00938 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00939 return -1;
00940 }
00941 }
00942 bs = READ_SIZE;
00943 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
00944 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
00945 x = errno;
00946 close(fd);
00947 errno = x;
00948 return -1;
00949 }
00950 return fd;
00951 }
00952
00953 static void dahdi_close(int fd)
00954 {
00955 if (fd > 0)
00956 close(fd);
00957 }
00958
00959 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
00960 {
00961 dahdi_close(chan_pvt->subs[sub_num].dfd);
00962 chan_pvt->subs[sub_num].dfd = -1;
00963 }
00964
00965 #ifdef HAVE_PRI
00966 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
00967 {
00968 dahdi_close(pri->fds[fd_num]);
00969 pri->fds[fd_num] = -1;
00970 }
00971 #endif
00972
00973 static int dahdi_setlinear(int dfd, int linear)
00974 {
00975 int res;
00976 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
00977 if (res)
00978 return res;
00979 return 0;
00980 }
00981
00982
00983 static int alloc_sub(struct dahdi_pvt *p, int x)
00984 {
00985 struct dahdi_bufferinfo bi;
00986 int res;
00987 if (p->subs[x].dfd < 0) {
00988 p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
00989 if (p->subs[x].dfd > -1) {
00990 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
00991 if (!res) {
00992 bi.txbufpolicy = p->buf_policy;
00993 bi.rxbufpolicy = p->buf_policy;
00994 bi.numbufs = p->buf_no;
00995 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
00996 if (res < 0) {
00997 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
00998 }
00999 } else
01000 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01001 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01002 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01003 dahdi_close_sub(p, x);
01004 return -1;
01005 }
01006 if (option_debug)
01007 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01008 return 0;
01009 } else
01010 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01011 return -1;
01012 }
01013 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01014 return -1;
01015 }
01016
01017 static int unalloc_sub(struct dahdi_pvt *p, int x)
01018 {
01019 if (!x) {
01020 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01021 return -1;
01022 }
01023 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01024 dahdi_close_sub(p, x);
01025 p->subs[x].linear = 0;
01026 p->subs[x].chan = 0;
01027 p->subs[x].owner = NULL;
01028 p->subs[x].inthreeway = 0;
01029 p->polarity = POLARITY_IDLE;
01030 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01031 return 0;
01032 }
01033
01034 static int digit_to_dtmfindex(char digit)
01035 {
01036 if (isdigit(digit))
01037 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01038 else if (digit >= 'A' && digit <= 'D')
01039 return DAHDI_TONE_DTMF_A + (digit - 'A');
01040 else if (digit >= 'a' && digit <= 'd')
01041 return DAHDI_TONE_DTMF_A + (digit - 'a');
01042 else if (digit == '*')
01043 return DAHDI_TONE_DTMF_s;
01044 else if (digit == '#')
01045 return DAHDI_TONE_DTMF_p;
01046 else
01047 return -1;
01048 }
01049
01050 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01051 {
01052 struct dahdi_pvt *pvt;
01053 int index;
01054 int dtmf = -1;
01055
01056 pvt = chan->tech_pvt;
01057
01058 ast_mutex_lock(&pvt->lock);
01059
01060 index = dahdi_get_index(chan, pvt, 0);
01061
01062 if ((index != SUB_REAL) || !pvt->owner)
01063 goto out;
01064
01065 #ifdef HAVE_PRI
01066 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01067 if (pvt->setup_ack) {
01068 if (!pri_grab(pvt, pvt->pri)) {
01069 pri_information(pvt->pri->pri, pvt->call, digit);
01070 pri_rel(pvt->pri);
01071 } else
01072 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01073 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01074 int res;
01075 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01076 res = strlen(pvt->dialdest);
01077 pvt->dialdest[res++] = digit;
01078 pvt->dialdest[res] = '\0';
01079 }
01080 goto out;
01081 }
01082 #endif
01083 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01084 goto out;
01085
01086 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01087 int res;
01088 struct dahdi_dialoperation zo = {
01089 .op = DAHDI_DIAL_OP_APPEND,
01090 .dialstr[0] = 'T',
01091 .dialstr[1] = digit,
01092 .dialstr[2] = 0,
01093 };
01094 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01095 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01096 else
01097 pvt->dialing = 1;
01098 } else {
01099 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01100 pvt->dialing = 1;
01101 pvt->begindigit = digit;
01102 }
01103
01104 out:
01105 ast_mutex_unlock(&pvt->lock);
01106
01107 return 0;
01108 }
01109
01110 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01111 {
01112 struct dahdi_pvt *pvt;
01113 int res = 0;
01114 int index;
01115 int x;
01116
01117 pvt = chan->tech_pvt;
01118
01119 ast_mutex_lock(&pvt->lock);
01120
01121 index = dahdi_get_index(chan, pvt, 0);
01122
01123 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01124 goto out;
01125
01126 #ifdef HAVE_PRI
01127
01128 if (pvt->sig == SIG_PRI && !pvt->begindigit)
01129 goto out;
01130 #endif
01131
01132 if (pvt->begindigit) {
01133 x = -1;
01134 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01135 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01136 pvt->dialing = 0;
01137 pvt->begindigit = 0;
01138 }
01139
01140 out:
01141 ast_mutex_unlock(&pvt->lock);
01142
01143 return res;
01144 }
01145
01146 static char *events[] = {
01147 "No event",
01148 "On hook",
01149 "Ring/Answered",
01150 "Wink/Flash",
01151 "Alarm",
01152 "No more alarm",
01153 "HDLC Abort",
01154 "HDLC Overrun",
01155 "HDLC Bad FCS",
01156 "Dial Complete",
01157 "Ringer On",
01158 "Ringer Off",
01159 "Hook Transition Complete",
01160 "Bits Changed",
01161 "Pulse Start",
01162 "Timer Expired",
01163 "Timer Ping",
01164 "Polarity Reversal",
01165 "Ring Begin",
01166 };
01167
01168 static struct {
01169 int alarm;
01170 char *name;
01171 } alarms[] = {
01172 { DAHDI_ALARM_RED, "Red Alarm" },
01173 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01174 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01175 { DAHDI_ALARM_RECOVER, "Recovering" },
01176 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01177 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01178 { DAHDI_ALARM_NONE, "None" },
01179 };
01180
01181 static char *alarm2str(int alarm)
01182 {
01183 int x;
01184 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01185 if (alarms[x].alarm & alarm)
01186 return alarms[x].name;
01187 }
01188 return alarm ? "Unknown Alarm" : "No Alarm";
01189 }
01190
01191 static char *event2str(int event)
01192 {
01193 static char buf[256];
01194 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01195 return events[event];
01196 sprintf(buf, "Event %d", event);
01197 return buf;
01198 }
01199
01200 #ifdef HAVE_PRI
01201 static char *dialplan2str(int dialplan)
01202 {
01203 if (dialplan == -1) {
01204 return("Dynamically set dialplan in ISDN");
01205 }
01206 return (pri_plan2str(dialplan));
01207 }
01208 #endif
01209
01210 static char *dahdi_sig2str(int sig)
01211 {
01212 static char buf[256];
01213 switch (sig) {
01214 case SIG_EM:
01215 return "E & M Immediate";
01216 case SIG_EMWINK:
01217 return "E & M Wink";
01218 case SIG_EM_E1:
01219 return "E & M E1";
01220 case SIG_FEATD:
01221 return "Feature Group D (DTMF)";
01222 case SIG_FEATDMF:
01223 return "Feature Group D (MF)";
01224 case SIG_FEATDMF_TA:
01225 return "Feature Groud D (MF) Tandem Access";
01226 case SIG_FEATB:
01227 return "Feature Group B (MF)";
01228 case SIG_E911:
01229 return "E911 (MF)";
01230 case SIG_FGC_CAMA:
01231 return "FGC/CAMA (Dialpulse)";
01232 case SIG_FGC_CAMAMF:
01233 return "FGC/CAMA (MF)";
01234 case SIG_FXSLS:
01235 return "FXS Loopstart";
01236 case SIG_FXSGS:
01237 return "FXS Groundstart";
01238 case SIG_FXSKS:
01239 return "FXS Kewlstart";
01240 case SIG_FXOLS:
01241 return "FXO Loopstart";
01242 case SIG_FXOGS:
01243 return "FXO Groundstart";
01244 case SIG_FXOKS:
01245 return "FXO Kewlstart";
01246 case SIG_PRI:
01247 return "ISDN PRI";
01248 case SIG_SF:
01249 return "SF (Tone) Immediate";
01250 case SIG_SFWINK:
01251 return "SF (Tone) Wink";
01252 case SIG_SF_FEATD:
01253 return "SF (Tone) with Feature Group D (DTMF)";
01254 case SIG_SF_FEATDMF:
01255 return "SF (Tone) with Feature Group D (MF)";
01256 case SIG_SF_FEATB:
01257 return "SF (Tone) with Feature Group B (MF)";
01258 case SIG_GR303FXOKS:
01259 return "GR-303 with FXOKS";
01260 case SIG_GR303FXSKS:
01261 return "GR-303 with FXSKS";
01262 case 0:
01263 return "Pseudo";
01264 default:
01265 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01266 return buf;
01267 }
01268 }
01269
01270 #define sig2str dahdi_sig2str
01271
01272 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01273 {
01274
01275
01276 struct dahdi_confinfo zi;
01277
01278 memset(&zi, 0, sizeof(zi));
01279 zi.chan = 0;
01280
01281 if (slavechannel > 0) {
01282
01283 zi.confmode = DAHDI_CONF_DIGITALMON;
01284 zi.confno = slavechannel;
01285 } else {
01286 if (!index) {
01287
01288 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01289 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01290 } else
01291 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01292 zi.confno = p->confno;
01293 }
01294 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01295 return 0;
01296 if (c->dfd < 0)
01297 return 0;
01298 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01299 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01300 return -1;
01301 }
01302 if (slavechannel < 1) {
01303 p->confno = zi.confno;
01304 }
01305 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01306 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01307 return 0;
01308 }
01309
01310 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01311 {
01312
01313 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01314 return 1;
01315
01316 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01317 return 1;
01318 return 0;
01319 }
01320
01321 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01322 {
01323 struct dahdi_confinfo zi;
01324 if (
01325 (c->dfd < 0) ||
01326
01327 !isourconf(p, c)
01328
01329 ) return 0;
01330 memset(&zi, 0, sizeof(zi));
01331 zi.chan = 0;
01332 zi.confno = 0;
01333 zi.confmode = 0;
01334 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01335 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01336 return -1;
01337 }
01338 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01339 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01340 return 0;
01341 }
01342
01343 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01344 {
01345 int x;
01346 int useslavenative;
01347 struct dahdi_pvt *slave = NULL;
01348
01349 useslavenative = 1;
01350
01351 for (x = 0; x < 3; x++) {
01352
01353
01354 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01355 useslavenative = 0;
01356 }
01357
01358
01359 if (useslavenative) {
01360 for (x = 0; x < MAX_SLAVES; x++) {
01361 if (p->slaves[x]) {
01362 if (slave) {
01363
01364
01365 slave = NULL;
01366 useslavenative = 0;
01367 break;
01368 } else {
01369
01370 slave = p->slaves[x];
01371 }
01372 }
01373 }
01374 }
01375
01376 if (!slave)
01377 useslavenative = 0;
01378 else if (slave->law != p->law) {
01379 useslavenative = 0;
01380 slave = NULL;
01381 }
01382 if (out)
01383 *out = slave;
01384 return useslavenative;
01385 }
01386
01387 static int reset_conf(struct dahdi_pvt *p)
01388 {
01389 struct dahdi_confinfo zi;
01390 memset(&zi, 0, sizeof(zi));
01391 p->confno = -1;
01392 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01393 if (p->subs[SUB_REAL].dfd > -1) {
01394 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01395 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01396 }
01397 return 0;
01398 }
01399
01400 static int update_conf(struct dahdi_pvt *p)
01401 {
01402 int needconf = 0;
01403 int x;
01404 int useslavenative;
01405 struct dahdi_pvt *slave = NULL;
01406
01407 useslavenative = isslavenative(p, &slave);
01408
01409 for (x = 0; x < 3; x++) {
01410
01411 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01412 conf_add(p, &p->subs[x], x, 0);
01413 needconf++;
01414 } else {
01415 conf_del(p, &p->subs[x], x);
01416 }
01417 }
01418
01419
01420 for (x = 0; x < MAX_SLAVES; x++) {
01421 if (p->slaves[x]) {
01422 if (useslavenative)
01423 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01424 else {
01425 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01426 needconf++;
01427 }
01428 }
01429 }
01430
01431 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01432 if (useslavenative)
01433 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01434 else {
01435 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01436 needconf++;
01437 }
01438 }
01439
01440 if (p->master) {
01441 if (isslavenative(p->master, NULL)) {
01442 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01443 } else {
01444 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01445 }
01446 }
01447 if (!needconf) {
01448
01449
01450 p->confno = -1;
01451 }
01452 if (option_debug)
01453 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01454 return 0;
01455 }
01456
01457 static void dahdi_enable_ec(struct dahdi_pvt *p)
01458 {
01459 int x;
01460 int res;
01461 if (!p)
01462 return;
01463 if (p->echocanon) {
01464 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01465 return;
01466 }
01467 if (p->digital) {
01468 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01469 return;
01470 }
01471 if (p->echocancel) {
01472 if (p->sig == SIG_PRI) {
01473 x = 1;
01474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01475 if (res)
01476 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01477 }
01478 x = p->echocancel;
01479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01480 if (res)
01481 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01482 else {
01483 p->echocanon = 1;
01484 if (option_debug)
01485 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01486 }
01487 } else if (option_debug)
01488 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01489 }
01490
01491 static void dahdi_train_ec(struct dahdi_pvt *p)
01492 {
01493 int x;
01494 int res;
01495 if (p && p->echocancel && p->echotraining) {
01496 x = p->echotraining;
01497 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01498 if (res)
01499 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01500 else {
01501 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01502 }
01503 } else
01504 ast_log(LOG_DEBUG, "No echo training requested\n");
01505 }
01506
01507 static void dahdi_disable_ec(struct dahdi_pvt *p)
01508 {
01509 int x;
01510 int res;
01511 if (p->echocancel) {
01512 x = 0;
01513 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01514 if (res)
01515 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01516 else if (option_debug)
01517 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01518 }
01519 p->echocanon = 0;
01520 }
01521
01522 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01523 {
01524 int j;
01525 int k;
01526 float linear_gain = pow(10.0, gain / 20.0);
01527
01528 switch (law) {
01529 case DAHDI_LAW_ALAW:
01530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01531 if (gain) {
01532 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01533 if (k > 32767) k = 32767;
01534 if (k < -32767) k = -32767;
01535 g->txgain[j] = AST_LIN2A(k);
01536 } else {
01537 g->txgain[j] = j;
01538 }
01539 }
01540 break;
01541 case DAHDI_LAW_MULAW:
01542 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01543 if (gain) {
01544 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01545 if (k > 32767) k = 32767;
01546 if (k < -32767) k = -32767;
01547 g->txgain[j] = AST_LIN2MU(k);
01548 } else {
01549 g->txgain[j] = j;
01550 }
01551 }
01552 break;
01553 }
01554 }
01555
01556 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01557 {
01558 int j;
01559 int k;
01560 float linear_gain = pow(10.0, gain / 20.0);
01561
01562 switch (law) {
01563 case DAHDI_LAW_ALAW:
01564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01565 if (gain) {
01566 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01567 if (k > 32767) k = 32767;
01568 if (k < -32767) k = -32767;
01569 g->rxgain[j] = AST_LIN2A(k);
01570 } else {
01571 g->rxgain[j] = j;
01572 }
01573 }
01574 break;
01575 case DAHDI_LAW_MULAW:
01576 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01577 if (gain) {
01578 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01579 if (k > 32767) k = 32767;
01580 if (k < -32767) k = -32767;
01581 g->rxgain[j] = AST_LIN2MU(k);
01582 } else {
01583 g->rxgain[j] = j;
01584 }
01585 }
01586 break;
01587 }
01588 }
01589
01590 static int set_actual_txgain(int fd, int chan, float gain, int law)
01591 {
01592 struct dahdi_gains g;
01593 int res;
01594
01595 memset(&g, 0, sizeof(g));
01596 g.chan = chan;
01597 res = ioctl(fd, DAHDI_GETGAINS, &g);
01598 if (res) {
01599 if (option_debug)
01600 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01601 return res;
01602 }
01603
01604 fill_txgain(&g, gain, law);
01605
01606 return ioctl(fd, DAHDI_SETGAINS, &g);
01607 }
01608
01609 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01610 {
01611 struct dahdi_gains g;
01612 int res;
01613
01614 memset(&g, 0, sizeof(g));
01615 g.chan = chan;
01616 res = ioctl(fd, DAHDI_GETGAINS, &g);
01617 if (res) {
01618 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01619 return res;
01620 }
01621
01622 fill_rxgain(&g, gain, law);
01623
01624 return ioctl(fd, DAHDI_SETGAINS, &g);
01625 }
01626
01627 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01628 {
01629 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01630 }
01631
01632 static int bump_gains(struct dahdi_pvt *p)
01633 {
01634 int res;
01635
01636
01637 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01638 if (res) {
01639 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01640 return -1;
01641 }
01642
01643 return 0;
01644 }
01645
01646 static int restore_gains(struct dahdi_pvt *p)
01647 {
01648 int res;
01649
01650 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01651 if (res) {
01652 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01653 return -1;
01654 }
01655
01656 return 0;
01657 }
01658
01659 static inline int dahdi_set_hook(int fd, int hs)
01660 {
01661 int x, res;
01662
01663 x = hs;
01664 res = ioctl(fd, DAHDI_HOOK, &x);
01665
01666 if (res < 0) {
01667 if (errno == EINPROGRESS)
01668 return 0;
01669 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01670
01671 }
01672
01673 return res;
01674 }
01675
01676 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01677 {
01678 int x, y, res;
01679 x = muted;
01680 if (p->sig == SIG_PRI) {
01681 y = 1;
01682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01683 if (res)
01684 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01685 }
01686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
01687 if (res < 0)
01688 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01689 return res;
01690 }
01691
01692 static int save_conference(struct dahdi_pvt *p)
01693 {
01694 struct dahdi_confinfo c;
01695 int res;
01696 if (p->saveconf.confmode) {
01697 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01698 return -1;
01699 }
01700 p->saveconf.chan = 0;
01701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
01702 if (res) {
01703 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01704 p->saveconf.confmode = 0;
01705 return -1;
01706 }
01707 c.chan = 0;
01708 c.confno = 0;
01709 c.confmode = DAHDI_CONF_NORMAL;
01710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
01711 if (res) {
01712 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01713 return -1;
01714 }
01715 if (option_debug)
01716 ast_log(LOG_DEBUG, "Disabled conferencing\n");
01717 return 0;
01718 }
01719
01720 static int restore_conference(struct dahdi_pvt *p)
01721 {
01722 int res;
01723 if (p->saveconf.confmode) {
01724 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
01725 p->saveconf.confmode = 0;
01726 if (res) {
01727 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01728 return -1;
01729 }
01730 }
01731 if (option_debug)
01732 ast_log(LOG_DEBUG, "Restored conferencing\n");
01733 return 0;
01734 }
01735
01736 static int send_callerid(struct dahdi_pvt *p);
01737
01738 static int send_cwcidspill(struct dahdi_pvt *p)
01739 {
01740 p->callwaitcas = 0;
01741 p->cidcwexpire = 0;
01742 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01743 return -1;
01744 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01745
01746 p->cidlen += READ_SIZE * 4;
01747 p->cidpos = 0;
01748 send_callerid(p);
01749 if (option_verbose > 2)
01750 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01751 return 0;
01752 }
01753
01754 static int has_voicemail(struct dahdi_pvt *p)
01755 {
01756
01757 return ast_app_has_voicemail(p->mailbox, NULL);
01758 }
01759
01760 static int send_callerid(struct dahdi_pvt *p)
01761 {
01762
01763 int res;
01764
01765 if (p->subs[SUB_REAL].linear) {
01766 p->subs[SUB_REAL].linear = 0;
01767 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
01768 }
01769 while (p->cidpos < p->cidlen) {
01770 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01771 if (res < 0) {
01772 if (errno == EAGAIN)
01773 return 0;
01774 else {
01775 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01776 return -1;
01777 }
01778 }
01779 if (!res)
01780 return 0;
01781 p->cidpos += res;
01782 }
01783 free(p->cidspill);
01784 p->cidspill = NULL;
01785 if (p->callwaitcas) {
01786
01787 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01788 } else
01789 restore_conference(p);
01790 return 0;
01791 }
01792
01793 static int dahdi_callwait(struct ast_channel *ast)
01794 {
01795 struct dahdi_pvt *p = ast->tech_pvt;
01796 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01797 if (p->cidspill) {
01798 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01799 free(p->cidspill);
01800 }
01801 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01802 return -1;
01803 save_conference(p);
01804
01805 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01806 if (!p->callwaitrings && p->callwaitingcallerid) {
01807 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01808 p->callwaitcas = 1;
01809 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01810 } else {
01811 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01812 p->callwaitcas = 0;
01813 p->cidlen = 2400 + READ_SIZE * 4;
01814 }
01815 p->cidpos = 0;
01816 send_callerid(p);
01817
01818 return 0;
01819 }
01820
01821 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
01822 {
01823 struct dahdi_pvt *p = ast->tech_pvt;
01824 int x, res, index,mysig;
01825 char *c, *n, *l;
01826 #ifdef HAVE_PRI
01827 char *s = NULL;
01828 #endif
01829 char dest[256];
01830 ast_mutex_lock(&p->lock);
01831 ast_copy_string(dest, rdest, sizeof(dest));
01832 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01833 if ((ast->_state == AST_STATE_BUSY)) {
01834 p->subs[SUB_REAL].needbusy = 1;
01835 ast_mutex_unlock(&p->lock);
01836 return 0;
01837 }
01838 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01839 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
01840 ast_mutex_unlock(&p->lock);
01841 return -1;
01842 }
01843 p->dialednone = 0;
01844 if ((p->radio || (p->oprmode < 0)))
01845 {
01846
01847 ast_setstate(ast, AST_STATE_UP);
01848 ast_mutex_unlock(&p->lock);
01849 return 0;
01850 }
01851 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
01852 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
01853 if (res)
01854 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
01855 p->outgoing = 1;
01856
01857 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01858
01859 mysig = p->sig;
01860 if (p->outsigmod > -1)
01861 mysig = p->outsigmod;
01862
01863 switch (mysig) {
01864 case SIG_FXOLS:
01865 case SIG_FXOGS:
01866 case SIG_FXOKS:
01867 if (p->owner == ast) {
01868
01869
01870
01871 p->dialing = 1;
01872 if (p->use_callerid) {
01873
01874 if (p->cidspill) {
01875 ast_log(LOG_WARNING, "cidspill already exists??\n");
01876 free(p->cidspill);
01877 }
01878 p->callwaitcas = 0;
01879 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01880 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01881 p->cidpos = 0;
01882 send_callerid(p);
01883 }
01884 }
01885
01886 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01887 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01888 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
01889 p->cidrings = cidrings[p->distinctivering - 1];
01890 } else {
01891 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01892 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
01893 p->cidrings = p->sendcalleridafter;
01894 }
01895
01896
01897 c = strchr(dest, '/');
01898 if (c)
01899 c++;
01900 if (c && (strlen(c) < p->stripmsd)) {
01901 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01902 c = NULL;
01903 }
01904 if (c) {
01905 p->dop.op = DAHDI_DIAL_OP_REPLACE;
01906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01907 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01908 } else {
01909 p->dop.dialstr[0] = '\0';
01910 }
01911 x = DAHDI_RING;
01912 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
01913 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01914 ast_mutex_unlock(&p->lock);
01915 return -1;
01916 }
01917 p->dialing = 1;
01918 } else {
01919
01920 p->callwaitrings = 0;
01921 if (ast->cid.cid_num)
01922 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01923 else
01924 p->callwait_num[0] = '\0';
01925 if (ast->cid.cid_name)
01926 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01927 else
01928 p->callwait_name[0] = '\0';
01929
01930 if (dahdi_callwait(ast)) {
01931 ast_mutex_unlock(&p->lock);
01932 return -1;
01933 }
01934
01935 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
01936 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01937
01938 }
01939 n = ast->cid.cid_name;
01940 l = ast->cid.cid_num;
01941 if (l)
01942 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01943 else
01944 p->lastcid_num[0] = '\0';
01945 if (n)
01946 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01947 else
01948 p->lastcid_name[0] = '\0';
01949 ast_setstate(ast, AST_STATE_RINGING);
01950 index = dahdi_get_index(ast, p, 0);
01951 if (index > -1) {
01952 p->subs[index].needringing = 1;
01953 }
01954 break;
01955 case SIG_FXSLS:
01956 case SIG_FXSGS:
01957 case SIG_FXSKS:
01958 case SIG_EMWINK:
01959 case SIG_EM:
01960 case SIG_EM_E1:
01961 case SIG_FEATD:
01962 case SIG_FEATDMF:
01963 case SIG_E911:
01964 case SIG_FGC_CAMA:
01965 case SIG_FGC_CAMAMF:
01966 case SIG_FEATB:
01967 case SIG_SFWINK:
01968 case SIG_SF:
01969 case SIG_SF_FEATD:
01970 case SIG_SF_FEATDMF:
01971 case SIG_FEATDMF_TA:
01972 case SIG_SF_FEATB:
01973 c = strchr(dest, '/');
01974 if (c)
01975 c++;
01976 else
01977 c = "";
01978 if (strlen(c) < p->stripmsd) {
01979 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01980 ast_mutex_unlock(&p->lock);
01981 return -1;
01982 }
01983 #ifdef HAVE_PRI
01984
01985 if (!p->pri) {
01986 #endif
01987 x = DAHDI_START;
01988 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
01989 if (res < 0) {
01990 if (errno != EINPROGRESS) {
01991 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
01992 ast_mutex_unlock(&p->lock);
01993 return -1;
01994 }
01995 }
01996 #ifdef HAVE_PRI
01997 }
01998 #endif
01999 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02000 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02001
02002 c += p->stripmsd;
02003
02004 switch (mysig) {
02005 case SIG_FEATD:
02006 l = ast->cid.cid_num;
02007 if (l)
02008 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02009 else
02010 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02011 break;
02012 case SIG_FEATDMF:
02013 l = ast->cid.cid_num;
02014 if (l)
02015 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02016 else
02017 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02018 break;
02019 case SIG_FEATDMF_TA:
02020 {
02021 const char *cic, *ozz;
02022
02023
02024 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02025 if (!ozz)
02026 ozz = defaultozz;
02027 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02028 if (!cic)
02029 cic = defaultcic;
02030 if (!ozz || !cic) {
02031 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02032 ast_mutex_unlock(&p->lock);
02033 return -1;
02034 }
02035 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02036 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02037 p->whichwink = 0;
02038 }
02039 break;
02040 case SIG_E911:
02041 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02042 break;
02043 case SIG_FGC_CAMA:
02044 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02045 break;
02046 case SIG_FGC_CAMAMF:
02047 case SIG_FEATB:
02048 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02049 break;
02050 default:
02051 if (p->pulse)
02052 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02053 else
02054 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02055 break;
02056 }
02057
02058 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02059 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02060 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02061 p->echorest[sizeof(p->echorest) - 1] = '\0';
02062 p->echobreak = 1;
02063 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02064 } else
02065 p->echobreak = 0;
02066 if (!res) {
02067 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02068 int saveerr = errno;
02069
02070 x = DAHDI_ONHOOK;
02071 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02072 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02073 ast_mutex_unlock(&p->lock);
02074 return -1;
02075 }
02076 } else
02077 ast_log(LOG_DEBUG, "Deferring dialing...\n");
02078 p->dialing = 1;
02079 if (ast_strlen_zero(c))
02080 p->dialednone = 1;
02081 ast_setstate(ast, AST_STATE_DIALING);
02082 break;
02083 case 0:
02084
02085 ast_setstate(ast, AST_STATE_UP);
02086 break;
02087 case SIG_PRI:
02088
02089 p->dialdest[0] = '\0';
02090 break;
02091 default:
02092 ast_log(LOG_DEBUG, "not yet implemented\n");
02093 ast_mutex_unlock(&p->lock);
02094 return -1;
02095 }
02096 #ifdef HAVE_PRI
02097 if (p->pri) {
02098 struct pri_sr *sr;
02099 #ifdef SUPPORT_USERUSER
02100 const char *useruser;
02101 #endif
02102 int pridialplan;
02103 int dp_strip;
02104 int prilocaldialplan;
02105 int ldp_strip;
02106 int exclusive;
02107 const char *rr_str;
02108 int redirect_reason;
02109
02110 c = strchr(dest, '/');
02111 if (c)
02112 c++;
02113 else
02114 c = dest;
02115
02116 l = NULL;
02117 n = NULL;
02118
02119 if (!p->hidecallerid) {
02120 l = ast->cid.cid_num;
02121 if (!p->hidecalleridname) {
02122 n = ast->cid.cid_name;
02123 }
02124 }
02125
02126
02127 if (strlen(c) < p->stripmsd) {
02128 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02129 ast_mutex_unlock(&p->lock);
02130 return -1;
02131 }
02132 if (mysig != SIG_FXSKS) {
02133 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02134 s = strchr(c + p->stripmsd, 'w');
02135 if (s) {
02136 if (strlen(s) > 1)
02137 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02138 else
02139 p->dop.dialstr[0] = '\0';
02140 *s = '\0';
02141 } else {
02142 p->dop.dialstr[0] = '\0';
02143 }
02144 }
02145 if (pri_grab(p, p->pri)) {
02146 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02147 ast_mutex_unlock(&p->lock);
02148 return -1;
02149 }
02150 if (!(p->call = pri_new_call(p->pri->pri))) {
02151 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02152 pri_rel(p->pri);
02153 ast_mutex_unlock(&p->lock);
02154 return -1;
02155 }
02156 if (!(sr = pri_sr_new())) {
02157 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02158 pri_destroycall(p->pri->pri, p->call);
02159 p->call = NULL;
02160 pri_rel(p->pri);
02161 ast_mutex_unlock(&p->lock);
02162 return -1;
02163 }
02164 if (p->bearer || (mysig == SIG_FXSKS)) {
02165 if (p->bearer) {
02166 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);
02167 p->bearer->call = p->call;
02168 } else
02169 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02170 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02171 }
02172 p->digital = IS_DIGITAL(ast->transfercapability);
02173
02174 if (p->priexclusive)
02175 exclusive = 1;
02176 else {
02177
02178 if (p->pri->nodetype == PRI_NETWORK)
02179 exclusive = 0;
02180 else
02181 exclusive = 1;
02182 }
02183
02184 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02185 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02186 (p->digital ? -1 :
02187 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02188 if (p->pri->facilityenable)
02189 pri_facility_enable(p->pri->pri);
02190
02191 if (option_verbose > 2)
02192 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02193 dp_strip = 0;
02194 pridialplan = p->pri->dialplan - 1;
02195 if (pridialplan == -2) {
02196 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02197 dp_strip = strlen(p->pri->internationalprefix);
02198 pridialplan = PRI_INTERNATIONAL_ISDN;
02199 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02200 dp_strip = strlen(p->pri->nationalprefix);
02201 pridialplan = PRI_NATIONAL_ISDN;
02202 } else {
02203 pridialplan = PRI_LOCAL_ISDN;
02204 }
02205 }
02206 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02207
02208 ldp_strip = 0;
02209 prilocaldialplan = p->pri->localdialplan - 1;
02210 if ((l != NULL) && (prilocaldialplan == -2)) {
02211 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02212 ldp_strip = strlen(p->pri->internationalprefix);
02213 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02214 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02215 ldp_strip = strlen(p->pri->nationalprefix);
02216 prilocaldialplan = PRI_NATIONAL_ISDN;
02217 } else {
02218 prilocaldialplan = PRI_LOCAL_ISDN;
02219 }
02220 }
02221 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02222 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02223 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02224 if (!strcasecmp(rr_str, "UNKNOWN"))
02225 redirect_reason = 0;
02226 else if (!strcasecmp(rr_str, "BUSY"))
02227 redirect_reason = 1;
02228 else if (!strcasecmp(rr_str, "NO_REPLY"))
02229 redirect_reason = 2;
02230 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02231 redirect_reason = 15;
02232 else
02233 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02234 } else
02235 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02236 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02237
02238 #ifdef SUPPORT_USERUSER
02239
02240 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02241
02242 if (useruser)
02243 pri_sr_set_useruser(sr, useruser);
02244 #endif
02245
02246 if (pri_setup(p->pri->pri, p->call, sr)) {
02247 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
02248 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02249 pri_rel(p->pri);
02250 ast_mutex_unlock(&p->lock);
02251 pri_sr_free(sr);
02252 return -1;
02253 }
02254 pri_sr_free(sr);
02255 ast_setstate(ast, AST_STATE_DIALING);
02256 pri_rel(p->pri);
02257 }
02258 #endif
02259 ast_mutex_unlock(&p->lock);
02260 return 0;
02261 }
02262
02263 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02264 {
02265 struct dahdi_pvt *p = *pvt;
02266
02267 if (p->prev)
02268 p->prev->next = p->next;
02269 if (p->next)
02270 p->next->prev = p->prev;
02271 if (p->use_smdi)
02272 ast_smdi_interface_unref(p->smdi_iface);
02273 ast_mutex_destroy(&p->lock);
02274 dahdi_close_sub(p, SUB_REAL);
02275 if (p->owner)
02276 p->owner->tech_pvt = NULL;
02277 free(p);
02278 *pvt = NULL;
02279 }
02280
02281 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02282 {
02283 int owned = 0;
02284 int i = 0;
02285
02286 if (!now) {
02287 if (cur->owner) {
02288 owned = 1;
02289 }
02290
02291 for (i = 0; i < 3; i++) {
02292 if (cur->subs[i].owner) {
02293 owned = 1;
02294 }
02295 }
02296 if (!owned) {
02297 if (prev) {
02298 prev->next = cur->next;
02299 if (prev->next)
02300 prev->next->prev = prev;
02301 else
02302 ifend = prev;
02303 } else {
02304 iflist = cur->next;
02305 if (iflist)
02306 iflist->prev = NULL;
02307 else
02308 ifend = NULL;
02309 }
02310 destroy_dahdi_pvt(&cur);
02311 }
02312 } else {
02313 if (prev) {
02314 prev->next = cur->next;
02315 if (prev->next)
02316 prev->next->prev = prev;
02317 else
02318 ifend = prev;
02319 } else {
02320 iflist = cur->next;
02321 if (iflist)
02322 iflist->prev = NULL;
02323 else
02324 ifend = NULL;
02325 }
02326 destroy_dahdi_pvt(&cur);
02327 }
02328 return 0;
02329 }
02330
02331 static void destroy_all_channels(void)
02332 {
02333 int x;
02334 struct dahdi_pvt *p, *pl;
02335
02336 while (num_restart_pending) {
02337 usleep(1);
02338 }
02339
02340 ast_mutex_lock(&iflock);
02341
02342 p = iflist;
02343 while (p) {
02344
02345 if (p->cidspill)
02346 ast_free(p->cidspill);
02347 pl = p;
02348 p = p->next;
02349 x = pl->channel;
02350
02351 if (pl)
02352 destroy_dahdi_pvt(&pl);
02353 if (option_verbose > 2)
02354 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02355 }
02356 iflist = NULL;
02357 ifcount = 0;
02358 ast_mutex_unlock(&iflock);
02359 }
02360
02361 #ifdef HAVE_PRI
02362 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02363 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02364
02365 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02366 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02367
02368 static char *dahdi_send_keypad_facility_descrip =
02369 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02370 " IE over the current channel.\n";
02371 static char *zap_send_keypad_facility_descrip =
02372 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02373 " IE over the current channel.\n";
02374
02375 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02376 {
02377
02378 struct dahdi_pvt *p;
02379 char *digits = (char *) data;
02380
02381 if (ast_strlen_zero(digits)) {
02382 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02383 return -1;
02384 }
02385
02386 p = (struct dahdi_pvt *)chan->tech_pvt;
02387
02388 if (!p) {
02389 ast_log(LOG_DEBUG, "Unable to find technology private\n");
02390 return -1;
02391 }
02392
02393 ast_mutex_lock(&p->lock);
02394
02395 if (!p->pri || !p->call) {
02396 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02397 ast_mutex_unlock(&p->lock);
02398 return -1;
02399 }
02400
02401 if (!pri_grab(p, p->pri)) {
02402 pri_keypad_facility(p->pri->pri, p->call, digits);
02403 pri_rel(p->pri);
02404 } else {
02405 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02406 ast_mutex_unlock(&p->lock);
02407 return -1;
02408 }
02409
02410 ast_mutex_unlock(&p->lock);
02411
02412 return 0;
02413 }
02414
02415 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02416 {
02417 return send_keypad_facility_exec(chan, data);
02418 }
02419
02420 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02421 {
02422 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);
02423 return send_keypad_facility_exec(chan, data);
02424 }
02425
02426 static int pri_is_up(struct dahdi_pri *pri)
02427 {
02428 int x;
02429 for (x = 0; x < NUM_DCHANS; x++) {
02430 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02431 return 1;
02432 }
02433 return 0;
02434 }
02435
02436 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02437 {
02438 bearer->owner = &inuse;
02439 bearer->realcall = crv;
02440 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02441 if (crv->subs[SUB_REAL].owner)
02442 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02443 crv->bearer = bearer;
02444 crv->call = bearer->call;
02445 crv->pri = pri;
02446 return 0;
02447 }
02448
02449 static char *pri_order(int level)
02450 {
02451 switch (level) {
02452 case 0:
02453 return "Primary";
02454 case 1:
02455 return "Secondary";
02456 case 2:
02457 return "Tertiary";
02458 case 3:
02459 return "Quaternary";
02460 default:
02461 return "<Unknown>";
02462 }
02463 }
02464
02465
02466 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02467 {
02468 int x = -1;
02469
02470 for (x = 0; x < NUM_DCHANS; x++) {
02471 if ((pri->dchans[x] == pri->pri))
02472 break;
02473 }
02474
02475 return pri->fds[x];
02476 }
02477
02478 static int pri_find_dchan(struct dahdi_pri *pri)
02479 {
02480 int oldslot = -1;
02481 struct pri *old;
02482 int newslot = -1;
02483 int x;
02484 old = pri->pri;
02485 for (x = 0; x < NUM_DCHANS; x++) {
02486 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02487 newslot = x;
02488 if (pri->dchans[x] == old) {
02489 oldslot = x;
02490 }
02491 }
02492 if (newslot < 0) {
02493 newslot = 0;
02494 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
02495 pri->dchannels[newslot]);
02496 }
02497 if (old && (oldslot != newslot))
02498 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02499 pri->dchannels[oldslot], pri->dchannels[newslot]);
02500 pri->pri = pri->dchans[newslot];
02501 return 0;
02502 }
02503 #endif
02504
02505 static int dahdi_hangup(struct ast_channel *ast)
02506 {
02507 int res;
02508 int index,x, law;
02509
02510 struct dahdi_pvt *p = ast->tech_pvt;
02511 struct dahdi_pvt *tmp = NULL;
02512 struct dahdi_pvt *prev = NULL;
02513 struct dahdi_params par;
02514
02515 if (option_debug)
02516 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02517 if (!ast->tech_pvt) {
02518 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02519 return 0;
02520 }
02521
02522 ast_mutex_lock(&p->lock);
02523
02524 index = dahdi_get_index(ast, p, 1);
02525
02526 if (p->sig == SIG_PRI) {
02527 x = 1;
02528 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02529 }
02530
02531 x = 0;
02532 dahdi_confmute(p, 0);
02533 restore_gains(p);
02534 if (p->origcid_num) {
02535 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02536 free(p->origcid_num);
02537 p->origcid_num = NULL;
02538 }
02539 if (p->origcid_name) {
02540 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02541 free(p->origcid_name);
02542 p->origcid_name = NULL;
02543 }
02544 if (p->dsp)
02545 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02546 if (p->exten)
02547 p->exten[0] = '\0';
02548
02549 if (option_debug)
02550 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02551 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02552 p->ignoredtmf = 0;
02553
02554 if (index > -1) {
02555
02556 p->subs[index].owner = NULL;
02557 p->subs[index].needanswer = 0;
02558 p->subs[index].needflash = 0;
02559 p->subs[index].needringing = 0;
02560 p->subs[index].needbusy = 0;
02561 p->subs[index].needcongestion = 0;
02562 p->subs[index].linear = 0;
02563 p->subs[index].needcallerid = 0;
02564 p->polarity = POLARITY_IDLE;
02565 dahdi_setlinear(p->subs[index].dfd, 0);
02566 if (index == SUB_REAL) {
02567 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02568 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02569 if (p->subs[SUB_CALLWAIT].inthreeway) {
02570
02571 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02572
02573 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02574 unalloc_sub(p, SUB_CALLWAIT);
02575 p->owner = NULL;
02576 } else {
02577
02578 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
02579 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02580 unalloc_sub(p, SUB_THREEWAY);
02581 if (p->subs[SUB_REAL].inthreeway) {
02582
02583
02584 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02585 p->owner = p->subs[SUB_REAL].owner;
02586 } else {
02587
02588 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02589 p->owner = NULL;
02590 }
02591 p->subs[SUB_REAL].inthreeway = 0;
02592 }
02593 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02594
02595 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02596 unalloc_sub(p, SUB_CALLWAIT);
02597 p->owner = p->subs[SUB_REAL].owner;
02598 if (p->owner->_state != AST_STATE_UP)
02599 p->subs[SUB_REAL].needanswer = 1;
02600 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02601 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02602 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02603 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02604 unalloc_sub(p, SUB_THREEWAY);
02605 if (p->subs[SUB_REAL].inthreeway) {
02606
02607
02608 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02609 p->owner = p->subs[SUB_REAL].owner;
02610 } else {
02611
02612 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02613 p->owner = NULL;
02614 }
02615 p->subs[SUB_REAL].inthreeway = 0;
02616 }
02617 } else if (index == SUB_CALLWAIT) {
02618
02619 if (p->subs[SUB_CALLWAIT].inthreeway) {
02620
02621
02622 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02623 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
02624 S_OR(p->mohsuggest, NULL),
02625 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02626 }
02627 p->subs[SUB_THREEWAY].inthreeway = 0;
02628
02629 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02630 unalloc_sub(p, SUB_THREEWAY);
02631 } else
02632 unalloc_sub(p, SUB_CALLWAIT);
02633 } else if (index == SUB_THREEWAY) {
02634 if (p->subs[SUB_CALLWAIT].inthreeway) {
02635
02636
02637 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02638 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
02639 S_OR(p->mohsuggest, NULL),
02640 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02641 }
02642 p->subs[SUB_CALLWAIT].inthreeway = 0;
02643 }
02644 p->subs[SUB_REAL].inthreeway = 0;
02645
02646
02647 unalloc_sub(p, SUB_THREEWAY);
02648 } else {
02649
02650 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02651 }
02652 }
02653
02654 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02655 p->owner = NULL;
02656 p->ringt = 0;
02657 p->distinctivering = 0;
02658 p->confirmanswer = 0;
02659 p->cidrings = 1;
02660 p->outgoing = 0;
02661 p->digital = 0;
02662 p->faxhandled = 0;
02663 p->pulsedial = 0;
02664 p->onhooktime = time(NULL);
02665 #ifdef HAVE_PRI
02666 p->proceeding = 0;
02667 p->progress = 0;
02668 p->alerting = 0;
02669 p->setup_ack = 0;
02670 #endif
02671 if (p->dsp) {
02672 ast_dsp_free(p->dsp);
02673 p->dsp = NULL;
02674 }
02675
02676 law = DAHDI_LAW_DEFAULT;
02677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02678 if (res < 0)
02679 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02680
02681 #ifdef HAVE_PRI
02682 if (p->pri) {
02683 #ifdef SUPPORT_USERUSER
02684 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02685 #endif
02686
02687
02688 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02689 if (!pri_grab(p, p->pri)) {
02690 if (p->alreadyhungup) {
02691 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
02692
02693 #ifdef SUPPORT_USERUSER
02694 pri_call_set_useruser(p->call, useruser);
02695 #endif
02696
02697 pri_hangup(p->pri->pri, p->call, -1);
02698 p->call = NULL;
02699 if (p->bearer)
02700 p->bearer->call = NULL;
02701 } else {
02702 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02703 int icause = ast->hangupcause ? ast->hangupcause : -1;
02704 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
02705
02706 #ifdef SUPPORT_USERUSER
02707 pri_call_set_useruser(p->call, useruser);
02708 #endif
02709
02710 p->alreadyhungup = 1;
02711 if (p->bearer)
02712 p->bearer->alreadyhungup = 1;
02713 if (cause) {
02714 if (atoi(cause))
02715 icause = atoi(cause);
02716 }
02717 pri_hangup(p->pri->pri, p->call, icause);
02718 }
02719 if (res < 0)
02720 ast_log(LOG_WARNING, "pri_disconnect failed\n");
02721 pri_rel(p->pri);
02722 } else {
02723 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02724 res = -1;
02725 }
02726 } else {
02727 if (p->bearer)
02728 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02729 p->call = NULL;
02730 res = 0;
02731 }
02732 }
02733 #endif
02734 if (p->sig && (p->sig != SIG_PRI))
02735 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
02736 if (res < 0) {
02737 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02738 }
02739 switch (p->sig) {
02740 case SIG_FXOGS:
02741 case SIG_FXOLS:
02742 case SIG_FXOKS:
02743 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02744 if (!res) {
02745 #if 0
02746 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02747 #endif
02748
02749 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02750 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
02751 else
02752 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02753 }
02754 break;
02755 case SIG_FXSGS:
02756 case SIG_FXSLS:
02757 case SIG_FXSKS:
02758
02759
02760 if (ast->_state != AST_STATE_RESERVED) {
02761 time(&p->guardtime);
02762 p->guardtime += 2;
02763 }
02764 break;
02765 default:
02766 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02767 }
02768 if (p->cidspill)
02769 free(p->cidspill);
02770 if (p->sig)
02771 dahdi_disable_ec(p);
02772 x = 0;
02773 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02774 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02775 p->didtdd = 0;
02776 p->cidspill = NULL;
02777 p->callwaitcas = 0;
02778 p->callwaiting = p->permcallwaiting;
02779 p->hidecallerid = p->permhidecallerid;
02780 p->dialing = 0;
02781 p->rdnis[0] = '\0';
02782 update_conf(p);
02783 reset_conf(p);
02784
02785 if (p->sig == SIG_PRI) {
02786 x = 0;
02787 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02788 }
02789 #ifdef HAVE_PRI
02790 if (p->bearer) {
02791 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02792
02793
02794 update_conf(p->bearer);
02795 reset_conf(p->bearer);
02796 p->bearer->owner = NULL;
02797 p->bearer->realcall = NULL;
02798 p->bearer = NULL;
02799 p->subs[SUB_REAL].dfd = -1;
02800 p->pri = NULL;
02801 }
02802 #endif
02803 if (num_restart_pending == 0)
02804 restart_monitor();
02805 }
02806
02807 p->callwaitingrepeat = 0;
02808 p->cidcwexpire = 0;
02809 p->oprmode = 0;
02810 ast->tech_pvt = NULL;
02811 ast_mutex_unlock(&p->lock);
02812 ast_module_unref(ast_module_info->self);
02813 if (option_verbose > 2)
02814 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02815
02816 ast_mutex_lock(&iflock);
02817
02818 if (p->restartpending) {
02819 num_restart_pending--;
02820 }
02821
02822 tmp = iflist;
02823 prev = NULL;
02824 if (p->destroy) {
02825 while (tmp) {
02826 if (tmp == p) {
02827 destroy_channel(prev, tmp, 0);
02828 break;
02829 } else {
02830 prev = tmp;
02831 tmp = tmp->next;
02832 }
02833 }
02834 }
02835 ast_mutex_unlock(&iflock);
02836 return 0;
02837 }
02838
02839 static int dahdi_answer(struct ast_channel *ast)
02840 {
02841 struct dahdi_pvt *p = ast->tech_pvt;
02842 int res = 0;
02843 int index;
02844 int oldstate = ast->_state;
02845 ast_setstate(ast, AST_STATE_UP);
02846 ast_mutex_lock(&p->lock);
02847 index = dahdi_get_index(ast, p, 0);
02848 if (index < 0)
02849 index = SUB_REAL;
02850
02851 if ((p->radio || (p->oprmode < 0))) {
02852 ast_mutex_unlock(&p->lock);
02853 return 0;
02854 }
02855 switch (p->sig) {
02856 case SIG_FXSLS:
02857 case SIG_FXSGS:
02858 case SIG_FXSKS:
02859 p->ringt = 0;
02860
02861 case SIG_EM:
02862 case SIG_EM_E1:
02863 case SIG_EMWINK:
02864 case SIG_FEATD:
02865 case SIG_FEATDMF:
02866 case SIG_FEATDMF_TA:
02867 case SIG_E911:
02868 case SIG_FGC_CAMA:
02869 case SIG_FGC_CAMAMF:
02870 case SIG_FEATB:
02871 case SIG_SF:
02872 case SIG_SFWINK:
02873 case SIG_SF_FEATD:
02874 case SIG_SF_FEATDMF:
02875 case SIG_SF_FEATB:
02876 case SIG_FXOLS:
02877 case SIG_FXOGS:
02878 case SIG_FXOKS:
02879
02880 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02881 if (p->hanguponpolarityswitch) {
02882 gettimeofday(&p->polaritydelaytv, NULL);
02883 }
02884 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02885 tone_zone_play_tone(p->subs[index].dfd, -1);
02886 p->dialing = 0;
02887 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02888 if (oldstate == AST_STATE_RINGING) {
02889 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02890 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
02891 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02892 p->owner = p->subs[SUB_REAL].owner;
02893 }
02894 }
02895 if (p->sig & __DAHDI_SIG_FXS) {
02896 dahdi_enable_ec(p);
02897 dahdi_train_ec(p);
02898 }
02899 break;
02900 #ifdef HAVE_PRI
02901 case SIG_PRI:
02902
02903 if (!pri_grab(p, p->pri)) {
02904 p->proceeding = 1;
02905 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02906 pri_rel(p->pri);
02907 } else {
02908 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02909 res = -1;
02910 }
02911 break;
02912 #endif
02913 case 0:
02914 ast_mutex_unlock(&p->lock);
02915 return 0;
02916 default:
02917 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02918 res = -1;
02919 }
02920 ast_mutex_unlock(&p->lock);
02921 return res;
02922 }
02923
02924 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
02925 {
02926 char *cp;
02927 signed char *scp;
02928 int x;
02929 int index;
02930 struct dahdi_pvt *p = chan->tech_pvt, *pp;
02931 struct oprmode *oprmode;
02932
02933
02934
02935 if (!data || (datalen < 1)) {
02936 errno = EINVAL;
02937 return -1;
02938 }
02939
02940 switch (option) {
02941 case AST_OPTION_TXGAIN:
02942 scp = (signed char *) data;
02943 index = dahdi_get_index(chan, p, 0);
02944 if (index < 0) {
02945 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02946 return -1;
02947 }
02948 if (option_debug)
02949 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02950 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
02951 case AST_OPTION_RXGAIN:
02952 scp = (signed char *) data;
02953 index = dahdi_get_index(chan, p, 0);
02954 if (index < 0) {
02955 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02956 return -1;
02957 }
02958 if (option_debug)
02959 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02960 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
02961 case AST_OPTION_TONE_VERIFY:
02962 if (!p->dsp)
02963 break;
02964 cp = (char *) data;
02965 switch (*cp) {
02966 case 1:
02967 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02968 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
02969 break;
02970 case 2:
02971 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02972 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
02973 break;
02974 default:
02975 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02976 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02977 break;
02978 }
02979 break;
02980 case AST_OPTION_TDD:
02981
02982 cp = (char *) data;
02983 p->mate = 0;
02984 if (!*cp) {
02985 if (option_debug)
02986 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02987 if (p->tdd)
02988 tdd_free(p->tdd);
02989 p->tdd = 0;
02990 break;
02991 }
02992 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
02993 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
02994 dahdi_disable_ec(p);
02995
02996 if (!p->didtdd) {
02997 unsigned char mybuf[41000], *buf;
02998 int size, res, fd, len;
02999 struct pollfd fds[1];
03000
03001 buf = mybuf;
03002 memset(buf, 0x7f, sizeof(mybuf));
03003 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03004 len = 40000;
03005 index = dahdi_get_index(chan, p, 0);
03006 if (index < 0) {
03007 ast_log(LOG_WARNING, "No index in TDD?\n");
03008 return -1;
03009 }
03010 fd = p->subs[index].dfd;
03011 while (len) {
03012 if (ast_check_hangup(chan))
03013 return -1;
03014 size = len;
03015 if (size > READ_SIZE)
03016 size = READ_SIZE;
03017 fds[0].fd = fd;
03018 fds[0].events = POLLPRI | POLLOUT;
03019 fds[0].revents = 0;
03020 res = poll(fds, 1, -1);
03021 if (!res) {
03022 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03023 continue;
03024 }
03025
03026 if (fds[0].revents & POLLPRI)
03027 return -1;
03028 if (!(fds[0].revents & POLLOUT)) {
03029 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03030 continue;
03031 }
03032 res = write(fd, buf, size);
03033 if (res != size) {
03034 if (res == -1) return -1;
03035 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03036 break;
03037 }
03038 len -= size;
03039 buf += size;
03040 }
03041 p->didtdd = 1;
03042 }
03043 if (*cp == 2) {
03044 if (p->tdd)
03045 tdd_free(p->tdd);
03046 p->tdd = 0;
03047 p->mate = 1;
03048 break;
03049 }
03050 if (!p->tdd) {
03051 p->tdd = tdd_new();
03052 }
03053 break;
03054 case AST_OPTION_RELAXDTMF:
03055 if (!p->dsp)
03056 break;
03057 cp = (char *) data;
03058 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03059 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03060 p->dtmfrelax = 0;
03061 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03062 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03063 break;
03064 case AST_OPTION_AUDIO_MODE:
03065 cp = (char *) data;
03066 if (!*cp) {
03067 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03068 x = 0;
03069 dahdi_disable_ec(p);
03070 } else {
03071 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03072 x = 1;
03073 }
03074 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03075 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03076 break;
03077 case AST_OPTION_OPRMODE:
03078 oprmode = (struct oprmode *) data;
03079 pp = oprmode->peer->tech_pvt;
03080 p->oprmode = pp->oprmode = 0;
03081
03082 p->oprpeer = pp;
03083 pp->oprpeer = p;
03084
03085 if (oprmode->mode)
03086 {
03087 pp->oprmode = oprmode->mode;
03088 p->oprmode = -oprmode->mode;
03089 }
03090 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03091 oprmode->mode, chan->name,oprmode->peer->name);;
03092 break;
03093 case AST_OPTION_ECHOCAN:
03094 cp = (char *) data;
03095 if (*cp) {
03096 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03097 dahdi_enable_ec(p);
03098 } else {
03099 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03100 dahdi_disable_ec(p);
03101 }
03102 break;
03103 }
03104 errno = 0;
03105
03106 return 0;
03107 }
03108
03109 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03110 {
03111 struct dahdi_pvt *p = chan->tech_pvt;
03112
03113 if (!strcasecmp(data, "rxgain")) {
03114 ast_mutex_lock(&p->lock);
03115 snprintf(buf, len, "%f", p->rxgain);
03116 ast_mutex_unlock(&p->lock);
03117 } else if (!strcasecmp(data, "txgain")) {
03118 ast_mutex_lock(&p->lock);
03119 snprintf(buf, len, "%f", p->txgain);
03120 ast_mutex_unlock(&p->lock);
03121 } else {
03122 ast_copy_string(buf, "", len);
03123 }
03124 return 0;
03125 }
03126
03127
03128 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03129 {
03130
03131 int x;
03132 int hasslaves;
03133 if (!master)
03134 return;
03135 if (needlock) {
03136 ast_mutex_lock(&master->lock);
03137 if (slave) {
03138 while (ast_mutex_trylock(&slave->lock)) {
03139 DEADLOCK_AVOIDANCE(&master->lock);
03140 }
03141 }
03142 }
03143 hasslaves = 0;
03144 for (x = 0; x < MAX_SLAVES; x++) {
03145 if (master->slaves[x]) {
03146 if (!slave || (master->slaves[x] == slave)) {
03147
03148 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03149 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03150 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03151 master->slaves[x]->master = NULL;
03152 master->slaves[x] = NULL;
03153 } else
03154 hasslaves = 1;
03155 }
03156 if (!hasslaves)
03157 master->inconference = 0;
03158 }
03159 if (!slave) {
03160 if (master->master) {
03161
03162 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03163 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03164 hasslaves = 0;
03165 for (x = 0; x < MAX_SLAVES; x++) {
03166 if (master->master->slaves[x] == master)
03167 master->master->slaves[x] = NULL;
03168 else if (master->master->slaves[x])
03169 hasslaves = 1;
03170 }
03171 if (!hasslaves)
03172 master->master->inconference = 0;
03173 }
03174 master->master = NULL;
03175 }
03176 update_conf(master);
03177 if (needlock) {
03178 if (slave)
03179 ast_mutex_unlock(&slave->lock);
03180 ast_mutex_unlock(&master->lock);
03181 }
03182 }
03183
03184 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03185 int x;
03186 if (!slave || !master) {
03187 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03188 return;
03189 }
03190 for (x = 0; x < MAX_SLAVES; x++) {
03191 if (!master->slaves[x]) {
03192 master->slaves[x] = slave;
03193 break;
03194 }
03195 }
03196 if (x >= MAX_SLAVES) {
03197 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03198 master->slaves[MAX_SLAVES - 1] = slave;
03199 }
03200 if (slave->master)
03201 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03202 slave->master = master;
03203
03204 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03205 }
03206
03207 static void disable_dtmf_detect(struct dahdi_pvt *p)
03208 {
03209 #ifdef DAHDI_TONEDETECT
03210 int val;
03211 #endif
03212
03213 p->ignoredtmf = 1;
03214
03215 #ifdef DAHDI_TONEDETECT
03216 val = 0;
03217 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03218 #endif
03219 if (!p->hardwaredtmf && p->dsp) {
03220 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03221 ast_dsp_set_features(p->dsp, p->dsp_features);
03222 }
03223 }
03224
03225 static void enable_dtmf_detect(struct dahdi_pvt *p)
03226 {
03227 #ifdef DAHDI_TONEDETECT
03228 int val;
03229 #endif
03230
03231 if (p->channel == CHAN_PSEUDO)
03232 return;
03233
03234 p->ignoredtmf = 0;
03235
03236 #ifdef DAHDI_TONEDETECT
03237 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03238 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03239 #endif
03240 if (!p->hardwaredtmf && p->dsp) {
03241 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03242 ast_dsp_set_features(p->dsp, p->dsp_features);
03243 }
03244 }
03245
03246 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
03247 {
03248 struct ast_channel *who;
03249 struct dahdi_pvt *p0, *p1, *op0, *op1;
03250 struct dahdi_pvt *master = NULL, *slave = NULL;
03251 struct ast_frame *f;
03252 int inconf = 0;
03253 int nothingok = 1;
03254 int ofd0, ofd1;
03255 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03256 int os0 = -1, os1 = -1;
03257 int priority = 0;
03258 struct ast_channel *oc0, *oc1;
03259 enum ast_bridge_result res;
03260
03261 #ifdef PRI_2BCT
03262 int triedtopribridge = 0;
03263 q931_call *q931c0 = NULL, *q931c1 = NULL;
03264 #endif
03265
03266
03267
03268
03269
03270
03271 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03272 return AST_BRIDGE_FAILED_NOWARN;
03273
03274 ast_mutex_lock(&c0->lock);
03275 while (ast_mutex_trylock(&c1->lock)) {
03276 DEADLOCK_AVOIDANCE(&c0->lock);
03277 }
03278
03279 p0 = c0->tech_pvt;
03280 p1 = c1->tech_pvt;
03281
03282 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03283 ast_mutex_unlock(&c0->lock);
03284 ast_mutex_unlock(&c1->lock);
03285 return AST_BRIDGE_FAILED_NOWARN;
03286 }
03287
03288 oi0 = dahdi_get_index(c0, p0, 0);
03289 oi1 = dahdi_get_index(c1, p1, 0);
03290 if ((oi0 < 0) || (oi1 < 0)) {
03291 ast_mutex_unlock(&c0->lock);
03292 ast_mutex_unlock(&c1->lock);
03293 return AST_BRIDGE_FAILED;
03294 }
03295
03296 op0 = p0 = c0->tech_pvt;
03297 op1 = p1 = c1->tech_pvt;
03298 ofd0 = c0->fds[0];
03299 ofd1 = c1->fds[0];
03300 oc0 = p0->owner;
03301 oc1 = p1->owner;
03302
03303 if (ast_mutex_trylock(&p0->lock)) {
03304
03305 ast_mutex_unlock(&c0->lock);
03306 ast_mutex_unlock(&c1->lock);
03307 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03308 return AST_BRIDGE_RETRY;
03309 }
03310 if (ast_mutex_trylock(&p1->lock)) {
03311
03312 ast_mutex_unlock(&p0->lock);
03313 ast_mutex_unlock(&c0->lock);
03314 ast_mutex_unlock(&c1->lock);
03315 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03316 return AST_BRIDGE_RETRY;
03317 }
03318
03319 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03320 if (p0->owner && p1->owner) {
03321
03322 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03323 master = p0;
03324 slave = p1;
03325 inconf = 1;
03326 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03327 master = p1;
03328 slave = p0;
03329 inconf = 1;
03330 } else {
03331 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
03332 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03333 p0->channel,
03334 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03335 p0->subs[SUB_REAL].inthreeway, p0->channel,
03336 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03337 p1->subs[SUB_REAL].inthreeway);
03338 }
03339 nothingok = 0;
03340 }
03341 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03342 if (p1->subs[SUB_THREEWAY].inthreeway) {
03343 master = p1;
03344 slave = p0;
03345 nothingok = 0;
03346 }
03347 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03348 if (p0->subs[SUB_THREEWAY].inthreeway) {
03349 master = p0;
03350 slave = p1;
03351 nothingok = 0;
03352 }
03353 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03354
03355
03356 if (p1->subs[SUB_CALLWAIT].inthreeway) {
03357 master = p1;
03358 slave = p0;
03359 nothingok = 0;
03360 }
03361 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03362
03363 if (p0->subs[SUB_CALLWAIT].inthreeway) {
03364 master = p0;
03365 slave = p1;
03366 nothingok = 0;
03367 }
03368 }
03369 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03370 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03371 if (master && slave) {
03372
03373
03374
03375 if ((oi1 == SUB_THREEWAY) &&
03376 p1->subs[SUB_THREEWAY].inthreeway &&
03377 p1->subs[SUB_REAL].owner &&
03378 p1->subs[SUB_REAL].inthreeway &&
03379 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03380 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03381 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03382 os1 = p1->subs[SUB_REAL].owner->_state;
03383 } else {
03384 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03385 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03386 }
03387 if ((oi0 == SUB_THREEWAY) &&
03388 p0->subs[SUB_THREEWAY].inthreeway &&
03389 p0->subs[SUB_REAL].owner &&
03390 p0->subs[SUB_REAL].inthreeway &&
03391 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03392 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03393 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03394 os0 = p0->subs[SUB_REAL].owner->_state;
03395 } else {
03396 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03397 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03398 }
03399 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03400 if (!p0->echocanbridged || !p1->echocanbridged) {
03401
03402 dahdi_disable_ec(p0);
03403 dahdi_disable_ec(p1);
03404 }
03405 }
03406 dahdi_link(slave, master);
03407 master->inconference = inconf;
03408 } else if (!nothingok)
03409 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03410
03411 update_conf(p0);
03412 update_conf(p1);
03413 t0 = p0->subs[SUB_REAL].inthreeway;
03414 t1 = p1->subs[SUB_REAL].inthreeway;
03415
03416 ast_mutex_unlock(&p0->lock);
03417 ast_mutex_unlock(&p1->lock);
03418
03419 ast_mutex_unlock(&c0->lock);
03420 ast_mutex_unlock(&c1->lock);
03421
03422
03423 if ((!master || !slave) && !nothingok) {
03424 dahdi_enable_ec(p0);
03425 dahdi_enable_ec(p1);
03426 return AST_BRIDGE_FAILED;
03427 }
03428
03429 if (option_verbose > 2)
03430 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03431
03432 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03433 disable_dtmf_detect(op0);
03434
03435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03436 disable_dtmf_detect(op1);
03437
03438 for (;;) {
03439 struct ast_channel *c0_priority[2] = {c0, c1};
03440 struct ast_channel *c1_priority[2] = {c1, c0};
03441
03442
03443
03444 ast_mutex_lock(&c0->lock);
03445 while (ast_mutex_trylock(&c1->lock)) {
03446 DEADLOCK_AVOIDANCE(&c0->lock);
03447 }
03448
03449 p0 = c0->tech_pvt;
03450 p1 = c1->tech_pvt;
03451
03452 if (op0 == p0)
03453 i0 = dahdi_get_index(c0, p0, 1);
03454 if (op1 == p1)
03455 i1 = dahdi_get_index(c1, p1, 1);
03456 ast_mutex_unlock(&c0->lock);
03457 ast_mutex_unlock(&c1->lock);
03458
03459 if (!timeoutms ||
03460 (op0 != p0) ||
03461 (op1 != p1) ||
03462 (ofd0 != c0->fds[0]) ||
03463 (ofd1 != c1->fds[0]) ||
03464 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
03465 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
03466 (oc0 != p0->owner) ||
03467 (oc1 != p1->owner) ||
03468 (t0 != p0->subs[SUB_REAL].inthreeway) ||
03469 (t1 != p1->subs[SUB_REAL].inthreeway) ||
03470 (oi0 != i0) ||
03471 (oi1 != i1)) {
03472 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03473 op0->channel, oi0, op1->channel, oi1);
03474 res = AST_BRIDGE_RETRY;
03475 goto return_from_bridge;
03476 }
03477
03478 #ifdef PRI_2BCT
03479 q931c0 = p0->call;
03480 q931c1 = p1->call;
03481 if (p0->transfer && p1->transfer
03482 && q931c0 && q931c1
03483 && !triedtopribridge) {
03484 pri_channel_bridge(q931c0, q931c1);
03485 triedtopribridge = 1;
03486 }
03487 #endif
03488
03489 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03490 if (!who) {
03491 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03492 continue;
03493 }
03494 f = ast_read(who);
03495 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03496 *fo = f;
03497 *rc = who;
03498 res = AST_BRIDGE_COMPLETE;
03499 goto return_from_bridge;
03500 }
03501 if (f->frametype == AST_FRAME_DTMF) {
03502 if ((who == c0) && p0->pulsedial) {
03503 ast_write(c1, f);
03504 } else if ((who == c1) && p1->pulsedial) {
03505 ast_write(c0, f);
03506 } else {
03507 *fo = f;
03508 *rc = who;
03509 res = AST_BRIDGE_COMPLETE;
03510 goto return_from_bridge;
03511 }
03512 }
03513 ast_frfree(f);
03514
03515
03516 priority = !priority;
03517 }
03518
03519 return_from_bridge:
03520 if (op0 == p0)
03521 dahdi_enable_ec(p0);
03522
03523 if (op1 == p1)
03524 dahdi_enable_ec(p1);
03525
03526 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03527 enable_dtmf_detect(op0);
03528
03529 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03530 enable_dtmf_detect(op1);
03531
03532 dahdi_unlink(slave, master, 1);
03533
03534 return res;
03535 }
03536
03537 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03538 {
03539 struct dahdi_pvt *p = newchan->tech_pvt;
03540 int x;
03541 ast_mutex_lock(&p->lock);
03542 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03543 if (p->owner == oldchan) {
03544 p->owner = newchan;
03545 }
03546 for (x = 0; x < 3; x++)
03547 if (p->subs[x].owner == oldchan) {
03548 if (!x)
03549 dahdi_unlink(NULL, p, 0);
03550 p->subs[x].owner = newchan;
03551 }
03552 if (newchan->_state == AST_STATE_RINGING)
03553 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03554 update_conf(p);
03555 ast_mutex_unlock(&p->lock);
03556 return 0;
03557 }
03558
03559 static int dahdi_ring_phone(struct dahdi_pvt *p)
03560 {
03561 int x;
03562 int res;
03563
03564 x = 0;
03565 x = DAHDI_ONHOOK;
03566 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03567 do {
03568 x = DAHDI_RING;
03569 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03570 if (res) {
03571 switch (errno) {
03572 case EBUSY:
03573 case EINTR:
03574
03575 usleep(10000);
03576 continue;
03577 case EINPROGRESS:
03578 res = 0;
03579 break;
03580 default:
03581 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03582 res = 0;
03583 }
03584 }
03585 } while (res);
03586 return res;
03587 }
03588
03589 static void *ss_thread(void *data);
03590
03591 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03592
03593 static int attempt_transfer(struct dahdi_pvt *p)
03594 {
03595
03596
03597
03598 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03599
03600
03601 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03602 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03603 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03604 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03605 }
03606 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03607 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03608 }
03609 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03610 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03611 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03612 return -1;
03613 }
03614
03615 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03616 unalloc_sub(p, SUB_THREEWAY);
03617 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03618 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03619 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03620 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03621 }
03622 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03623 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03624 }
03625 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03626 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03627 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03628 return -1;
03629 }
03630
03631 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03632 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03633 unalloc_sub(p, SUB_THREEWAY);
03634
03635 return 1;
03636 } else {
03637 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03638 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03639 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03640 return -1;
03641 }
03642 return 0;
03643 }
03644
03645 static int check_for_conference(struct dahdi_pvt *p)
03646 {
03647 struct dahdi_confinfo ci;
03648
03649 if (p->master || (p->confno > -1))
03650 return 0;
03651 memset(&ci, 0, sizeof(ci));
03652 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03653 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03654 return 0;
03655 }
03656
03657
03658
03659 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03660 if (option_verbose > 2)
03661 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03662 return 1;
03663 }
03664 return 0;
03665 }
03666
03667 static int get_alarms(struct dahdi_pvt *p)
03668 {
03669 int res;
03670 struct dahdi_spaninfo zi;
03671 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03672
03673
03674
03675
03676
03677 struct dahdi_params params;
03678 #endif
03679
03680 memset(&zi, 0, sizeof(zi));
03681 zi.spanno = p->span;
03682
03683
03684 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03685 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03686 return 0;
03687 }
03688 if (zi.alarms != DAHDI_ALARM_NONE)
03689 return zi.alarms;
03690 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03691
03692 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
03693 return params.chan_alarms;
03694
03695 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03696 #endif
03697 return DAHDI_ALARM_NONE;
03698 }
03699
03700 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
03701 {
03702 struct dahdi_pvt *p = ast->tech_pvt;
03703 struct ast_frame *f = *dest;
03704
03705 if (option_debug)
03706 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03707
03708 if (p->confirmanswer) {
03709 if (option_debug)
03710 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03711
03712
03713 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03714 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03715 *dest = &p->subs[index].f;
03716
03717 p->confirmanswer = 0;
03718 } else if (p->callwaitcas) {
03719 if ((f->subclass == 'A') || (f->subclass == 'D')) {
03720 if (option_debug)
03721 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03722 if (p->cidspill)
03723 free(p->cidspill);
03724 send_cwcidspill(p);
03725 }
03726 if ((f->subclass != 'm') && (f->subclass != 'u'))
03727 p->callwaitcas = 0;
03728 p->subs[index].f.frametype = AST_FRAME_NULL;
03729 p->subs[index].f.subclass = 0;
03730 *dest = &p->subs[index].f;
03731 } else if (f->subclass == 'f') {
03732
03733 if ((p->callprogress & 0x6) && !p->faxhandled) {
03734 p->faxhandled++;
03735 if (strcmp(ast->exten, "fax")) {
03736 const char *target_context = S_OR(ast->macrocontext, ast->context);
03737
03738
03739
03740
03741
03742 ast_mutex_unlock(&p->lock);
03743 ast_channel_unlock(ast);
03744 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03745 ast_channel_lock(ast);
03746 ast_mutex_lock(&p->lock);
03747 if (option_verbose > 2)
03748 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03749
03750 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03751 if (ast_async_goto(ast, target_context, "fax", 1))
03752 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03753 } else {
03754 ast_channel_lock(ast);
03755 ast_mutex_lock(&p->lock);
03756 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03757 }
03758 } else if (option_debug)
03759 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03760 } else if (option_debug)
03761 ast_log(LOG_DEBUG, "Fax already handled\n");
03762 dahdi_confmute(p, 0);
03763 p->subs[index].f.frametype = AST_FRAME_NULL;
03764 p->subs[index].f.subclass = 0;
03765 *dest = &p->subs[index].f;
03766 } else if (f->subclass == 'm') {
03767
03768 dahdi_confmute(p, 1);
03769 p->subs[index].f.frametype = AST_FRAME_NULL;
03770 p->subs[index].f.subclass = 0;
03771 *dest = &p->subs[index].f;
03772 } else if (f->subclass == 'u') {
03773
03774 dahdi_confmute(p, 0);
03775 p->subs[index].f.frametype = AST_FRAME_NULL;
03776 p->subs[index].f.subclass = 0;
03777 *dest = &p->subs[index].f;
03778 } else
03779 dahdi_confmute(p, 0);
03780 }
03781
03782 static void handle_alarms(struct dahdi_pvt *p, int alarms)
03783 {
03784 const char *alarm_str = alarm2str(alarms);
03785
03786
03787
03788 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
03789 p->unknown_alarm = 1;
03790 return;
03791 } else {
03792 p->unknown_alarm = 0;
03793 }
03794
03795 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
03796 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03797 "Alarm: %s\r\n"
03798 "Channel: %d\r\n",
03799 alarm_str, p->channel);
03800 }
03801
03802 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
03803 {
03804 int res, x;
03805 int index, mysig;
03806 char *c;
03807 struct dahdi_pvt *p = ast->tech_pvt;
03808 pthread_t threadid;
03809 pthread_attr_t attr;
03810 struct ast_channel *chan;
03811 struct ast_frame *f;
03812
03813 index = dahdi_get_index(ast, p, 0);
03814 mysig = p->sig;
03815 if (p->outsigmod > -1)
03816 mysig = p->outsigmod;
03817 p->subs[index].f.frametype = AST_FRAME_NULL;
03818 p->subs[index].f.subclass = 0;
03819 p->subs[index].f.datalen = 0;
03820 p->subs[index].f.samples = 0;
03821 p->subs[index].f.mallocd = 0;
03822 p->subs[index].f.offset = 0;
03823 p->subs[index].f.src = "dahdi_handle_event";
03824 p->subs[index].f.data = NULL;
03825 f = &p->subs[index].f;
03826
03827 if (index < 0)
03828 return &p->subs[index].f;
03829 if (p->fake_event) {
03830 res = p->fake_event;
03831 p->fake_event = 0;
03832 } else
03833 res = dahdi_get_event(p->subs[index].dfd);
03834
03835 if (option_debug)
03836 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03837
03838 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
03839 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
03840
03841 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03842 #ifdef HAVE_PRI
03843 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03844
03845 } else {
03846 #endif
03847 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03848 p->subs[index].f.subclass = res & 0xff;
03849 #ifdef HAVE_PRI
03850 }
03851 #endif
03852 dahdi_handle_dtmfup(ast, index, &f);
03853 return f;
03854 }
03855
03856 if (res & DAHDI_EVENT_DTMFDOWN) {
03857 if (option_debug)
03858 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03859
03860 dahdi_confmute(p, 1);
03861 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03862 p->subs[index].f.subclass = res & 0xff;
03863 return &p->subs[index].f;
03864 }
03865
03866 switch (res) {
03867 #ifdef DAHDI_EVENT_EC_DISABLED
03868 case DAHDI_EVENT_EC_DISABLED:
03869 if (option_verbose > 2)
03870 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03871 p->echocanon = 0;
03872 break;
03873 #endif
03874 case DAHDI_EVENT_BITSCHANGED:
03875 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03876 case DAHDI_EVENT_PULSE_START:
03877
03878 if (!ast->pbx)
03879 tone_zone_play_tone(p->subs[index].dfd, -1);
03880 break;
03881 case DAHDI_EVENT_DIALCOMPLETE:
03882 if (p->inalarm) break;
03883 if ((p->radio || (p->oprmode < 0))) break;
03884 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
03885 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
03886 return NULL;
03887 }
03888 if (!x) {
03889 dahdi_enable_ec(p);
03890 if (p->echobreak) {
03891 dahdi_train_ec(p);
03892 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03893 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03894 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
03895 p->echobreak = 0;
03896 } else {
03897 p->dialing = 0;
03898 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03899
03900 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03901 ast_setstate(ast, AST_STATE_UP);
03902 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03903 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03904 break;
03905 } else {
03906
03907 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03908 }
03909 }
03910 if (ast->_state == AST_STATE_DIALING) {
03911 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03912 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03913 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
03914 ast_setstate(ast, AST_STATE_RINGING);
03915 } else if (!p->answeronpolarityswitch) {
03916 ast_setstate(ast, AST_STATE_UP);
03917 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03918 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03919
03920 p->polarity = POLARITY_REV;
03921 } else {
03922
03923 p->polarity = POLARITY_IDLE;
03924 }
03925 }
03926 }
03927 }
03928 break;
03929 case DAHDI_EVENT_ALARM:
03930 #ifdef HAVE_PRI
03931 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03932
03933 if (p->call) {
03934 if (p->pri && p->pri->pri) {
03935 if (!pri_grab(p, p->pri)) {
03936 pri_hangup(p->pri->pri, p->call, -1);
03937 pri_destroycall(p->pri->pri, p->call);
03938 p->call = NULL;
03939 pri_rel(p->pri);
03940 } else
03941 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03942 } else
03943 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03944 }
03945 if (p->owner)
03946 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03947 }
03948 if (p->bearer)
03949 p->bearer->inalarm = 1;
03950 else
03951 #endif
03952 p->inalarm = 1;
03953 res = get_alarms(p);
03954 handle_alarms(p, res);
03955 #ifdef HAVE_LIBPRI
03956 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03957
03958 } else {
03959 break;
03960 }
03961 #endif
03962 case DAHDI_EVENT_ONHOOK:
03963 if (p->radio) {
03964 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03965 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03966 break;
03967 }
03968 if (p->oprmode < 0)
03969 {
03970 if (p->oprmode != -1) break;
03971 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03972 {
03973
03974 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
03975 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
03976 save_conference(p->oprpeer);
03977 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03978 }
03979 break;
03980 }
03981 switch (p->sig) {
03982 case SIG_FXOLS:
03983 case SIG_FXOGS:
03984 case SIG_FXOKS:
03985 p->onhooktime = time(NULL);
03986 p->msgstate = -1;
03987
03988 if (index == SUB_REAL) {
03989
03990 if (p->subs[SUB_CALLWAIT].owner) {
03991
03992 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03993 if (option_verbose > 2)
03994 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03995 unalloc_sub(p, SUB_CALLWAIT);
03996 #if 0
03997 p->subs[index].needanswer = 0;
03998 p->subs[index].needringing = 0;
03999 #endif
04000 p->callwaitingrepeat = 0;
04001 p->cidcwexpire = 0;
04002 p->owner = NULL;
04003
04004 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04005 p->dialing = 1;
04006 dahdi_ring_phone(p);
04007 } else if (p->subs[SUB_THREEWAY].owner) {
04008 unsigned int mssinceflash;
04009
04010
04011 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04012
04013 ast_mutex_unlock(&p->lock);
04014 DEADLOCK_AVOIDANCE(&ast->lock);
04015
04016
04017
04018 ast_mutex_lock(&p->lock);
04019 if (p->owner != ast) {
04020 ast_log(LOG_WARNING, "This isn't good...\n");
04021 return NULL;
04022 }
04023 }
04024 if (!p->subs[SUB_THREEWAY].owner) {
04025 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04026 return NULL;
04027 }
04028 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04029 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04030 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04031
04032
04033 if (p->subs[SUB_THREEWAY].owner)
04034 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04035 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04036 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04037 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04038 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04039 if (p->transfer) {
04040
04041 p->subs[SUB_REAL].inthreeway = 0;
04042 p->subs[SUB_THREEWAY].inthreeway = 0;
04043
04044 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04045 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04046
04047 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04048 p->owner = NULL;
04049
04050 dahdi_ring_phone(p);
04051 } else {
04052 if ((res = attempt_transfer(p)) < 0) {
04053 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04054 if (p->subs[SUB_THREEWAY].owner)
04055 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04056 } else if (res) {
04057
04058 if (p->subs[SUB_THREEWAY].owner)
04059 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04060 break;
04061 }
04062 }
04063 } else {
04064 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04065 if (p->subs[SUB_THREEWAY].owner)
04066 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04067 }
04068 } else {
04069 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04070
04071 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04072 p->owner = NULL;
04073
04074 dahdi_ring_phone(p);
04075 }
04076 }
04077 } else {
04078 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04079 }
04080
04081 default:
04082 dahdi_disable_ec(p);
04083 return NULL;
04084 }
04085 break;
04086 case DAHDI_EVENT_RINGOFFHOOK:
04087 if (p->inalarm) break;
04088 if (p->oprmode < 0)
04089 {
04090 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04091 {
04092
04093 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04094 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04095 restore_conference(p->oprpeer);
04096 }
04097 break;
04098 }
04099 if (p->radio)
04100 {
04101 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04102 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04103 break;
04104 }
04105
04106
04107 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04108 c = strchr(p->dialdest, '/');
04109 if (c)
04110 c++;
04111 else
04112 c = p->dialdest;
04113 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04114 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04115 if (strlen(p->dop.dialstr) > 4) {
04116 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04117 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04118 p->echorest[sizeof(p->echorest) - 1] = '\0';
04119 p->echobreak = 1;
04120 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04121 } else
04122 p->echobreak = 0;
04123 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04124 int saveerr = errno;
04125
04126 x = DAHDI_ONHOOK;
04127 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04128 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04129 return NULL;
04130 }
04131 p->dialing = 1;
04132 return &p->subs[index].f;
04133 }
04134 switch (p->sig) {
04135 case SIG_FXOLS:
04136 case SIG_FXOGS:
04137 case SIG_FXOKS:
04138 switch (ast->_state) {
04139 case AST_STATE_RINGING:
04140 dahdi_enable_ec(p);
04141 dahdi_train_ec(p);
04142 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04143 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04144
04145 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04146 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04147 if (p->cidspill) {
04148
04149 free(p->cidspill);
04150 p->cidspill = NULL;
04151 }
04152 p->dialing = 0;
04153 p->callwaitcas = 0;
04154 if (p->confirmanswer) {
04155
04156 p->subs[index].f.frametype = AST_FRAME_NULL;
04157 p->subs[index].f.subclass = 0;
04158 } else if (!ast_strlen_zero(p->dop.dialstr)) {
04159
04160 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04161 if (res < 0) {
04162 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04163 p->dop.dialstr[0] = '\0';
04164 return NULL;
04165 } else {
04166 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04167 p->subs[index].f.frametype = AST_FRAME_NULL;
04168 p->subs[index].f.subclass = 0;
04169 p->dialing = 1;
04170 }
04171 p->dop.dialstr[0] = '\0';
04172 ast_setstate(ast, AST_STATE_DIALING);
04173 } else
04174 ast_setstate(ast, AST_STATE_UP);
04175 return &p->subs[index].f;
04176 case AST_STATE_DOWN:
04177 ast_setstate(ast, AST_STATE_RING);
04178 ast->rings = 1;
04179 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04180 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04181 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04182 return &p->subs[index].f;
04183 case AST_STATE_UP:
04184
04185 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04186
04187 if (ast_bridged_channel(p->owner))
04188 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04189 p->subs[index].needunhold = 1;
04190 break;
04191 case AST_STATE_RESERVED:
04192
04193 if (has_voicemail(p))
04194 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04195 else
04196 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04197 break;
04198 default:
04199 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04200 }
04201 break;
04202 case SIG_FXSLS:
04203 case SIG_FXSGS:
04204 case SIG_FXSKS:
04205 if (ast->_state == AST_STATE_RING) {
04206 p->ringt = p->ringt_base;
04207 }
04208
04209
04210 case SIG_EM:
04211 case SIG_EM_E1:
04212 case SIG_EMWINK:
04213 case SIG_FEATD:
04214 case SIG_FEATDMF:
04215 case SIG_FEATDMF_TA:
04216 case SIG_E911:
04217 case SIG_FGC_CAMA:
04218 case SIG_FGC_CAMAMF:
04219 case SIG_FEATB:
04220 case SIG_SF:
04221 case SIG_SFWINK:
04222 case SIG_SF_FEATD:
04223 case SIG_SF_FEATDMF:
04224 case SIG_SF_FEATB:
04225 if (ast->_state == AST_STATE_PRERING)
04226 ast_setstate(ast, AST_STATE_RING);
04227 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04228 if (option_debug)
04229 ast_log(LOG_DEBUG, "Ring detected\n");
04230 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04231 p->subs[index].f.subclass = AST_CONTROL_RING;
04232 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04233 if (option_debug)
04234 ast_log(LOG_DEBUG, "Line answered\n");
04235 if (p->confirmanswer) {
04236 p->subs[index].f.frametype = AST_FRAME_NULL;
04237 p->subs[index].f.subclass = 0;
04238 } else {
04239 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04240 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04241 ast_setstate(ast, AST_STATE_UP);
04242 }
04243 } else if (ast->_state != AST_STATE_RING)
04244 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04245 break;
04246 default:
04247 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04248 }
04249 break;
04250 #ifdef DAHDI_EVENT_RINGBEGIN
04251 case DAHDI_EVENT_RINGBEGIN:
04252 switch (p->sig) {
04253 case SIG_FXSLS:
04254 case SIG_FXSGS:
04255 case SIG_FXSKS:
04256 if (ast->_state == AST_STATE_RING) {
04257 p->ringt = p->ringt_base;
04258 }
04259 break;
04260 }
04261 break;
04262 #endif
04263 case DAHDI_EVENT_RINGEROFF:
04264 if (p->inalarm) break;
04265 if ((p->radio || (p->oprmode < 0))) break;
04266 ast->rings++;
04267 if ((ast->rings > p->cidrings) && (p->cidspill)) {
04268 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
04269 free(p->cidspill);
04270 p->cidspill = NULL;
04271 p->callwaitcas = 0;
04272 }
04273 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04274 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04275 break;
04276 case DAHDI_EVENT_RINGERON:
04277 break;
04278 case DAHDI_EVENT_NOALARM:
04279 p->inalarm = 0;
04280 #ifdef HAVE_PRI
04281
04282 if (p->bearer)
04283 p->bearer->inalarm = 0;
04284 #endif
04285 if (!p->unknown_alarm) {
04286 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04287 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04288 "Channel: %d\r\n", p->channel);
04289 } else {
04290 p->unknown_alarm = 0;
04291 }
04292 break;
04293 case DAHDI_EVENT_WINKFLASH:
04294 if (p->inalarm) break;
04295 if (p->radio) break;
04296 if (p->oprmode < 0) break;
04297 if (p->oprmode > 1)
04298 {
04299 struct dahdi_params par;
04300
04301 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04302 {
04303 if (!par.rxisoffhook)
04304 {
04305
04306 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04307 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04308 save_conference(p);
04309 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04310 }
04311 }
04312 break;
04313 }
04314
04315 gettimeofday(&p->flashtime, NULL);
04316 switch (mysig) {
04317 case SIG_FXOLS:
04318 case SIG_FXOGS:
04319 case SIG_FXOKS:
04320 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04321 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04322 p->callwaitcas = 0;
04323
04324 if (index != SUB_REAL) {
04325 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04326 goto winkflashdone;
04327 }
04328
04329 if (p->subs[SUB_CALLWAIT].owner) {
04330
04331 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04332 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04333 p->owner = p->subs[SUB_REAL].owner;
04334 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04335 if (p->owner->_state == AST_STATE_RINGING) {
04336 ast_setstate(p->owner, AST_STATE_UP);
04337 p->subs[SUB_REAL].needanswer = 1;
04338 }
04339 p->callwaitingrepeat = 0;
04340 p->cidcwexpire = 0;
04341
04342 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04343 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04344 S_OR(p->mohsuggest, NULL),
04345 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04346 }
04347 p->subs[SUB_CALLWAIT].needhold = 1;
04348 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04349 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04350 S_OR(p->mohsuggest, NULL),
04351 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04352 }
04353 p->subs[SUB_REAL].needunhold = 1;
04354 } else if (!p->subs[SUB_THREEWAY].owner) {
04355 char cid_num[256];
04356 char cid_name[256];
04357
04358 if (!p->threewaycalling) {
04359
04360 p->subs[SUB_REAL].needflash = 1;
04361 goto winkflashdone;
04362 } else if (!check_for_conference(p)) {
04363 if (p->dahditrcallerid && p->owner) {
04364 if (p->owner->cid.cid_num)
04365 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04366 if (p->owner->cid.cid_name)
04367 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04368 }
04369
04370
04371 if (!((ast->pbx) ||
04372 (ast->_state == AST_STATE_UP) ||
04373 (ast->_state == AST_STATE_RING))) {
04374 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04375 goto winkflashdone;
04376 }
04377 if (alloc_sub(p, SUB_THREEWAY)) {
04378 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04379 goto winkflashdone;
04380 }
04381
04382 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04383 if (p->dahditrcallerid) {
04384 if (!p->origcid_num)
04385 p->origcid_num = ast_strdup(p->cid_num);
04386 if (!p->origcid_name)
04387 p->origcid_name = ast_strdup(p->cid_name);
04388 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04389 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04390 }
04391
04392 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04393
04394 dahdi_disable_ec(p);
04395 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04396 if (res)
04397 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04398 p->owner = chan;
04399 pthread_attr_init(&attr);
04400 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04401 if (!chan) {
04402 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04403 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04404 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04405 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04406 dahdi_enable_ec(p);
04407 ast_hangup(chan);
04408 } else {
04409 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04410 int way3bridge = 0, cdr3way = 0;
04411
04412 if (!other) {
04413 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04414 } else
04415 way3bridge = 1;
04416
04417 if (p->subs[SUB_THREEWAY].owner->cdr)
04418 cdr3way = 1;
04419
04420 if (option_verbose > 2)
04421 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04422
04423 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04424 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04425 S_OR(p->mohsuggest, NULL),
04426 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04427 }
04428 p->subs[SUB_THREEWAY].needhold = 1;
04429 }
04430 pthread_attr_destroy(&attr);
04431 }
04432 } else {
04433
04434 if (p->subs[SUB_THREEWAY].inthreeway) {
04435
04436 if (option_debug)
04437 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04438
04439 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04440
04441 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04442 p->owner = p->subs[SUB_REAL].owner;
04443 }
04444
04445 if (option_verbose > 2)
04446 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04447 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04448 p->subs[SUB_REAL].inthreeway = 0;
04449 p->subs[SUB_THREEWAY].inthreeway = 0;
04450 } else {
04451
04452 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
04453 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04454 int otherindex = SUB_THREEWAY;
04455 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04456 int way3bridge = 0, cdr3way = 0;
04457
04458 if (!other) {
04459 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04460 } else
04461 way3bridge = 1;
04462
04463 if (p->subs[SUB_THREEWAY].owner->cdr)
04464 cdr3way = 1;
04465
04466 if (option_verbose > 2)
04467 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
04468
04469 p->subs[SUB_THREEWAY].inthreeway = 1;
04470 p->subs[SUB_REAL].inthreeway = 1;
04471 if (ast->_state == AST_STATE_UP) {
04472 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04473 otherindex = SUB_REAL;
04474 }
04475 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04476 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04477 p->subs[otherindex].needunhold = 1;
04478 p->owner = p->subs[SUB_REAL].owner;
04479 if (ast->_state == AST_STATE_RINGING) {
04480 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04481 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04482 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04483 }
04484 } else {
04485 if (option_verbose > 2)
04486 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04487 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04488 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04489 p->owner = p->subs[SUB_REAL].owner;
04490 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04491 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04492 p->subs[SUB_REAL].needunhold = 1;
04493 dahdi_enable_ec(p);
04494 }
04495
04496 }
04497 }
04498 winkflashdone:
04499 update_conf(p);
04500 break;
04501 case SIG_EM:
04502 case SIG_EM_E1:
04503 case SIG_EMWINK:
04504 case SIG_FEATD:
04505 case SIG_SF:
04506 case SIG_SFWINK:
04507 case SIG_SF_FEATD:
04508 case SIG_FXSLS:
04509 case SIG_FXSGS:
04510 if (p->dialing)
04511 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04512 else
04513 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04514 break;
04515 case SIG_FEATDMF_TA:
04516 switch (p->whichwink) {
04517 case 0:
04518 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04519 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04520 break;
04521 case 1:
04522 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04523 break;
04524 case 2:
04525 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04526 return NULL;
04527 }
04528 p->whichwink++;
04529
04530 case SIG_FEATDMF:
04531 case SIG_E911:
04532 case SIG_FGC_CAMAMF:
04533 case SIG_FGC_CAMA:
04534 case SIG_FEATB:
04535 case SIG_SF_FEATDMF:
04536 case SIG_SF_FEATB:
04537
04538 if (!ast_strlen_zero(p->dop.dialstr)) {
04539 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04540 if (res < 0) {
04541 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04542 p->dop.dialstr[0] = '\0';
04543 return NULL;
04544 } else
04545 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04546 }
04547 p->dop.dialstr[0] = '\0';
04548 break;
04549 default:
04550 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04551 }
04552 break;
04553 case DAHDI_EVENT_HOOKCOMPLETE:
04554 if (p->inalarm) break;
04555 if ((p->radio || (p->oprmode < 0))) break;
04556 switch (mysig) {
04557 case SIG_FXSLS:
04558 case SIG_FXSGS:
04559 case SIG_FXSKS:
04560 case SIG_EM:
04561 case SIG_EM_E1:
04562 case SIG_EMWINK:
04563 case SIG_FEATD:
04564 case SIG_SF:
04565 case SIG_SFWINK:
04566 case SIG_SF_FEATD:
04567 if (!ast_strlen_zero(p->dop.dialstr)) {
04568 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04569 if (res < 0) {
04570 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04571 p->dop.dialstr[0] = '\0';
04572 return NULL;
04573 } else
04574 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04575 }
04576 p->dop.dialstr[0] = '\0';
04577 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04578 break;
04579 case SIG_FEATDMF:
04580 case SIG_FEATDMF_TA:
04581 case SIG_E911:
04582 case SIG_FGC_CAMA:
04583 case SIG_FGC_CAMAMF:
04584 case SIG_FEATB:
04585 case SIG_SF_FEATDMF:
04586 case SIG_SF_FEATB:
04587 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04588 break;
04589 default:
04590 break;
04591 }
04592 break;
04593 case DAHDI_EVENT_POLARITY:
04594
04595
04596
04597
04598
04599
04600 if (p->polarity == POLARITY_IDLE) {
04601 p->polarity = POLARITY_REV;
04602 if (p->answeronpolarityswitch &&
04603 ((ast->_state == AST_STATE_DIALING) ||
04604 (ast->_state == AST_STATE_RINGING))) {
04605 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04606 ast_setstate(p->owner, AST_STATE_UP);
04607 if (p->hanguponpolarityswitch) {
04608 gettimeofday(&p->polaritydelaytv, NULL);
04609 }
04610 } else
04611 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04612 }
04613
04614
04615 if (p->hanguponpolarityswitch &&
04616 (p->polarityonanswerdelay > 0) &&
04617 (p->polarity == POLARITY_REV) &&
04618 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04619
04620 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04621
04622 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04623 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04624 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04625 p->polarity = POLARITY_IDLE;
04626 } else {
04627 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
04628 }
04629 } else {
04630 p->polarity = POLARITY_IDLE;
04631 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04632 }
04633
04634 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04635 break;
04636 default:
04637 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04638 }
04639 return &p->subs[index].f;
04640 }
04641
04642 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04643 {
04644 struct dahdi_pvt *p = ast->tech_pvt;
04645 int res;
04646 int usedindex=-1;
04647 int index;
04648 struct ast_frame *f;
04649
04650
04651 index = dahdi_get_index(ast, p, 1);
04652
04653 p->subs[index].f.frametype = AST_FRAME_NULL;
04654 p->subs[index].f.datalen = 0;
04655 p->subs[index].f.samples = 0;
04656 p->subs[index].f.mallocd = 0;
04657 p->subs[index].f.offset = 0;
04658 p->subs[index].f.subclass = 0;
04659 p->subs[index].f.delivery = ast_tv(0,0);
04660 p->subs[index].f.src = "dahdi_exception";
04661 p->subs[index].f.data = NULL;
04662
04663
04664 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04665
04666
04667
04668
04669
04670 if (p->fake_event) {
04671 res = p->fake_event;
04672 p->fake_event = 0;
04673 } else
04674 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04675
04676 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04677 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04678 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04679 p->owner = p->subs[SUB_REAL].owner;
04680 if (p->owner && ast_bridged_channel(p->owner))
04681 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04682 p->subs[SUB_REAL].needunhold = 1;
04683 }
04684 switch (res) {
04685 case DAHDI_EVENT_ONHOOK:
04686 dahdi_disable_ec(p);
04687 if (p->owner) {
04688 if (option_verbose > 2)
04689 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04690 dahdi_ring_phone(p);
04691 p->callwaitingrepeat = 0;
04692 p->cidcwexpire = 0;
04693 } else
04694 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04695 update_conf(p);
04696 break;
04697 case DAHDI_EVENT_RINGOFFHOOK:
04698 dahdi_enable_ec(p);
04699 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04700 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04701 p->subs[SUB_REAL].needanswer = 1;
04702 p->dialing = 0;
04703 }
04704 break;
04705 case DAHDI_EVENT_HOOKCOMPLETE:
04706 case DAHDI_EVENT_RINGERON:
04707 case DAHDI_EVENT_RINGEROFF:
04708
04709 break;
04710 case DAHDI_EVENT_WINKFLASH:
04711 gettimeofday(&p->flashtime, NULL);
04712 if (p->owner) {
04713 if (option_verbose > 2)
04714 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04715 if (p->owner->_state != AST_STATE_UP) {
04716
04717 usedindex = dahdi_get_index(p->owner, p, 0);
04718 if (usedindex > -1) {
04719 p->subs[usedindex].needanswer = 1;
04720 }
04721 ast_setstate(p->owner, AST_STATE_UP);
04722 }
04723 p->callwaitingrepeat = 0;
04724 p->cidcwexpire = 0;
04725 if (ast_bridged_channel(p->owner))
04726 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04727 p->subs[SUB_REAL].needunhold = 1;
04728 } else
04729 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04730 update_conf(p);
04731 break;
04732 default:
04733 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04734 }
04735 f = &p->subs[index].f;
04736 return f;
04737 }
04738 if (!(p->radio || (p->oprmode < 0)) && option_debug)
04739 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04740
04741 if (ast != p->owner) {
04742 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04743 f = &p->subs[index].f;
04744 return f;
04745 }
04746 f = dahdi_handle_event(ast);
04747 return f;
04748 }
04749
04750 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
04751 {
04752 struct dahdi_pvt *p = ast->tech_pvt;
04753 struct ast_frame *f;
04754 ast_mutex_lock(&p->lock);
04755 f = __dahdi_exception(ast);
04756 ast_mutex_unlock(&p->lock);
04757 return f;
04758 }
04759
04760 static struct ast_frame *dahdi_read(struct ast_channel *ast)
04761 {
04762 struct dahdi_pvt *p = ast->tech_pvt;
04763 int res;
04764 int index;
04765 void *readbuf;
04766 struct ast_frame *f;
04767
04768 while (ast_mutex_trylock(&p->lock)) {
04769 DEADLOCK_AVOIDANCE(&ast->lock);
04770 }
04771
04772 index = dahdi_get_index(ast, p, 0);
04773
04774
04775 if (index < 0) {
04776 ast_log(LOG_WARNING, "We dont exist?\n");
04777 ast_mutex_unlock(&p->lock);
04778 return NULL;
04779 }
04780
04781 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04782
04783 p->subs[index].f.frametype = AST_FRAME_NULL;
04784 p->subs[index].f.datalen = 0;
04785 p->subs[index].f.samples = 0;
04786 p->subs[index].f.mallocd = 0;
04787 p->subs[index].f.offset = 0;
04788 p->subs[index].f.subclass = 0;
04789 p->subs[index].f.delivery = ast_tv(0,0);
04790 p->subs[index].f.src = "dahdi_read";
04791 p->subs[index].f.data = NULL;
04792
04793
04794 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04795 {
04796 struct dahdi_params ps;
04797
04798 ps.channo = p->channel;
04799 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
04800 ast_mutex_unlock(&p->lock);
04801 return NULL;
04802 }
04803 p->firstradio = 1;
04804 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04805 if (ps.rxisoffhook)
04806 {
04807 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04808 }
04809 else
04810 {
04811 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04812 }
04813 ast_mutex_unlock(&p->lock);
04814 return &p->subs[index].f;
04815 }
04816 if (p->ringt == 1) {
04817 ast_mutex_unlock(&p->lock);
04818 return NULL;
04819 }
04820 else if (p->ringt > 0)
04821 p->ringt--;
04822
04823 if (p->subs[index].needringing) {
04824
04825 p->subs[index].needringing = 0;
04826 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04827 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04828 ast_setstate(ast, AST_STATE_RINGING);
04829 ast_mutex_unlock(&p->lock);
04830 return &p->subs[index].f;
04831 }
04832
04833 if (p->subs[index].needbusy) {
04834
04835 p->subs[index].needbusy = 0;
04836 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04837 p->subs[index].f.subclass = AST_CONTROL_BUSY;
04838 ast_mutex_unlock(&p->lock);
04839 return &p->subs[index].f;
04840 }
04841
04842 if (p->subs[index].needcongestion) {
04843
04844 p->subs[index].needcongestion = 0;
04845 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04846 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04847 ast_mutex_unlock(&p->lock);
04848 return &p->subs[index].f;
04849 }
04850
04851 if (p->subs[index].needcallerid) {
04852 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04853 S_OR(p->lastcid_name, NULL),
04854 S_OR(p->lastcid_num, NULL)
04855 );
04856 p->subs[index].needcallerid = 0;
04857 }
04858
04859 if (p->subs[index].needanswer) {
04860
04861 p->subs[index].needanswer = 0;
04862 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04863 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04864 ast_mutex_unlock(&p->lock);
04865 return &p->subs[index].f;
04866 }
04867
04868 if (p->subs[index].needflash) {
04869
04870 p->subs[index].needflash = 0;
04871 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04872 p->subs[index].f.subclass = AST_CONTROL_FLASH;
04873 ast_mutex_unlock(&p->lock);
04874 return &p->subs[index].f;
04875 }
04876
04877 if (p->subs[index].needhold) {
04878
04879 p->subs[index].needhold = 0;
04880 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04881 p->subs[index].f.subclass = AST_CONTROL_HOLD;
04882 ast_mutex_unlock(&p->lock);
04883 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04884 return &p->subs[index].f;
04885 }
04886
04887 if (p->subs[index].needunhold) {
04888
04889 p->subs[index].needunhold = 0;
04890 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04891 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04892 ast_mutex_unlock(&p->lock);
04893 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04894 return &p->subs[index].f;
04895 }
04896
04897 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04898 if (!p->subs[index].linear) {
04899 p->subs[index].linear = 1;
04900 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04901 if (res)
04902 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04903 }
04904 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04905 (ast->rawreadformat == AST_FORMAT_ALAW)) {
04906 if (p->subs[index].linear) {
04907 p->subs[index].linear = 0;
04908 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04909 if (res)
04910 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04911 }
04912 } else {
04913 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04914 ast_mutex_unlock(&p->lock);
04915 return NULL;
04916 }
04917 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04918 CHECK_BLOCKING(ast);
04919 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04920 ast_clear_flag(ast, AST_FLAG_BLOCKING);
04921
04922 if (res < 0) {
04923 f = NULL;
04924 if (res == -1) {
04925 if (errno == EAGAIN) {
04926
04927 ast_mutex_unlock(&p->lock);
04928 return &p->subs[index].f;
04929 } else if (errno == ELAST) {
04930 f = __dahdi_exception(ast);
04931 } else
04932 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
04933 }
04934 ast_mutex_unlock(&p->lock);
04935 return f;
04936 }
04937 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04938 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04939 f = __dahdi_exception(ast);
04940 ast_mutex_unlock(&p->lock);
04941 return f;
04942 }
04943 if (p->tdd) {
04944 int c;
04945
04946 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04947 if (c < 0) {
04948 ast_log(LOG_DEBUG,"tdd_feed failed\n");
04949 ast_mutex_unlock(&p->lock);
04950 return NULL;
04951 }
04952 if (c) {
04953 p->subs[index].f.subclass = 0;
04954 p->subs[index].f.frametype = AST_FRAME_TEXT;
04955 p->subs[index].f.mallocd = 0;
04956 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04957 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04958 p->subs[index].f.datalen = 1;
04959 *((char *) p->subs[index].f.data) = c;
04960 ast_mutex_unlock(&p->lock);
04961 return &p->subs[index].f;
04962 }
04963 }
04964
04965 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
04966 p->callwaitingrepeat--;
04967 }
04968 if (p->cidcwexpire)
04969 p->cidcwexpire--;
04970
04971 if (p->callwaitingrepeat == 1) {
04972 p->callwaitrings++;
04973 dahdi_callwait(ast);
04974 }
04975
04976 if (p->cidcwexpire == 1) {
04977 if (option_verbose > 2)
04978 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04979 restore_conference(p);
04980 }
04981 if (p->subs[index].linear) {
04982 p->subs[index].f.datalen = READ_SIZE * 2;
04983 } else
04984 p->subs[index].f.datalen = READ_SIZE;
04985
04986
04987 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04988 send_callerid(p);
04989 }
04990
04991 p->subs[index].f.frametype = AST_FRAME_VOICE;
04992 p->subs[index].f.subclass = ast->rawreadformat;
04993 p->subs[index].f.samples = READ_SIZE;
04994 p->subs[index].f.mallocd = 0;
04995 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04996 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04997 #if 0
04998 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04999 #endif
05000 if (p->dialing ||
05001 (index && (ast->_state != AST_STATE_UP)) ||
05002 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05003 ) {
05004
05005
05006 p->subs[index].f.frametype = AST_FRAME_NULL;
05007 p->subs[index].f.subclass = 0;
05008 p->subs[index].f.samples = 0;
05009 p->subs[index].f.mallocd = 0;
05010 p->subs[index].f.offset = 0;
05011 p->subs[index].f.data = NULL;
05012 p->subs[index].f.datalen= 0;
05013 }
05014 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05015
05016 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05017 if (f) {
05018 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05019 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05020
05021
05022 f = NULL;
05023 }
05024 } else if (f->frametype == AST_FRAME_DTMF) {
05025 #ifdef HAVE_PRI
05026 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05027
05028 f->frametype = AST_FRAME_NULL;
05029 f->subclass = 0;
05030 }
05031 #endif
05032
05033 p->pulsedial = 0;
05034 }
05035 }
05036 } else
05037 f = &p->subs[index].f;
05038
05039 if (f && (f->frametype == AST_FRAME_DTMF))
05040 dahdi_handle_dtmfup(ast, index, &f);
05041
05042
05043 if (p->fake_event)
05044 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05045
05046 ast_mutex_unlock(&p->lock);
05047 return f;
05048 }
05049
05050 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05051 {
05052 int sent=0;
05053 int size;
05054 int res;
05055 int fd;
05056 fd = p->subs[index].dfd;
05057 while (len) {
05058 size = len;
05059 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05060 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05061 res = write(fd, buf, size);
05062 if (res != size) {
05063 if (option_debug)
05064 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05065 return sent;
05066 }
05067 len -= size;
05068 buf += size;
05069 }
05070 return sent;
05071 }
05072
05073 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05074 {
05075 struct dahdi_pvt *p = ast->tech_pvt;
05076 int res;
05077 int index;
05078 index = dahdi_get_index(ast, p, 0);
05079 if (index < 0) {
05080 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05081 return -1;
05082 }
05083
05084 #if 0
05085 #ifdef HAVE_PRI
05086 ast_mutex_lock(&p->lock);
05087 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05088 if (p->pri->pri) {
05089 if (!pri_grab(p, p->pri)) {
05090 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05091 pri_rel(p->pri);
05092 } else
05093 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05094 }
05095 p->proceeding=1;
05096 }
05097 ast_mutex_unlock(&p->lock);
05098 #endif
05099 #endif
05100
05101 if (frame->frametype != AST_FRAME_VOICE) {
05102 if (frame->frametype != AST_FRAME_IMAGE)
05103 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05104 return 0;
05105 }
05106 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
05107 (frame->subclass != AST_FORMAT_ULAW) &&
05108 (frame->subclass != AST_FORMAT_ALAW)) {
05109 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05110 return -1;
05111 }
05112 if (p->dialing) {
05113 if (option_debug)
05114 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05115 return 0;
05116 }
05117 if (!p->owner) {
05118 if (option_debug)
05119 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05120 return 0;
05121 }
05122 if (p->cidspill) {
05123 if (option_debug)
05124 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05125 return 0;
05126 }
05127
05128 if (!frame->data || !frame->datalen)
05129 return 0;
05130
05131 if (frame->subclass == AST_FORMAT_SLINEAR) {
05132 if (!p->subs[index].linear) {
05133 p->subs[index].linear = 1;
05134 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05135 if (res)
05136 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05137 }
05138 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05139 } else {
05140
05141 if (p->subs[index].linear) {
05142 p->subs[index].linear = 0;
05143 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05144 if (res)
05145 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05146 }
05147 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05148 }
05149 if (res < 0) {
05150 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05151 return -1;
05152 }
05153 return 0;
05154 }
05155
05156 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05157 {
05158 struct dahdi_pvt *p = chan->tech_pvt;
05159 int res=-1;
05160 int index;
05161 int func = DAHDI_FLASH;
05162 ast_mutex_lock(&p->lock);
05163 index = dahdi_get_index(chan, p, 0);
05164 if (option_debug)
05165 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05166 if (index == SUB_REAL) {
05167 switch (condition) {
05168 case AST_CONTROL_BUSY:
05169 #ifdef HAVE_PRI
05170 if (p->priindication_oob && p->sig == SIG_PRI) {
05171 chan->hangupcause = AST_CAUSE_USER_BUSY;
05172 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05173 res = 0;
05174 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05175 if (p->pri->pri) {
05176 if (!pri_grab(p, p->pri)) {
05177 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05178 pri_rel(p->pri);
05179 }
05180 else
05181 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05182 }
05183 p->progress = 1;
05184 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05185 } else
05186 #endif
05187 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05188 break;
05189 case AST_CONTROL_RINGING:
05190 #ifdef HAVE_PRI
05191 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05192 if (p->pri->pri) {
05193 if (!pri_grab(p, p->pri)) {
05194 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05195 pri_rel(p->pri);
05196 }
05197 else
05198 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05199 }
05200 p->alerting = 1;
05201 }
05202 #endif
05203 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05204 if (chan->_state != AST_STATE_UP) {
05205 if ((chan->_state != AST_STATE_RING) ||
05206 ((p->sig != SIG_FXSKS) &&
05207 (p->sig != SIG_FXSLS) &&
05208 (p->sig != SIG_FXSGS)))
05209 ast_setstate(chan, AST_STATE_RINGING);
05210 }
05211 break;
05212 case AST_CONTROL_PROCEEDING:
05213 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05214 #ifdef HAVE_PRI
05215 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05216 if (p->pri->pri) {
05217 if (!pri_grab(p, p->pri)) {
05218 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05219 pri_rel(p->pri);
05220 }
05221 else
05222 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05223 }
05224 p->proceeding = 1;
05225 }
05226 #endif
05227
05228 res = 0;
05229 break;
05230 case AST_CONTROL_PROGRESS:
05231 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05232 #ifdef HAVE_PRI
05233 p->digital = 0;
05234 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05235 if (p->pri->pri) {
05236 if (!pri_grab(p, p->pri)) {
05237 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05238 pri_rel(p->pri);
05239 }
05240 else
05241 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05242 }
05243 p->progress = 1;
05244 }
05245 #endif
05246
05247 res = 0;
05248 break;
05249 case AST_CONTROL_CONGESTION:
05250 chan->hangupcause = AST_CAUSE_CONGESTION;
05251 #ifdef HAVE_PRI
05252 if (p->priindication_oob && p->sig == SIG_PRI) {
05253 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05254 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05255 res = 0;
05256 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05257 if (p->pri) {
05258 if (!pri_grab(p, p->pri)) {
05259 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05260 pri_rel(p->pri);
05261 } else
05262 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05263 }
05264 p->progress = 1;
05265 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05266 } else
05267 #endif
05268 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05269 break;
05270 case AST_CONTROL_HOLD:
05271 #ifdef HAVE_PRI
05272 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05273 if (!pri_grab(p, p->pri)) {
05274 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05275 pri_rel(p->pri);
05276 } else
05277 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05278 } else
05279 #endif
05280 ast_moh_start(chan, data, p->mohinterpret);
05281 break;
05282 case AST_CONTROL_UNHOLD:
05283 #ifdef HAVE_PRI
05284 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05285 if (!pri_grab(p, p->pri)) {
05286 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05287 pri_rel(p->pri);
05288 } else
05289 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05290 } else
05291 #endif
05292 ast_moh_stop(chan);
05293 break;
05294 case AST_CONTROL_RADIO_KEY:
05295 if (p->radio)
05296 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05297 res = 0;
05298 break;
05299 case AST_CONTROL_RADIO_UNKEY:
05300 if (p->radio)
05301 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05302 res = 0;
05303 break;
05304 case AST_CONTROL_FLASH:
05305
05306 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05307
05308 p->dop.dialstr[0] = '\0';
05309 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05310 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
05311 chan->name, strerror(errno));
05312 } else
05313 res = 0;
05314 } else
05315 res = 0;
05316 break;
05317 case AST_CONTROL_SRCUPDATE:
05318 res = 0;
05319 break;
05320 case -1:
05321 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05322 break;
05323 }
05324 } else
05325 res = 0;
05326 ast_mutex_unlock(&p->lock);
05327 return res;
05328 }
05329
05330 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05331 {
05332 struct ast_channel *tmp;
05333 int deflaw;
05334 int res;
05335 int x,y;
05336 int features;
05337 char *b2 = NULL;
05338 struct dahdi_params ps;
05339 char chanprefix[*dahdi_chan_name_len + 4];
05340
05341 if (i->subs[index].owner) {
05342 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05343 return NULL;
05344 }
05345 y = 1;
05346 do {
05347 if (b2)
05348 free(b2);
05349 #ifdef HAVE_PRI
05350 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05351 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05352 else
05353 #endif
05354 if (i->channel == CHAN_PSEUDO)
05355 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05356 else
05357 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05358 for (x = 0; x < 3; x++) {
05359 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05360 break;
05361 }
05362 y++;
05363 } while (x < 3);
05364 strcpy(chanprefix, dahdi_chan_name);
05365 strcat(chanprefix, "/%s");
05366 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05367 if (b2)
05368 free(b2);
05369 if (!tmp)
05370 return NULL;
05371 tmp->tech = chan_tech;
05372 ps.channo = i->channel;
05373 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05374 if (res) {
05375 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05376 ps.curlaw = DAHDI_LAW_MULAW;
05377 }
05378 if (ps.curlaw == DAHDI_LAW_ALAW)
05379 deflaw = AST_FORMAT_ALAW;
05380 else
05381 deflaw = AST_FORMAT_ULAW;
05382 if (law) {
05383 if (law == DAHDI_LAW_ALAW)
05384 deflaw = AST_FORMAT_ALAW;
05385 else
05386 deflaw = AST_FORMAT_ULAW;
05387 }
05388 tmp->fds[0] = i->subs[index].dfd;
05389 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05390
05391 tmp->rawreadformat = deflaw;
05392 tmp->readformat = deflaw;
05393 tmp->rawwriteformat = deflaw;
05394 tmp->writeformat = deflaw;
05395 i->subs[index].linear = 0;
05396 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05397 features = 0;
05398 if (index == SUB_REAL) {
05399 if (i->busydetect && CANBUSYDETECT(i))
05400 features |= DSP_FEATURE_BUSY_DETECT;
05401 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05402 features |= DSP_FEATURE_CALL_PROGRESS;
05403 if ((!i->outgoing && (i->callprogress & 4)) ||
05404 (i->outgoing && (i->callprogress & 2))) {
05405 features |= DSP_FEATURE_FAX_DETECT;
05406 }
05407 #ifdef DAHDI_TONEDETECT
05408 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05409 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05410 #endif
05411 i->hardwaredtmf = 0;
05412 features |= DSP_FEATURE_DTMF_DETECT;
05413 #ifdef DAHDI_TONEDETECT
05414 } else if (NEED_MFDETECT(i)) {
05415 i->hardwaredtmf = 1;
05416 features |= DSP_FEATURE_DTMF_DETECT;
05417 }
05418 #endif
05419 }
05420 if (features) {
05421 if (i->dsp) {
05422 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05423 } else {
05424 if (i->channel != CHAN_PSEUDO)
05425 i->dsp = ast_dsp_new();
05426 else
05427 i->dsp = NULL;
05428 if (i->dsp) {
05429 i->dsp_features = features;
05430 #ifdef HAVE_PRI
05431
05432 if (i->outgoing && (i->sig == SIG_PRI)) {
05433
05434
05435 i->dsp_features = features & ~DSP_PROGRESS_TALK;
05436 features = 0;
05437 }
05438 #endif
05439 ast_dsp_set_features(i->dsp, features);
05440 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05441 if (!ast_strlen_zero(progzone))
05442 ast_dsp_set_call_progress_zone(i->dsp, progzone);
05443 if (i->busydetect && CANBUSYDETECT(i)) {
05444 if(i->silencethreshold > 0)
05445 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05446 ast_dsp_set_busy_count(i->dsp, i->busycount);
05447 if(i->busytonelength > 0)
05448 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05449 if((i->busytonelength == i->busyquietlength) && i->busycompare)
05450 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05451 }
05452 }
05453 }
05454 }
05455
05456 if (state == AST_STATE_RING)
05457 tmp->rings = 1;
05458 tmp->tech_pvt = i;
05459 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05460
05461 tmp->callgroup = i->callgroup;
05462 tmp->pickupgroup = i->pickupgroup;
05463 }
05464 if (!ast_strlen_zero(i->language))
05465 ast_string_field_set(tmp, language, i->language);
05466 if (!i->owner)
05467 i->owner = tmp;
05468 if (!ast_strlen_zero(i->accountcode))
05469 ast_string_field_set(tmp, accountcode, i->accountcode);
05470 if (i->amaflags)
05471 tmp->amaflags = i->amaflags;
05472 i->subs[index].owner = tmp;
05473 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05474 ast_string_field_set(tmp, call_forward, i->call_forward);
05475
05476 if (!i->adsi)
05477 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05478 if (!ast_strlen_zero(i->exten))
05479 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05480 if (!ast_strlen_zero(i->rdnis))
05481 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05482 if (!ast_strlen_zero(i->dnid))
05483 tmp->cid.cid_dnid = ast_strdup(i->dnid);
05484
05485
05486
05487 #ifdef PRI_ANI
05488 if (!ast_strlen_zero(i->cid_ani))
05489 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05490 else
05491 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05492 #else
05493 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05494 #endif
05495 tmp->cid.cid_pres = i->callingpres;
05496 tmp->cid.cid_ton = i->cid_ton;
05497 #ifdef HAVE_PRI
05498 tmp->transfercapability = transfercapability;
05499 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05500 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05501 i->digital = 1;
05502
05503 i->isidlecall = 0;
05504 i->alreadyhungup = 0;
05505 #endif
05506
05507 i->fake_event = 0;
05508
05509 dahdi_confmute(i, 0);
05510
05511 ast_jb_configure(tmp, &global_jbconf);
05512 if (startpbx) {
05513 if (ast_pbx_start(tmp)) {
05514 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05515 ast_hangup(tmp);
05516 i->owner = NULL;
05517 return NULL;
05518 }
05519 }
05520
05521 ast_module_ref(ast_module_info->self);
05522
05523 return tmp;
05524 }
05525
05526
05527 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05528 {
05529 char c;
05530
05531 *str = 0;
05532 for (;;)
05533 {
05534
05535 c = ast_waitfordigit(chan, ms);
05536
05537 if (c < 1)
05538 return c;
05539 *str++ = c;
05540 *str = 0;
05541 if (strchr(term, c))
05542 return 1;
05543 }
05544 }
05545
05546 static int dahdi_wink(struct dahdi_pvt *p, int index)
05547 {
05548 int j;
05549 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05550 for (;;)
05551 {
05552
05553 j = DAHDI_IOMUX_SIGEVENT;
05554
05555 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05556
05557 if (j & DAHDI_IOMUX_SIGEVENT) break;
05558 }
05559
05560 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05561 return 0;
05562 }
05563
05564 static void *ss_thread(void *data)
05565 {
05566 struct ast_channel *chan = data;
05567 struct dahdi_pvt *p = chan->tech_pvt;
05568 char exten[AST_MAX_EXTENSION] = "";
05569 char exten2[AST_MAX_EXTENSION] = "";
05570 unsigned char buf[256];
05571 char dtmfcid[300];
05572 char dtmfbuf[300];
05573 struct callerid_state *cs = NULL;
05574 char *name = NULL, *number = NULL;
05575 int distMatches;
05576 int curRingData[3];
05577 int receivedRingT;
05578 int counter1;
05579 int counter;
05580 int samples = 0;
05581 struct ast_smdi_md_message *smdi_msg = NULL;
05582 int flags;
05583 int i;
05584 int timeout;
05585 int getforward = 0;
05586 char *s1, *s2;
05587 int len = 0;
05588 int res;
05589 int index;
05590
05591 ast_mutex_lock(&ss_thread_lock);
05592 ss_thread_count++;
05593 ast_mutex_unlock(&ss_thread_lock);
05594
05595
05596
05597 if (!p) {
05598 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05599 ast_hangup(chan);
05600 goto quit;
05601 }
05602 if (option_verbose > 2)
05603 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05604 index = dahdi_get_index(chan, p, 1);
05605 if (index < 0) {
05606 ast_log(LOG_WARNING, "Huh?\n");
05607 ast_hangup(chan);
05608 goto quit;
05609 }
05610 if (p->dsp)
05611 ast_dsp_digitreset(p->dsp);
05612 switch (p->sig) {
05613 #ifdef HAVE_PRI
05614 case SIG_PRI:
05615
05616 ast_copy_string(exten, p->exten, sizeof(exten));
05617 len = strlen(exten);
05618 res = 0;
05619 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05620 if (len && !ast_ignore_pattern(chan->context, exten))
05621 tone_zone_play_tone(p->subs[index].dfd, -1);
05622 else
05623 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05624 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05625 timeout = matchdigittimeout;
05626 else
05627 timeout = gendigittimeout;
05628 res = ast_waitfordigit(chan, timeout);
05629 if (res < 0) {
05630 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05631 ast_hangup(chan);
05632 goto quit;
05633 } else if (res) {
05634 exten[len++] = res;
05635 exten[len] = '\0';
05636 } else
05637 break;
05638 }
05639
05640 if (ast_strlen_zero(exten)) {
05641 if (option_verbose > 2)
05642 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05643 exten[0] = 's';
05644 exten[1] = '\0';
05645 }
05646 tone_zone_play_tone(p->subs[index].dfd, -1);
05647 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05648
05649 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05650 if (p->dsp) ast_dsp_digitreset(p->dsp);
05651 dahdi_enable_ec(p);
05652 ast_setstate(chan, AST_STATE_RING);
05653 res = ast_pbx_run(chan);
05654 if (res) {
05655 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05656 }
05657 } else {
05658 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05659 chan->hangupcause = AST_CAUSE_UNALLOCATED;
05660 ast_hangup(chan);
05661 p->exten[0] = '\0';
05662
05663 p->call = NULL;
05664 }
05665 goto quit;
05666 break;
05667 #endif
05668 case SIG_FEATD:
05669 case SIG_FEATDMF:
05670 case SIG_FEATDMF_TA:
05671 case SIG_E911:
05672 case SIG_FGC_CAMAMF:
05673 case SIG_FEATB:
05674 case SIG_EMWINK:
05675 case SIG_SF_FEATD:
05676 case SIG_SF_FEATDMF:
05677 case SIG_SF_FEATB:
05678 case SIG_SFWINK:
05679 if (dahdi_wink(p, index))
05680 goto quit;
05681
05682 case SIG_EM:
05683 case SIG_EM_E1:
05684 case SIG_SF:
05685 case SIG_FGC_CAMA:
05686 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05687 if (p->dsp)
05688 ast_dsp_digitreset(p->dsp);
05689
05690 if (p->dsp) {
05691 if (NEED_MFDETECT(p))
05692 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05693 else
05694 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05695 }
05696 memset(dtmfbuf, 0, sizeof(dtmfbuf));
05697
05698 if (!p->immediate)
05699
05700 res = ast_waitfordigit(chan, 5000);
05701 else
05702 res = 0;
05703 if (res > 0) {
05704
05705 dtmfbuf[0] = res;
05706 switch (p->sig) {
05707 case SIG_FEATD:
05708 case SIG_SF_FEATD:
05709 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05710 if (res > 0)
05711 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05712 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05713 break;
05714 case SIG_FEATDMF_TA:
05715 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05716 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05717 if (dahdi_wink(p, index)) goto quit;
05718 dtmfbuf[0] = 0;
05719
05720 res = ast_waitfordigit(chan, 5000);
05721 if (res <= 0) break;
05722 dtmfbuf[0] = res;
05723
05724 case SIG_FEATDMF:
05725 case SIG_E911:
05726 case SIG_FGC_CAMAMF:
05727 case SIG_SF_FEATDMF:
05728 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05729
05730 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05731 {
05732 if (dahdi_wink(p, index)) goto quit;
05733 dtmfbuf[0] = 0;
05734
05735 res = ast_waitfordigit(chan, 5000);
05736 if (res <= 0) break;
05737 dtmfbuf[0] = res;
05738 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05739 }
05740 if (res > 0) {
05741
05742 if (p->sig == SIG_E911)
05743 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05744 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05745 }
05746 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05747 break;
05748 case SIG_FEATB:
05749 case SIG_SF_FEATB:
05750 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05751 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05752 break;
05753 case SIG_EMWINK:
05754
05755
05756
05757
05758 if (res == '*') {
05759 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05760 if (res > 0)
05761 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05762 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05763 break;
05764 }
05765 default:
05766
05767 len = 1;
05768 dtmfbuf[len] = '\0';
05769 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05770 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05771 timeout = matchdigittimeout;
05772 } else {
05773 timeout = gendigittimeout;
05774 }
05775 res = ast_waitfordigit(chan, timeout);
05776 if (res < 0) {
05777 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05778 ast_hangup(chan);
05779 goto quit;
05780 } else if (res) {
05781 dtmfbuf[len++] = res;
05782 dtmfbuf[len] = '\0';
05783 } else {
05784 break;
05785 }
05786 }
05787 break;
05788 }
05789 }
05790 if (res == -1) {
05791 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05792 ast_hangup(chan);
05793 goto quit;
05794 } else if (res < 0) {
05795 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05796 ast_hangup(chan);
05797 goto quit;
05798 }
05799
05800 if (p->sig == SIG_FGC_CAMA) {
05801 char anibuf[100];
05802
05803 if (ast_safe_sleep(chan,1000) == -1) {
05804 ast_hangup(chan);
05805 goto quit;
05806 }
05807 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05808 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05809 res = my_getsigstr(chan, anibuf, "#", 10000);
05810 if ((res > 0) && (strlen(anibuf) > 2)) {
05811 if (anibuf[strlen(anibuf) - 1] == '#')
05812 anibuf[strlen(anibuf) - 1] = 0;
05813 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05814 }
05815 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05816 }
05817
05818 ast_copy_string(exten, dtmfbuf, sizeof(exten));
05819 if (ast_strlen_zero(exten))
05820 ast_copy_string(exten, "s", sizeof(exten));
05821 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05822
05823 if (exten[0] == '*') {
05824 char *stringp=NULL;
05825 ast_copy_string(exten2, exten, sizeof(exten2));
05826
05827 stringp=exten2 +1;
05828 s1 = strsep(&stringp, "*");
05829 s2 = strsep(&stringp, "*");
05830 if (s2) {
05831 if (!ast_strlen_zero(p->cid_num))
05832 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05833 else
05834 ast_set_callerid(chan, s1, NULL, s1);
05835 ast_copy_string(exten, s2, sizeof(exten));
05836 } else
05837 ast_copy_string(exten, s1, sizeof(exten));
05838 } else if (p->sig == SIG_FEATD)
05839 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
05840 }
05841 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05842 if (exten[0] == '*') {
05843 char *stringp=NULL;
05844 ast_copy_string(exten2, exten, sizeof(exten2));
05845
05846 stringp=exten2 +1;
05847 s1 = strsep(&stringp, "#");
05848 s2 = strsep(&stringp, "#");
05849 if (s2) {
05850 if (!ast_strlen_zero(p->cid_num))
05851 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05852 else
05853 if (*(s1 + 2))
05854 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05855 ast_copy_string(exten, s2 + 1, sizeof(exten));
05856 } else
05857 ast_copy_string(exten, s1 + 2, sizeof(exten));
05858 } else
05859 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
05860 }
05861 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05862 if (exten[0] == '*') {
05863 char *stringp=NULL;
05864 ast_copy_string(exten2, exten, sizeof(exten2));
05865
05866 stringp=exten2 +1;
05867 s1 = strsep(&stringp, "#");
05868 s2 = strsep(&stringp, "#");
05869 if (s2 && (*(s2 + 1) == '0')) {
05870 if (*(s2 + 2))
05871 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05872 }
05873 if (s1) ast_copy_string(exten, s1, sizeof(exten));
05874 else ast_copy_string(exten, "911", sizeof(exten));
05875 } else
05876 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
05877 }
05878 if (p->sig == SIG_FEATB) {
05879 if (exten[0] == '*') {
05880 char *stringp=NULL;
05881 ast_copy_string(exten2, exten, sizeof(exten2));
05882
05883 stringp=exten2 +1;
05884 s1 = strsep(&stringp, "#");
05885 ast_copy_string(exten, exten2 + 1, sizeof(exten));
05886 } else
05887 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
05888 }
05889 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05890 dahdi_wink(p, index);
05891
05892
05893
05894 if (ast_safe_sleep(chan,100)) goto quit;
05895 }
05896 dahdi_enable_ec(p);
05897 if (NEED_MFDETECT(p)) {
05898 if (p->dsp) {
05899 if (!p->hardwaredtmf)
05900 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05901 else {
05902 ast_dsp_free(p->dsp);
05903 p->dsp = NULL;
05904 }
05905 }
05906 }
05907
05908 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05909 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05910 if (p->dsp) ast_dsp_digitreset(p->dsp);
05911 res = ast_pbx_run(chan);
05912 if (res) {
05913 ast_log(LOG_WARNING, "PBX exited non-zero\n");
05914 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05915 }
05916 goto quit;
05917 } else {
05918 if (option_verbose > 2)
05919 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05920 sleep(2);
05921 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
05922 if (res < 0)
05923 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05924 else
05925 sleep(1);
05926 res = ast_streamfile(chan, "ss-noservice", chan->language);
05927 if (res >= 0)
05928 ast_waitstream(chan, "");
05929 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05930 ast_hangup(chan);
05931 goto quit;
05932 }
05933 break;
05934 case SIG_FXOLS:
05935 case SIG_FXOGS:
05936 case SIG_FXOKS:
05937
05938 timeout = firstdigittimeout;
05939
05940
05941 if (p->subs[SUB_THREEWAY].owner)
05942 timeout = 999999;
05943 while (len < AST_MAX_EXTENSION-1) {
05944
05945
05946 if (p->immediate)
05947 res = 's';
05948 else
05949 res = ast_waitfordigit(chan, timeout);
05950 timeout = 0;
05951 if (res < 0) {
05952 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05953 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05954 ast_hangup(chan);
05955 goto quit;
05956 } else if (res) {
05957 exten[len++]=res;
05958 exten[len] = '\0';
05959 }
05960 if (!ast_ignore_pattern(chan->context, exten))
05961 tone_zone_play_tone(p->subs[index].dfd, -1);
05962 else
05963 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05964 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05965 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05966 if (getforward) {
05967
05968 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
05969 if (option_verbose > 2)
05970 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05971 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
05972 if (res)
05973 break;
05974 usleep(500000);
05975 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05976 sleep(1);
05977 memset(exten, 0, sizeof(exten));
05978 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05979 len = 0;
05980 getforward = 0;
05981 } else {
05982 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05983 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05984 if (!ast_strlen_zero(p->cid_num)) {
05985 if (!p->hidecallerid)
05986 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05987 else
05988 ast_set_callerid(chan, NULL, NULL, p->cid_num);
05989 }
05990 if (!ast_strlen_zero(p->cid_name)) {
05991 if (!p->hidecallerid)
05992 ast_set_callerid(chan, NULL, p->cid_name, NULL);
05993 }
05994 ast_setstate(chan, AST_STATE_RING);
05995 dahdi_enable_ec(p);
05996 res = ast_pbx_run(chan);
05997 if (res) {
05998 ast_log(LOG_WARNING, "PBX exited non-zero\n");
05999 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06000 }
06001 goto quit;
06002 }
06003 } else {
06004
06005
06006 timeout = matchdigittimeout;
06007 }
06008 } else if (res == 0) {
06009 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06010 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06011 dahdi_wait_event(p->subs[index].dfd);
06012 ast_hangup(chan);
06013 goto quit;
06014 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06015 if (option_verbose > 2)
06016 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06017
06018 p->callwaiting = 0;
06019 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06020 if (res) {
06021 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06022 chan->name, strerror(errno));
06023 }
06024 len = 0;
06025 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06026 memset(exten, 0, sizeof(exten));
06027 timeout = firstdigittimeout;
06028
06029 } else if (!strcmp(exten,ast_pickup_ext())) {
06030
06031
06032
06033
06034 if (index == SUB_REAL) {
06035
06036 if (p->subs[SUB_THREEWAY].owner) {
06037
06038
06039 alloc_sub(p, SUB_CALLWAIT);
06040 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06041 unalloc_sub(p, SUB_THREEWAY);
06042 }
06043 dahdi_enable_ec(p);
06044 if (ast_pickup_call(chan)) {
06045 ast_log(LOG_DEBUG, "No call pickup possible...\n");
06046 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06047 dahdi_wait_event(p->subs[index].dfd);
06048 }
06049 ast_hangup(chan);
06050 goto quit;
06051 } else {
06052 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
06053 ast_hangup(chan);
06054 goto quit;
06055 }
06056
06057 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06058 if (option_verbose > 2)
06059 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06060
06061 p->hidecallerid = 1;
06062 if (chan->cid.cid_num)
06063 free(chan->cid.cid_num);
06064 chan->cid.cid_num = NULL;
06065 if (chan->cid.cid_name)
06066 free(chan->cid.cid_name);
06067 chan->cid.cid_name = NULL;
06068 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06069 if (res) {
06070 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06071 chan->name, strerror(errno));
06072 }
06073 len = 0;
06074 memset(exten, 0, sizeof(exten));
06075 timeout = firstdigittimeout;
06076 } else if (p->callreturn && !strcmp(exten, "*69")) {
06077 res = 0;
06078 if (!ast_strlen_zero(p->lastcid_num)) {
06079 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06080 }
06081 if (!res)
06082 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06083 break;
06084 } else if (!strcmp(exten, "*78")) {
06085
06086 if (option_verbose > 2)
06087 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06088 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06089 "Channel: %s/%d\r\n"
06090 "Status: enabled\r\n", dahdi_chan_name, p->channel);
06091 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06092 p->dnd = 1;
06093 getforward = 0;
06094 memset(exten, 0, sizeof(exten));
06095 len = 0;
06096 } else if (!strcmp(exten, "*79")) {
06097
06098 if (option_verbose > 2)
06099 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06100 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06101 "Channel: %s/%d\r\n"
06102 "Status: disabled\r\n", dahdi_chan_name, p->channel);
06103 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06104 p->dnd = 0;
06105 getforward = 0;
06106 memset(exten, 0, sizeof(exten));
06107 len = 0;
06108 } else if (p->cancallforward && !strcmp(exten, "*72")) {
06109 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06110 getforward = 1;
06111 memset(exten, 0, sizeof(exten));
06112 len = 0;
06113 } else if (p->cancallforward && !strcmp(exten, "*73")) {
06114 if (option_verbose > 2)
06115 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06116 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06117 memset(p->call_forward, 0, sizeof(p->call_forward));
06118 getforward = 0;
06119 memset(exten, 0, sizeof(exten));
06120 len = 0;
06121 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
06122 p->subs[SUB_THREEWAY].owner &&
06123 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06124
06125
06126 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06127 if (option_verbose > 2)
06128 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06129 break;
06130 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06131 if (option_verbose > 2)
06132 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06133 res = ast_db_put("blacklist", p->lastcid_num, "1");
06134 if (!res) {
06135 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06136 memset(exten, 0, sizeof(exten));
06137 len = 0;
06138 }
06139 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06140 if (option_verbose > 2)
06141 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06142
06143 p->hidecallerid = 0;
06144 if (chan->cid.cid_num)
06145 free(chan->cid.cid_num);
06146 chan->cid.cid_num = NULL;
06147 if (chan->cid.cid_name)
06148 free(chan->cid.cid_name);
06149 chan->cid.cid_name = NULL;
06150 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06151 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06152 if (res) {
06153 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06154 chan->name, strerror(errno));
06155 }
06156 len = 0;
06157 memset(exten, 0, sizeof(exten));
06158 timeout = firstdigittimeout;
06159 } else if (!strcmp(exten, "*0")) {
06160 struct ast_channel *nbridge =
06161 p->subs[SUB_THREEWAY].owner;
06162 struct dahdi_pvt *pbridge = NULL;
06163
06164 if (nbridge && ast_bridged_channel(nbridge))
06165 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06166 if (nbridge && pbridge &&
06167 (nbridge->tech == chan_tech) &&
06168 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06169 ISTRUNK(pbridge)) {
06170 int func = DAHDI_FLASH;
06171
06172 p->dop.dialstr[0] = '\0';
06173
06174 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06175 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06176 nbridge->name, strerror(errno));
06177 }
06178 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06179 unalloc_sub(p, SUB_THREEWAY);
06180 p->owner = p->subs[SUB_REAL].owner;
06181 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06182 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06183 ast_hangup(chan);
06184 goto quit;
06185 } else {
06186 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06187 dahdi_wait_event(p->subs[index].dfd);
06188 tone_zone_play_tone(p->subs[index].dfd, -1);
06189 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06190 unalloc_sub(p, SUB_THREEWAY);
06191 p->owner = p->subs[SUB_REAL].owner;
06192 ast_hangup(chan);
06193 goto quit;
06194 }
06195 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06196 ((exten[0] != '*') || (strlen(exten) > 2))) {
06197 if (option_debug)
06198 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
06199 break;
06200 }
06201 if (!timeout)
06202 timeout = gendigittimeout;
06203 if (len && !ast_ignore_pattern(chan->context, exten))
06204 tone_zone_play_tone(p->subs[index].dfd, -1);
06205 }
06206 break;
06207 case SIG_FXSLS:
06208 case SIG_FXSGS:
06209 case SIG_FXSKS:
06210 #ifdef HAVE_PRI
06211 if (p->pri) {
06212
06213 struct ast_frame *f;
06214 int res;
06215 time_t start;
06216
06217 time(&start);
06218 ast_setstate(chan, AST_STATE_RING);
06219 while (time(NULL) < start + 3) {
06220 res = ast_waitfor(chan, 1000);
06221 if (res) {
06222 f = ast_read(chan);
06223 if (!f) {
06224 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06225 ast_hangup(chan);
06226 goto quit;
06227 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06228 res = 1;
06229 } else
06230 res = 0;
06231 ast_frfree(f);
06232 if (res) {
06233 ast_log(LOG_DEBUG, "Got ring!\n");
06234 res = 0;
06235 break;
06236 }
06237 }
06238 }
06239 }
06240 #endif
06241
06242 if (p->use_smdi && p->smdi_iface) {
06243 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06244
06245 if (smdi_msg != NULL) {
06246 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06247
06248 if (smdi_msg->type == 'B')
06249 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06250 else if (smdi_msg->type == 'N')
06251 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06252
06253 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06254 } else {
06255 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06256 }
06257 }
06258
06259 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06260 number = smdi_msg->calling_st;
06261
06262
06263
06264
06265 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06266
06267 if (p->cid_signalling == CID_SIG_DTMF) {
06268 int i = 0;
06269 cs = NULL;
06270 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06271 "channel %s\n", chan->name);
06272 dahdi_setlinear(p->subs[index].dfd, 0);
06273 res = 2000;
06274 for (;;) {
06275 struct ast_frame *f;
06276 res = ast_waitfor(chan, res);
06277 if (res <= 0) {
06278 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06279 "Exiting simple switch\n");
06280 ast_hangup(chan);
06281 goto quit;
06282 }
06283 f = ast_read(chan);
06284 if (!f)
06285 break;
06286 if (f->frametype == AST_FRAME_DTMF) {
06287 dtmfbuf[i++] = f->subclass;
06288 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06289 res = 2000;
06290 }
06291 ast_frfree(f);
06292 if (chan->_state == AST_STATE_RING ||
06293 chan->_state == AST_STATE_RINGING)
06294 break;
06295 }
06296 dtmfbuf[i] = '\0';
06297 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06298
06299 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06300 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06301 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
06302 dtmfcid, flags);
06303
06304 if (!ast_strlen_zero(dtmfcid))
06305 number = dtmfcid;
06306 else
06307 number = NULL;
06308
06309 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06310 cs = callerid_new(p->cid_signalling);
06311 if (cs) {
06312 samples = 0;
06313 #if 1
06314 bump_gains(p);
06315 #endif
06316
06317 dahdi_setlinear(p->subs[index].dfd, 0);
06318
06319
06320 for (;;) {
06321 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06322 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06323 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06324 callerid_free(cs);
06325 ast_hangup(chan);
06326 goto quit;
06327 }
06328 if (i & DAHDI_IOMUX_SIGEVENT) {
06329 res = dahdi_get_event(p->subs[index].dfd);
06330 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06331
06332 if (p->cid_signalling == CID_SIG_V23_JP) {
06333 #ifdef DAHDI_EVENT_RINGBEGIN
06334 if (res == DAHDI_EVENT_RINGBEGIN) {
06335 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06336 usleep(1);
06337 }
06338 #endif
06339 } else {
06340 res = 0;
06341 break;
06342 }
06343 } else if (i & DAHDI_IOMUX_READ) {
06344 res = read(p->subs[index].dfd, buf, sizeof(buf));
06345 if (res < 0) {
06346 if (errno != ELAST) {
06347 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06348 callerid_free(cs);
06349 ast_hangup(chan);
06350 goto quit;
06351 }
06352 break;
06353 }
06354 samples += res;
06355
06356 if (p->cid_signalling == CID_SIG_V23_JP) {
06357 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06358 } else {
06359 res = callerid_feed(cs, buf, res, AST_LAW(p));
06360 }
06361
06362 if (res < 0) {
06363 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06364 break;
06365 } else if (res)
06366 break;
06367 else if (samples > (8000 * 10))
06368 break;
06369 }
06370 }
06371 if (res == 1) {
06372 callerid_get(cs, &name, &number, &flags);
06373 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06374 }
06375
06376 if (p->cid_signalling == CID_SIG_V23_JP) {
06377 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06378 usleep(1);
06379 res = 4000;
06380 } else {
06381
06382
06383 res = 2000;
06384 }
06385
06386 for (;;) {
06387 struct ast_frame *f;
06388 res = ast_waitfor(chan, res);
06389 if (res <= 0) {
06390 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06391 "Exiting simple switch\n");
06392 ast_hangup(chan);
06393 goto quit;
06394 }
06395 if (!(f = ast_read(chan))) {
06396 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06397 ast_hangup(chan);
06398 goto quit;
06399 }
06400 ast_frfree(f);
06401 if (chan->_state == AST_STATE_RING ||
06402 chan->_state == AST_STATE_RINGING)
06403 break;
06404 }
06405
06406
06407
06408 if (p->usedistinctiveringdetection == 1) {
06409 len = 0;
06410 distMatches = 0;
06411
06412 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06413 curRingData[receivedRingT] = 0;
06414 receivedRingT = 0;
06415 counter = 0;
06416 counter1 = 0;
06417
06418 if (strcmp(p->context,p->defcontext) != 0) {
06419 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06420 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06421 }
06422
06423 for (;;) {
06424 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06425 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06426 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06427 callerid_free(cs);
06428 ast_hangup(chan);
06429 goto quit;
06430 }
06431 if (i & DAHDI_IOMUX_SIGEVENT) {
06432 res = dahdi_get_event(p->subs[index].dfd);
06433 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06434 res = 0;
06435
06436
06437 curRingData[receivedRingT] = p->ringt;
06438
06439 if (p->ringt < p->ringt_base/2)
06440 break;
06441
06442
06443 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06444 break;
06445 } else if (i & DAHDI_IOMUX_READ) {
06446 res = read(p->subs[index].dfd, buf, sizeof(buf));
06447 if (res < 0) {
06448 if (errno != ELAST) {
06449 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06450 callerid_free(cs);
06451 ast_hangup(chan);
06452 goto quit;
06453 }
06454 break;
06455 }
06456 if (p->ringt)
06457 p->ringt--;
06458 if (p->ringt == 1) {
06459 res = -1;
06460 break;
06461 }
06462 }
06463 }
06464 if (option_verbose > 2)
06465
06466 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06467
06468 for (counter = 0; counter < 3; counter++) {
06469
06470
06471 distMatches = 0;
06472 for (counter1 = 0; counter1 < 3; counter1++) {
06473 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06474 (p->drings.ringnum[counter].ring[counter1]-10)) {
06475 distMatches++;
06476 }
06477 }
06478 if (distMatches == 3) {
06479
06480 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06481 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06482 if (option_verbose > 2)
06483 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06484 break;
06485 }
06486 }
06487 }
06488
06489 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06490 #if 1
06491 restore_gains(p);
06492 #endif
06493 } else
06494 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06495 } else {
06496 ast_log(LOG_WARNING, "Channel %s in prering "
06497 "state, but I have nothing to do. "
06498 "Terminating simple switch, should be "
06499 "restarted by the actual ring.\n",
06500 chan->name);
06501 ast_hangup(chan);
06502 goto quit;
06503 }
06504 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06505
06506 cs = callerid_new(p->cid_signalling);
06507 if (cs) {
06508 #if 1
06509 bump_gains(p);
06510 #endif
06511 samples = 0;
06512 len = 0;
06513 distMatches = 0;
06514
06515 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06516 curRingData[receivedRingT] = 0;
06517 receivedRingT = 0;
06518 counter = 0;
06519 counter1 = 0;
06520
06521 if (strcmp(p->context,p->defcontext) != 0) {
06522 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06523 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06524 }
06525
06526
06527 dahdi_setlinear(p->subs[index].dfd, 0);
06528 for (;;) {
06529 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06530 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06531 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06532 callerid_free(cs);
06533 ast_hangup(chan);
06534 goto quit;
06535 }
06536 if (i & DAHDI_IOMUX_SIGEVENT) {
06537 res = dahdi_get_event(p->subs[index].dfd);
06538 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06539
06540 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06541 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06542 p->polarity = POLARITY_IDLE;
06543 callerid_free(cs);
06544 ast_hangup(chan);
06545 goto quit;
06546 }
06547 res = 0;
06548
06549
06550 curRingData[receivedRingT] = p->ringt;
06551
06552 if (p->ringt < p->ringt_base/2)
06553 break;
06554
06555
06556 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06557 break;
06558 } else if (i & DAHDI_IOMUX_READ) {
06559 res = read(p->subs[index].dfd, buf, sizeof(buf));
06560 if (res < 0) {
06561 if (errno != ELAST) {
06562 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06563 callerid_free(cs);
06564 ast_hangup(chan);
06565 goto quit;
06566 }
06567 break;
06568 }
06569 if (p->ringt)
06570 p->ringt--;
06571 if (p->ringt == 1) {
06572 res = -1;
06573 break;
06574 }
06575 samples += res;
06576 res = callerid_feed(cs, buf, res, AST_LAW(p));
06577 if (res < 0) {
06578 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06579 break;
06580 } else if (res)
06581 break;
06582 else if (samples > (8000 * 10))
06583 break;
06584 }
06585 }
06586 if (res == 1) {
06587 callerid_get(cs, &name, &number, &flags);
06588 if (option_debug)
06589 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06590 }
06591 if (distinctiveringaftercid == 1) {
06592
06593 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06594 curRingData[receivedRingT] = 0;
06595 }
06596 receivedRingT = 0;
06597 if (option_verbose > 2)
06598 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06599 for (;;) {
06600 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06601 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06602 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06603 callerid_free(cs);
06604 ast_hangup(chan);
06605 goto quit;
06606 }
06607 if (i & DAHDI_IOMUX_SIGEVENT) {
06608 res = dahdi_get_event(p->subs[index].dfd);
06609 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06610 res = 0;
06611
06612
06613 curRingData[receivedRingT] = p->ringt;
06614
06615 if (p->ringt < p->ringt_base/2)
06616 break;
06617
06618
06619 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06620 break;
06621 } else if (i & DAHDI_IOMUX_READ) {
06622 res = read(p->subs[index].dfd, buf, sizeof(buf));
06623 if (res < 0) {
06624 if (errno != ELAST) {
06625 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06626 callerid_free(cs);
06627 ast_hangup(chan);
06628 goto quit;
06629 }
06630 break;
06631 }
06632 if (p->ringt)
06633 p->ringt--;
06634 if (p->ringt == 1) {
06635 res = -1;
06636 break;
06637 }
06638 }
06639 }
06640 }
06641 if (p->usedistinctiveringdetection == 1) {
06642 if (option_verbose > 2)
06643
06644 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06645
06646 for (counter = 0; counter < 3; counter++) {
06647
06648
06649 if (option_verbose > 2)
06650
06651 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06652 p->drings.ringnum[counter].ring[0],
06653 p->drings.ringnum[counter].ring[1],
06654 p->drings.ringnum[counter].ring[2]);
06655 distMatches = 0;
06656 for (counter1 = 0; counter1 < 3; counter1++) {
06657 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06658 (p->drings.ringnum[counter].ring[counter1]-10)) {
06659 distMatches++;
06660 }
06661 }
06662 if (distMatches == 3) {
06663
06664 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06665 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06666 if (option_verbose > 2)
06667 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06668 break;
06669 }
06670 }
06671 }
06672
06673 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06674 #if 1
06675 restore_gains(p);
06676 #endif
06677 if (res < 0) {
06678 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06679 }
06680 } else
06681 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06682 }
06683 else
06684 cs = NULL;
06685
06686 if (number)
06687 ast_shrink_phone_number(number);
06688 ast_set_callerid(chan, number, name, number);
06689
06690 if (smdi_msg)
06691 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06692
06693 if (cs)
06694 callerid_free(cs);
06695
06696 ast_setstate(chan, AST_STATE_RING);
06697 chan->rings = 1;
06698 p->ringt = p->ringt_base;
06699 res = ast_pbx_run(chan);
06700 if (res) {
06701 ast_hangup(chan);
06702 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06703 }
06704 goto quit;
06705 default:
06706 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06707 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06708 if (res < 0)
06709 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06710 }
06711 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06712 if (res < 0)
06713 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06714 ast_hangup(chan);
06715 quit:
06716 ast_mutex_lock(&ss_thread_lock);
06717 ss_thread_count--;
06718 ast_cond_signal(&ss_thread_complete);
06719 ast_mutex_unlock(&ss_thread_lock);
06720 return NULL;
06721 }
06722
06723
06724 static int dahdi_destroy_channel_bynum(int channel)
06725 {
06726 struct dahdi_pvt *tmp = NULL;
06727 struct dahdi_pvt *prev = NULL;
06728
06729 tmp = iflist;
06730 while (tmp) {
06731 if (tmp->channel == channel) {
06732 int x = DAHDI_FLASH;
06733 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06734 destroy_channel(prev, tmp, 1);
06735 ast_module_unref(ast_module_info->self);
06736 return RESULT_SUCCESS;
06737 }
06738 prev = tmp;
06739 tmp = tmp->next;
06740 }
06741 return RESULT_FAILURE;
06742 }
06743
06744 static int handle_init_event(struct dahdi_pvt *i, int event)
06745 {
06746 int res;
06747 pthread_t threadid;
06748 pthread_attr_t attr;
06749 struct ast_channel *chan;
06750 pthread_attr_init(&attr);
06751 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06752
06753 switch (event) {
06754 case DAHDI_EVENT_NONE:
06755 case DAHDI_EVENT_BITSCHANGED:
06756 break;
06757 case DAHDI_EVENT_WINKFLASH:
06758 case DAHDI_EVENT_RINGOFFHOOK:
06759 if (i->inalarm) break;
06760 if (i->radio) break;
06761
06762 switch (i->sig) {
06763 case SIG_FXOLS:
06764 case SIG_FXOGS:
06765 case SIG_FXOKS:
06766 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06767 if (res && (errno == EBUSY))
06768 break;
06769 if (i->cidspill) {
06770
06771 free(i->cidspill);
06772 i->cidspill = NULL;
06773 }
06774 if (i->immediate) {
06775 dahdi_enable_ec(i);
06776
06777 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06778 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06779 if (!chan) {
06780 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06781 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06782 if (res < 0)
06783 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06784 }
06785 } else {
06786
06787 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06788 if (chan) {
06789 if (has_voicemail(i))
06790 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06791 else
06792 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06793 if (res < 0)
06794 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06795 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06796 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06797 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06798 if (res < 0)
06799 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06800 ast_hangup(chan);
06801 }
06802 } else
06803 ast_log(LOG_WARNING, "Unable to create channel\n");
06804 }
06805 break;
06806 case SIG_FXSLS:
06807 case SIG_FXSGS:
06808 case SIG_FXSKS:
06809 i->ringt = i->ringt_base;
06810
06811 case SIG_EMWINK:
06812 case SIG_FEATD:
06813 case SIG_FEATDMF:
06814 case SIG_FEATDMF_TA:
06815 case SIG_E911:
06816 case SIG_FGC_CAMA:
06817 case SIG_FGC_CAMAMF:
06818 case SIG_FEATB:
06819 case SIG_EM:
06820 case SIG_EM_E1:
06821 case SIG_SFWINK:
06822 case SIG_SF_FEATD:
06823 case SIG_SF_FEATDMF:
06824 case SIG_SF_FEATB:
06825 case SIG_SF:
06826
06827 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06828 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06829 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06830 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06831 if (res < 0)
06832 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06833 ast_hangup(chan);
06834 } else if (!chan) {
06835 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06836 }
06837 break;
06838 default:
06839 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06840 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06841 if (res < 0)
06842 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06843 return -1;
06844 }
06845 break;
06846 case DAHDI_EVENT_NOALARM:
06847 i->inalarm = 0;
06848 if (!i->unknown_alarm) {
06849 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06850 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06851 "Channel: %d\r\n", i->channel);
06852 } else {
06853 i->unknown_alarm = 0;
06854 }
06855 break;
06856 case DAHDI_EVENT_ALARM:
06857 i->inalarm = 1;
06858 res = get_alarms(i);
06859 handle_alarms(i, res);
06860
06861 case DAHDI_EVENT_ONHOOK:
06862 if (i->radio)
06863 break;
06864
06865 switch (i->sig) {
06866 case SIG_FXOLS:
06867 case SIG_FXOGS:
06868 case SIG_FEATD:
06869 case SIG_FEATDMF:
06870 case SIG_FEATDMF_TA:
06871 case SIG_E911:
06872 case SIG_FGC_CAMA:
06873 case SIG_FGC_CAMAMF:
06874 case SIG_FEATB:
06875 case SIG_EM:
06876 case SIG_EM_E1:
06877 case SIG_EMWINK:
06878 case SIG_SF_FEATD:
06879 case SIG_SF_FEATDMF:
06880 case SIG_SF_FEATB:
06881 case SIG_SF:
06882 case SIG_SFWINK:
06883 case SIG_FXSLS:
06884 case SIG_FXSGS:
06885 case SIG_FXSKS:
06886 case SIG_GR303FXSKS:
06887 dahdi_disable_ec(i);
06888 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06889 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06890 break;
06891 case SIG_GR303FXOKS:
06892 case SIG_FXOKS:
06893 dahdi_disable_ec(i);
06894
06895 #ifdef ZHONE_HACK
06896 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06897 usleep(1);
06898 #endif
06899 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06900 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06901 break;
06902 case SIG_PRI:
06903 dahdi_disable_ec(i);
06904 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06905 break;
06906 default:
06907 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06908 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06909 return -1;
06910 }
06911 break;
06912 case DAHDI_EVENT_POLARITY:
06913 switch (i->sig) {
06914 case SIG_FXSLS:
06915 case SIG_FXSKS:
06916 case SIG_FXSGS:
06917
06918
06919
06920
06921 if (i->hanguponpolarityswitch)
06922 i->polarity = POLARITY_REV;
06923
06924 if (i->cid_start == CID_START_POLARITY) {
06925 i->polarity = POLARITY_REV;
06926 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06927 "CID detection on channel %d\n",
06928 i->channel);
06929 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06930 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06931 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06932 }
06933 }
06934 break;
06935 default:
06936 ast_log(LOG_WARNING, "handle_init_event detected "
06937 "polarity reversal on non-FXO (SIG_FXS) "
06938 "interface %d\n", i->channel);
06939 }
06940 break;
06941 case DAHDI_EVENT_REMOVED:
06942 ast_log(LOG_NOTICE,
06943 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
06944 i->channel);
06945 dahdi_destroy_channel_bynum(i->channel);
06946 break;
06947 }
06948 pthread_attr_destroy(&attr);
06949 return 0;
06950 }
06951
06952 static void *do_monitor(void *data)
06953 {
06954 int count, res, res2, spoint, pollres=0;
06955 struct dahdi_pvt *i;
06956 struct dahdi_pvt *last = NULL;
06957 time_t thispass = 0, lastpass = 0;
06958 int found;
06959 char buf[1024];
06960 struct pollfd *pfds=NULL;
06961 int lastalloc = -1;
06962
06963
06964
06965 #if 0
06966 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06967 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06968 return NULL;
06969 }
06970 ast_log(LOG_DEBUG, "Monitor starting...\n");
06971 #endif
06972 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
06973
06974 for (;;) {
06975
06976 ast_mutex_lock(&iflock);
06977 if (!pfds || (lastalloc != ifcount)) {
06978 if (pfds) {
06979 free(pfds);
06980 pfds = NULL;
06981 }
06982 if (ifcount) {
06983 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06984 ast_mutex_unlock(&iflock);
06985 return NULL;
06986 }
06987 }
06988 lastalloc = ifcount;
06989 }
06990
06991
06992 count = 0;
06993 i = iflist;
06994 while (i) {
06995 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
06996 if (!i->owner && !i->subs[SUB_REAL].owner) {
06997
06998 pfds[count].fd = i->subs[SUB_REAL].dfd;
06999 pfds[count].events = POLLPRI;
07000 pfds[count].revents = 0;
07001
07002 if (i->cidspill)
07003 pfds[count].events |= POLLIN;
07004 count++;
07005 }
07006 }
07007 i = i->next;
07008 }
07009
07010 ast_mutex_unlock(&iflock);
07011
07012 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07013 pthread_testcancel();
07014
07015 res = poll(pfds, count, 1000);
07016 pthread_testcancel();
07017 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07018
07019
07020 if (res < 0) {
07021 if ((errno != EAGAIN) && (errno != EINTR))
07022 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07023 continue;
07024 }
07025
07026
07027 ast_mutex_lock(&iflock);
07028 found = 0;
07029 spoint = 0;
07030 lastpass = thispass;
07031 thispass = time(NULL);
07032 i = iflist;
07033 while (i) {
07034 if (thispass != lastpass) {
07035 if (!found && ((i == last) || ((i == iflist) && !last))) {
07036 last = i;
07037 if (last) {
07038 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07039 (last->sig & __DAHDI_SIG_FXO)) {
07040 res = ast_app_has_voicemail(last->mailbox, NULL);
07041 if (last->msgstate != res) {
07042 int x;
07043 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07044 x = DAHDI_FLUSH_BOTH;
07045 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07046 if (res2)
07047 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07048 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07049
07050 x = 4000;
07051 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07052 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07053 last->cidpos = 0;
07054 last->msgstate = res;
07055 last->onhooktime = thispass;
07056 }
07057 found ++;
07058 }
07059 }
07060 last = last->next;
07061 }
07062 }
07063 }
07064 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07065 if (i->radio && !i->owner)
07066 {
07067 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07068 if (res)
07069 {
07070 if (option_debug)
07071 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07072
07073 ast_mutex_unlock(&iflock);
07074 handle_init_event(i, res);
07075 ast_mutex_lock(&iflock);
07076 }
07077 i = i->next;
07078 continue;
07079 }
07080 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07081 if (pollres & POLLIN) {
07082 if (i->owner || i->subs[SUB_REAL].owner) {
07083 #ifdef HAVE_PRI
07084 if (!i->pri)
07085 #endif
07086 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07087 i = i->next;
07088 continue;
07089 }
07090 if (!i->cidspill) {
07091 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07092 i = i->next;
07093 continue;
07094 }
07095 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07096 if (res > 0) {
07097
07098 if (res > i->cidlen - i->cidpos)
07099 res = i->cidlen - i->cidpos;
07100 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07101 if (res2 > 0) {
07102 i->cidpos += res2;
07103 if (i->cidpos >= i->cidlen) {
07104 free(i->cidspill);
07105 i->cidspill = 0;
07106 i->cidpos = 0;
07107 i->cidlen = 0;
07108 }
07109 } else {
07110 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07111 i->msgstate = -1;
07112 }
07113 } else {
07114 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07115 }
07116 }
07117 if (pollres & POLLPRI) {
07118 if (i->owner || i->subs[SUB_REAL].owner) {
07119 #ifdef HAVE_PRI
07120 if (!i->pri)
07121 #endif
07122 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07123 i = i->next;
07124 continue;
07125 }
07126 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07127 if (option_debug)
07128 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07129
07130 ast_mutex_unlock(&iflock);
07131 handle_init_event(i, res);
07132 ast_mutex_lock(&iflock);
07133 }
07134 }
07135 i=i->next;
07136 }
07137 ast_mutex_unlock(&iflock);
07138 }
07139
07140 return NULL;
07141
07142 }
07143
07144 static int restart_monitor(void)
07145 {
07146 pthread_attr_t attr;
07147 pthread_attr_init(&attr);
07148 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07149
07150 if (monitor_thread == AST_PTHREADT_STOP)
07151 return 0;
07152 ast_mutex_lock(&monlock);
07153 if (monitor_thread == pthread_self()) {
07154 ast_mutex_unlock(&monlock);
07155 ast_log(LOG_WARNING, "Cannot kill myself\n");
07156 return -1;
07157 }
07158 if (monitor_thread != AST_PTHREADT_NULL) {
07159
07160 pthread_kill(monitor_thread, SIGURG);
07161 } else {
07162
07163 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07164 ast_mutex_unlock(&monlock);
07165 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07166 pthread_attr_destroy(&attr);
07167 return -1;
07168 }
07169 }
07170 ast_mutex_unlock(&monlock);
07171 pthread_attr_destroy(&attr);
07172 return 0;
07173 }
07174
07175 #ifdef HAVE_PRI
07176 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07177 {
07178 int x;
07179 int trunkgroup;
07180
07181 trunkgroup = pris[*span].mastertrunkgroup;
07182 if (trunkgroup) {
07183
07184 for (x = 0; x < NUM_SPANS; x++) {
07185 if (pris[x].trunkgroup == trunkgroup) {
07186 *span = x;
07187 return 0;
07188 }
07189 }
07190 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07191 *span = -1;
07192 } else {
07193 if (pris[*span].trunkgroup) {
07194 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07195 *span = -1;
07196 } else if (pris[*span].mastertrunkgroup) {
07197 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07198 *span = -1;
07199 } else {
07200 if (si->totalchans == 31) {
07201
07202 pris[*span].dchannels[0] = 16 + offset;
07203 } else if (si->totalchans == 24) {
07204
07205 pris[*span].dchannels[0] = 24 + offset;
07206 } else if (si->totalchans == 3) {
07207
07208 pris[*span].dchannels[0] = 3 + offset;
07209 } else {
07210 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);
07211 *span = -1;
07212 return 0;
07213 }
07214 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07215 pris[*span].offset = offset;
07216 pris[*span].span = *span + 1;
07217 }
07218 }
07219 return 0;
07220 }
07221
07222 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07223 {
07224 struct dahdi_spaninfo si;
07225 struct dahdi_params p;
07226 int fd;
07227 int span;
07228 int ospan=0;
07229 int x,y;
07230 for (x = 0; x < NUM_SPANS; x++) {
07231 if (pris[x].trunkgroup == trunkgroup) {
07232 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07233 return -1;
07234 }
07235 }
07236 for (y = 0; y < NUM_DCHANS; y++) {
07237 if (!channels[y])
07238 break;
07239 memset(&si, 0, sizeof(si));
07240 memset(&p, 0, sizeof(p));
07241 fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07242 if (fd < 0) {
07243 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07244 return -1;
07245 }
07246 x = channels[y];
07247 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07248 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07249 close(fd);
07250 return -1;
07251 }
07252 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07253 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07254 return -1;
07255 }
07256 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07257 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07258 close(fd);
07259 return -1;
07260 }
07261 span = p.spanno - 1;
07262 if (pris[span].trunkgroup) {
07263 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07264 close(fd);
07265 return -1;
07266 }
07267 if (pris[span].pvts[0]) {
07268 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07269 close(fd);
07270 return -1;
07271 }
07272 if (!y) {
07273 pris[span].trunkgroup = trunkgroup;
07274 pris[span].offset = channels[y] - p.chanpos;
07275 ospan = span;
07276 }
07277 pris[ospan].dchannels[y] = channels[y];
07278 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07279 pris[span].span = span + 1;
07280 close(fd);
07281 }
07282 return 0;
07283 }
07284
07285 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07286 {
07287 if (pris[span].mastertrunkgroup) {
07288 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);
07289 return -1;
07290 }
07291 pris[span].mastertrunkgroup = trunkgroup;
07292 pris[span].prilogicalspan = logicalspan;
07293 return 0;
07294 }
07295
07296 #endif
07297
07298 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07299 {
07300
07301 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
07302 char fn[80];
07303 #if 1
07304 struct dahdi_bufferinfo bi;
07305 #endif
07306 int res;
07307 int span=0;
07308 int here = 0;
07309 int x;
07310 struct dahdi_pvt **wlist;
07311 struct dahdi_pvt **wend;
07312 struct dahdi_params p;
07313
07314 wlist = &iflist;
07315 wend = &ifend;
07316
07317 #ifdef HAVE_PRI
07318 if (pri) {
07319 wlist = &pri->crvs;
07320 wend = &pri->crvend;
07321 }
07322 #endif
07323
07324 tmp2 = *wlist;
07325 prev = NULL;
07326
07327 while (tmp2) {
07328 if (!tmp2->destroy) {
07329 if (tmp2->channel == channel) {
07330 tmp = tmp2;
07331 here = 1;
07332 break;
07333 }
07334 if (tmp2->channel > channel) {
07335 break;
07336 }
07337 }
07338 prev = tmp2;
07339 tmp2 = tmp2->next;
07340 }
07341
07342 if (!here && reloading != 1) {
07343 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07344 if (tmp)
07345 free(tmp);
07346 return NULL;
07347 }
07348 ast_mutex_init(&tmp->lock);
07349 ifcount++;
07350 for (x = 0; x < 3; x++)
07351 tmp->subs[x].dfd = -1;
07352 tmp->channel = channel;
07353 }
07354
07355 if (tmp) {
07356 int chan_sig = conf->chan.sig;
07357 if (!here) {
07358 if ((channel != CHAN_PSEUDO) && !pri) {
07359 int count = 0;
07360 snprintf(fn, sizeof(fn), "%d", channel);
07361
07362 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07363 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
07364 usleep(1);
07365 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07366 count++;
07367 }
07368
07369 if (tmp->subs[SUB_REAL].dfd < 0) {
07370 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);
07371 destroy_dahdi_pvt(&tmp);
07372 return NULL;
07373 }
07374 memset(&p, 0, sizeof(p));
07375 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07376 if (res < 0) {
07377 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07378 destroy_dahdi_pvt(&tmp);
07379 return NULL;
07380 }
07381 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07382 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
07383 destroy_dahdi_pvt(&tmp);
07384 return NULL;
07385 }
07386 tmp->law = p.curlaw;
07387 tmp->span = p.spanno;
07388 span = p.spanno - 1;
07389 } else {
07390 if (channel == CHAN_PSEUDO)
07391 chan_sig = 0;
07392 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07393 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07394 return NULL;
07395 }
07396 }
07397 #ifdef HAVE_PRI
07398 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07399 int offset;
07400 int myswitchtype;
07401 int matchesdchan;
07402 int x,y;
07403 offset = 0;
07404 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07405 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07406 destroy_dahdi_pvt(&tmp);
07407 return NULL;
07408 }
07409 if (span >= NUM_SPANS) {
07410 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07411 destroy_dahdi_pvt(&tmp);
07412 return NULL;
07413 } else {
07414 struct dahdi_spaninfo si;
07415 si.spanno = 0;
07416 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07417 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07418 destroy_dahdi_pvt(&tmp);
07419 return NULL;
07420 }
07421
07422 tmp->logicalspan = pris[span].prilogicalspan;
07423 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07424 if (span < 0) {
07425 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07426 destroy_dahdi_pvt(&tmp);
07427 return NULL;
07428 }
07429 if (chan_sig == SIG_PRI)
07430 myswitchtype = conf->pri.switchtype;
07431 else
07432 myswitchtype = PRI_SWITCH_GR303_TMC;
07433
07434 matchesdchan=0;
07435 for (x = 0; x < NUM_SPANS; x++) {
07436 for (y = 0; y < NUM_DCHANS; y++) {
07437 if (pris[x].dchannels[y] == tmp->channel) {
07438 matchesdchan = 1;
07439 break;
07440 }
07441 }
07442 }
07443 offset = p.chanpos;
07444 if (!matchesdchan) {
07445 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07446 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07447 destroy_dahdi_pvt(&tmp);
07448 return NULL;
07449 }
07450 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07451 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07452 destroy_dahdi_pvt(&tmp);
07453 return NULL;
07454 }
07455 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07456 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07457 destroy_dahdi_pvt(&tmp);
07458 return NULL;
07459 }
07460 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07461 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07462 destroy_dahdi_pvt(&tmp);
07463 return NULL;
07464 }
07465 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07466 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07467 destroy_dahdi_pvt(&tmp);
07468 return NULL;
07469 }
07470 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07471 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07472 destroy_dahdi_pvt(&tmp);
07473 return NULL;
07474 }
07475 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07476 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07477 destroy_dahdi_pvt(&tmp);
07478 return NULL;
07479 }
07480 if (pris[span].numchans >= MAX_CHANNELS) {
07481 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07482 pris[span].trunkgroup);
07483 destroy_dahdi_pvt(&tmp);
07484 return NULL;
07485 }
07486 pris[span].nodetype = conf->pri.nodetype;
07487 pris[span].switchtype = myswitchtype;
07488 pris[span].nsf = conf->pri.nsf;
07489 pris[span].dialplan = conf->pri.dialplan;
07490 pris[span].localdialplan = conf->pri.localdialplan;
07491 pris[span].pvts[pris[span].numchans++] = tmp;
07492 pris[span].minunused = conf->pri.minunused;
07493 pris[span].minidle = conf->pri.minidle;
07494 pris[span].overlapdial = conf->pri.overlapdial;
07495 #ifdef HAVE_PRI_INBANDDISCONNECT
07496 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07497 #endif
07498 pris[span].facilityenable = conf->pri.facilityenable;
07499 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07500 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07501 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07502 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07503 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07504 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07505 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07506 pris[span].resetinterval = conf->pri.resetinterval;
07507
07508 tmp->pri = &pris[span];
07509 tmp->prioffset = offset;
07510 tmp->call = NULL;
07511 } else {
07512 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07513 destroy_dahdi_pvt(&tmp);
07514 return NULL;
07515 }
07516 }
07517 } else {
07518 tmp->prioffset = 0;
07519 }
07520 #endif
07521 } else {
07522 chan_sig = tmp->sig;
07523 memset(&p, 0, sizeof(p));
07524 if (tmp->subs[SUB_REAL].dfd > -1)
07525 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07526 }
07527
07528 switch (chan_sig) {
07529 case SIG_FXSKS:
07530 case SIG_FXSLS:
07531 case SIG_EM:
07532 case SIG_EM_E1:
07533 case SIG_EMWINK:
07534 case SIG_FEATD:
07535 case SIG_FEATDMF:
07536 case SIG_FEATDMF_TA:
07537 case SIG_FEATB:
07538 case SIG_E911:
07539 case SIG_SF:
07540 case SIG_SFWINK:
07541 case SIG_FGC_CAMA:
07542 case SIG_FGC_CAMAMF:
07543 case SIG_SF_FEATD:
07544 case SIG_SF_FEATDMF:
07545 case SIG_SF_FEATB:
07546 p.starttime = 250;
07547 break;
07548 }
07549
07550 if (tmp->radio) {
07551
07552 p.channo = channel;
07553 p.rxwinktime = 1;
07554 p.rxflashtime = 1;
07555 p.starttime = 1;
07556 p.debouncetime = 5;
07557 }
07558 if (!tmp->radio) {
07559 p.channo = channel;
07560
07561 if (conf->timing.prewinktime >= 0)
07562 p.prewinktime = conf->timing.prewinktime;
07563 if (conf->timing.preflashtime >= 0)
07564 p.preflashtime = conf->timing.preflashtime;
07565 if (conf->timing.winktime >= 0)
07566 p.winktime = conf->timing.winktime;
07567 if (conf->timing.flashtime >= 0)
07568 p.flashtime = conf->timing.flashtime;
07569 if (conf->timing.starttime >= 0)
07570 p.starttime = conf->timing.starttime;
07571 if (conf->timing.rxwinktime >= 0)
07572 p.rxwinktime = conf->timing.rxwinktime;
07573 if (conf->timing.rxflashtime >= 0)
07574 p.rxflashtime = conf->timing.rxflashtime;
07575 if (conf->timing.debouncetime >= 0)
07576 p.debouncetime = conf->timing.debouncetime;
07577 }
07578
07579
07580 if (tmp->subs[SUB_REAL].dfd >= 0)
07581 {
07582 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07583 if (res < 0) {
07584 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07585 destroy_dahdi_pvt(&tmp);
07586 return NULL;
07587 }
07588 }
07589 #if 1
07590 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07591 memset(&bi, 0, sizeof(bi));
07592 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07593 if (!res) {
07594 bi.txbufpolicy = conf->chan.buf_policy;
07595 bi.rxbufpolicy = conf->chan.buf_policy;
07596 bi.numbufs = conf->chan.buf_no;
07597 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07598 if (res < 0) {
07599 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07600 }
07601 } else
07602 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07603 }
07604 #endif
07605 tmp->immediate = conf->chan.immediate;
07606 tmp->transfertobusy = conf->chan.transfertobusy;
07607 tmp->sig = chan_sig;
07608 tmp->outsigmod = conf->chan.outsigmod;
07609 tmp->ringt_base = ringt_base;
07610 tmp->firstradio = 0;
07611 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07612 tmp->permcallwaiting = conf->chan.callwaiting;
07613 else
07614 tmp->permcallwaiting = 0;
07615
07616 tmp->destroy = 0;
07617 tmp->drings = drings;
07618 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07619 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07620 tmp->threewaycalling = conf->chan.threewaycalling;
07621 tmp->adsi = conf->chan.adsi;
07622 tmp->use_smdi = conf->chan.use_smdi;
07623 tmp->permhidecallerid = conf->chan.hidecallerid;
07624 tmp->callreturn = conf->chan.callreturn;
07625 tmp->echocancel = conf->chan.echocancel;
07626 tmp->echotraining = conf->chan.echotraining;
07627 tmp->pulse = conf->chan.pulse;
07628 if (tmp->echocancel)
07629 tmp->echocanbridged = conf->chan.echocanbridged;
07630 else {
07631 if (conf->chan.echocanbridged)
07632 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07633 tmp->echocanbridged = 0;
07634 }
07635 tmp->busydetect = conf->chan.busydetect;
07636 tmp->busycount = conf->chan.busycount;
07637 tmp->busycompare = conf->chan.busycompare;
07638 tmp->busytonelength = conf->chan.busytonelength;
07639 tmp->busyquietlength = conf->chan.busyquietlength;
07640 tmp->busyfuzziness = conf->chan.busyfuzziness;
07641 tmp->silencethreshold = conf->chan.silencethreshold;
07642 tmp->callprogress = conf->chan.callprogress;
07643 tmp->cancallforward = conf->chan.cancallforward;
07644 tmp->dtmfrelax = conf->chan.dtmfrelax;
07645 tmp->callwaiting = tmp->permcallwaiting;
07646 tmp->hidecallerid = tmp->permhidecallerid;
07647 tmp->channel = channel;
07648 tmp->stripmsd = conf->chan.stripmsd;
07649 tmp->use_callerid = conf->chan.use_callerid;
07650 tmp->cid_signalling = conf->chan.cid_signalling;
07651 tmp->cid_start = conf->chan.cid_start;
07652 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07653 tmp->restrictcid = conf->chan.restrictcid;
07654 tmp->use_callingpres = conf->chan.use_callingpres;
07655 tmp->priindication_oob = conf->chan.priindication_oob;
07656 tmp->priexclusive = conf->chan.priexclusive;
07657 if (tmp->usedistinctiveringdetection) {
07658 if (!tmp->use_callerid) {
07659 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07660 tmp->use_callerid = 1;
07661 }
07662 }
07663
07664 if (tmp->cid_signalling == CID_SIG_SMDI) {
07665 if (!tmp->use_smdi) {
07666 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07667 tmp->use_smdi = 1;
07668 }
07669 }
07670 if (tmp->use_smdi) {
07671 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07672 if (!(tmp->smdi_iface)) {
07673 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07674 tmp->use_smdi = 0;
07675 }
07676 }
07677
07678 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07679 tmp->amaflags = conf->chan.amaflags;
07680 if (!here) {
07681 tmp->confno = -1;
07682 tmp->propconfno = -1;
07683 }
07684 tmp->canpark = conf->chan.canpark;
07685 tmp->transfer = conf->chan.transfer;
07686 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07687 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07688 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07689 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07690 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07691 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07692 tmp->cid_ton = 0;
07693 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07694 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07695 tmp->msgstate = -1;
07696 tmp->group = conf->chan.group;
07697 tmp->callgroup = conf->chan.callgroup;
07698 tmp->pickupgroup= conf->chan.pickupgroup;
07699 tmp->rxgain = conf->chan.rxgain;
07700 tmp->txgain = conf->chan.txgain;
07701 tmp->tonezone = conf->chan.tonezone;
07702 tmp->onhooktime = time(NULL);
07703 if (tmp->subs[SUB_REAL].dfd > -1) {
07704 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07705 if (tmp->dsp)
07706 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07707 update_conf(tmp);
07708 if (!here) {
07709 if (chan_sig != SIG_PRI)
07710
07711 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07712 }
07713 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
07714 #ifdef HAVE_PRI
07715
07716 if (tmp->pri && !pri_is_up(tmp->pri)) {
07717 tmp->inalarm = 1;
07718 }
07719 #endif
07720 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
07721 tmp->inalarm = 1;
07722 handle_alarms(tmp, res);
07723 } else {
07724
07725
07726
07727
07728
07729
07730
07731
07732
07733
07734 tmp->unknown_alarm = 1;
07735 }
07736 }
07737
07738 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07739 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07740 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07741 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07742
07743 }
07744 if (tmp && !here) {
07745
07746 if (!*wlist) {
07747 *wlist = tmp;
07748 tmp->prev = NULL;
07749 tmp->next = NULL;
07750 *wend = tmp;
07751 } else {
07752
07753 struct dahdi_pvt *working = *wlist;
07754
07755
07756 if (working->channel > tmp->channel) {
07757 tmp->next = *wlist;
07758 tmp->prev = NULL;
07759 (*wlist)->prev = tmp;
07760 *wlist = tmp;
07761 } else {
07762
07763 while (working) {
07764
07765 if (working->next) {
07766 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07767 tmp->next = working->next;
07768 tmp->prev = working;
07769 working->next->prev = tmp;
07770 working->next = tmp;
07771 break;
07772 }
07773 } else {
07774
07775 if (working->channel < tmp->channel) {
07776 working->next = tmp;
07777 tmp->next = NULL;
07778 tmp->prev = working;
07779 *wend = tmp;
07780 break;
07781 }
07782 }
07783 working = working->next;
07784 }
07785 }
07786 }
07787 }
07788 return tmp;
07789 }
07790
07791 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
07792 {
07793 int res;
07794 struct dahdi_params par;
07795
07796
07797 if (groupmatch) {
07798 if ((p->group & groupmatch) != groupmatch)
07799 return 0;
07800 *groupmatched = 1;
07801 }
07802
07803 if (channelmatch != -1) {
07804 if (p->channel != channelmatch)
07805 return 0;
07806 *channelmatched = 1;
07807 }
07808
07809 if (busy) {
07810 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07811 *busy = 1;
07812 }
07813
07814 if (p->dnd)
07815 return 0;
07816
07817 if (p->guardtime && (time(NULL) < p->guardtime))
07818 return 0;
07819
07820
07821 if (!p->owner) {
07822 #ifdef HAVE_PRI
07823
07824 if (p->pri) {
07825 if (p->resetting || p->call)
07826 return 0;
07827 else
07828 return 1;
07829 }
07830 #endif
07831 if (!(p->radio || (p->oprmode < 0)))
07832 {
07833 if (!p->sig || (p->sig == SIG_FXSLS))
07834 return 1;
07835
07836 if (p->subs[SUB_REAL].dfd > -1)
07837 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
07838 else {
07839
07840 res = 0;
07841 par.rxisoffhook = 0;
07842 }
07843 if (res) {
07844 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
07845 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07846
07847
07848
07849 if (par.rxbits > -1)
07850 return 1;
07851 if (par.rxisoffhook)
07852 return 1;
07853 else
07854 #ifdef DAHDI_CHECK_HOOKSTATE
07855 return 0;
07856 #else
07857 return 1;
07858 #endif
07859 } else if (par.rxisoffhook) {
07860 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07861
07862 return 0;
07863 }
07864 }
07865 return 1;
07866 }
07867
07868
07869 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
07870 return 0;
07871
07872 if (!p->callwaiting) {
07873
07874 return 0;
07875 }
07876
07877 if (p->subs[SUB_CALLWAIT].dfd > -1) {
07878
07879 return 0;
07880 }
07881
07882 if ((p->owner->_state != AST_STATE_UP) &&
07883 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07884
07885 return 0;
07886 }
07887 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07888
07889 return 0;
07890 }
07891
07892 return 1;
07893 }
07894
07895 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
07896 {
07897 struct dahdi_pvt *p;
07898 struct dahdi_bufferinfo bi;
07899 int res;
07900
07901 if ((p = ast_malloc(sizeof(*p)))) {
07902 memcpy(p, src, sizeof(struct dahdi_pvt));
07903 ast_mutex_init(&p->lock);
07904 p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
07905
07906 if (p->subs[SUB_REAL].dfd < 0) {
07907 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
07908 destroy_dahdi_pvt(&p);
07909 return NULL;
07910 }
07911 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07912 if (!res) {
07913 bi.txbufpolicy = p->buf_policy;
07914 bi.rxbufpolicy = p->buf_policy;
07915 bi.numbufs = p->buf_no;
07916 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07917 if (res < 0) {
07918 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
07919 }
07920 } else
07921 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
07922 }
07923 p->destroy = 1;
07924 p->next = iflist;
07925 p->prev = NULL;
07926 iflist = p;
07927 if (iflist->next)
07928 iflist->next->prev = p;
07929 return p;
07930 }
07931
07932
07933 #ifdef HAVE_PRI
07934 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
07935 {
07936 int x;
07937 if (backwards)
07938 x = pri->numchans;
07939 else
07940 x = 0;
07941 for (;;) {
07942 if (backwards && (x < 0))
07943 break;
07944 if (!backwards && (x >= pri->numchans))
07945 break;
07946 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
07947 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
07948 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
07949 return x;
07950 }
07951 if (backwards)
07952 x--;
07953 else
07954 x++;
07955 }
07956 return -1;
07957 }
07958 #endif
07959
07960 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
07961 {
07962 ast_group_t groupmatch = 0;
07963 int channelmatch = -1;
07964 int roundrobin = 0;
07965 int callwait = 0;
07966 int busy = 0;
07967 struct dahdi_pvt *p;
07968 struct ast_channel *tmp = NULL;
07969 char *dest=NULL;
07970 int x;
07971 char *s;
07972 char opt=0;
07973 int res=0, y=0;
07974 int backwards = 0;
07975 #ifdef HAVE_PRI
07976 int crv;
07977 int bearer = -1;
07978 int trunkgroup;
07979 struct dahdi_pri *pri=NULL;
07980 #endif
07981 struct dahdi_pvt *exit, *start, *end;
07982 ast_mutex_t *lock;
07983 int channelmatched = 0;
07984 int groupmatched = 0;
07985
07986
07987 lock = &iflock;
07988 start = iflist;
07989 end = ifend;
07990 if (data) {
07991 dest = ast_strdupa((char *)data);
07992 } else {
07993 ast_log(LOG_WARNING, "Channel requested with no data\n");
07994 return NULL;
07995 }
07996 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
07997
07998 char *stringp=NULL;
07999 stringp=dest + 1;
08000 s = strsep(&stringp, "/");
08001 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08002 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08003 return NULL;
08004 }
08005 groupmatch = ((ast_group_t) 1 << x);
08006 if (toupper(dest[0]) == 'G') {
08007 if (dest[0] == 'G') {
08008 backwards = 1;
08009 p = ifend;
08010 } else
08011 p = iflist;
08012 } else {
08013 if (dest[0] == 'R') {
08014 backwards = 1;
08015 p = round_robin[x]?round_robin[x]->prev:ifend;
08016 if (!p)
08017 p = ifend;
08018 } else {
08019 p = round_robin[x]?round_robin[x]->next:iflist;
08020 if (!p)
08021 p = iflist;
08022 }
08023 roundrobin = 1;
08024 }
08025 } else {
08026 char *stringp=NULL;
08027 stringp=dest;
08028 s = strsep(&stringp, "/");
08029 p = iflist;
08030 if (!strcasecmp(s, "pseudo")) {
08031
08032 x = CHAN_PSEUDO;
08033 channelmatch = x;
08034 }
08035 #ifdef HAVE_PRI
08036 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08037 if ((trunkgroup < 1) || (crv < 1)) {
08038 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08039 return NULL;
08040 }
08041 res--;
08042 for (x = 0; x < NUM_SPANS; x++) {
08043 if (pris[x].trunkgroup == trunkgroup) {
08044 pri = pris + x;
08045 lock = &pri->lock;
08046 start = pri->crvs;
08047 end = pri->crvend;
08048 break;
08049 }
08050 }
08051 if (!pri) {
08052 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08053 return NULL;
08054 }
08055 channelmatch = crv;
08056 p = pris[x].crvs;
08057 }
08058 #endif
08059 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08060 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08061 return NULL;
08062 } else {
08063 channelmatch = x;
08064 }
08065 }
08066
08067 ast_mutex_lock(lock);
08068 exit = p;
08069 while (p && !tmp) {
08070 if (roundrobin)
08071 round_robin[x] = p;
08072 #if 0
08073 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08074 #endif
08075
08076 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08077 if (option_debug)
08078 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08079 if (p->inalarm)
08080 goto next;
08081
08082 callwait = (p->owner != NULL);
08083 #ifdef HAVE_PRI
08084 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08085 if (p->sig != SIG_FXSKS) {
08086
08087
08088 bearer = pri_find_empty_chan(pri, 0);
08089 if (bearer < 0) {
08090 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08091 p = NULL;
08092 break;
08093 }
08094 pri_assign_bearer(p, pri, pri->pvts[bearer]);
08095 } else {
08096 if (alloc_sub(p, 0)) {
08097 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08098 p = NULL;
08099 break;
08100 } else
08101 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08102 p->pri = pri;
08103 }
08104 }
08105 #endif
08106 if (p->channel == CHAN_PSEUDO) {
08107 p = chandup(p);
08108 if (!p) {
08109 break;
08110 }
08111 }
08112 if (p->owner) {
08113 if (alloc_sub(p, SUB_CALLWAIT)) {
08114 p = NULL;
08115 break;
08116 }
08117 }
08118 p->outgoing = 1;
08119 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08120 #ifdef HAVE_PRI
08121 if (p->bearer) {
08122
08123 p->bearer->owner = tmp;
08124 }
08125 #endif
08126
08127 if (res > 1) {
08128 if (opt == 'c') {
08129
08130 p->confirmanswer = 1;
08131 } else if (opt == 'r') {
08132
08133 if (res < 3)
08134 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08135 else
08136 p->distinctivering = y;
08137 } else if (opt == 'd') {
08138
08139 p->digital = 1;
08140 if (tmp)
08141 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08142 } else {
08143 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08144 }
08145 }
08146
08147 if (tmp && callwait)
08148 tmp->cdrflags |= AST_CDR_CALLWAIT;
08149 break;
08150 }
08151 next:
08152 if (backwards) {
08153 p = p->prev;
08154 if (!p)
08155 p = end;
08156 } else {
08157 p = p->next;
08158 if (!p)
08159 p = start;
08160 }
08161
08162 if (p == exit)
08163 break;
08164 }
08165 ast_mutex_unlock(lock);
08166 restart_monitor();
08167 if (callwait)
08168 *cause = AST_CAUSE_BUSY;
08169 else if (!tmp) {
08170 if (channelmatched) {
08171 if (busy)
08172 *cause = AST_CAUSE_BUSY;
08173 } else if (groupmatched) {
08174 *cause = AST_CAUSE_CONGESTION;
08175 }
08176 }
08177
08178 return tmp;
08179 }
08180
08181
08182 #ifdef HAVE_PRI
08183 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08184 {
08185 struct dahdi_pvt *p;
08186 p = pri->crvs;
08187 while (p) {
08188 if (p->channel == crv)
08189 return p;
08190 p = p->next;
08191 }
08192 return NULL;
08193 }
08194
08195
08196 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08197 {
08198 int x;
08199 int span = PRI_SPAN(channel);
08200 int spanfd;
08201 struct dahdi_params param;
08202 int principle = -1;
08203 int explicit = PRI_EXPLICIT(channel);
08204 channel = PRI_CHANNEL(channel);
08205
08206 if (!explicit) {
08207 spanfd = pri_active_dchan_fd(pri);
08208 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
08209 return -1;
08210 span = pris[param.spanno - 1].prilogicalspan;
08211 }
08212
08213 for (x = 0; x < pri->numchans; x++) {
08214 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08215 principle = x;
08216 break;
08217 }
08218 }
08219
08220 return principle;
08221 }
08222
08223 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08224 {
08225 int x;
08226 struct dahdi_pvt *crv;
08227 if (!c) {
08228 if (principle < 0)
08229 return -1;
08230 return principle;
08231 }
08232 if ((principle > -1) &&
08233 (principle < pri->numchans) &&
08234 (pri->pvts[principle]) &&
08235 (pri->pvts[principle]->call == c))
08236 return principle;
08237
08238 for (x = 0; x < pri->numchans; x++) {
08239 if (!pri->pvts[x])
08240 continue;
08241 if (pri->pvts[x]->call == c) {
08242
08243 if (principle != x) {
08244 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08245
08246 if (option_verbose > 2)
08247 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08248 old->channel, new->channel);
08249 if (new->owner) {
08250 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08251 old->channel, new->channel, new->channel);
08252 return -1;
08253 }
08254
08255 new->owner = old->owner;
08256 old->owner = NULL;
08257 if (new->owner) {
08258 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08259 new->owner->tech_pvt = new;
08260 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08261 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08262 old->subs[SUB_REAL].owner = NULL;
08263 } else
08264 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
08265 new->call = old->call;
08266 old->call = NULL;
08267
08268
08269 new->dsp = old->dsp;
08270 new->dsp_features = old->dsp_features;
08271 old->dsp = NULL;
08272 old->dsp_features = 0;
08273 }
08274 return principle;
08275 }
08276 }
08277
08278 crv = pri->crvs;
08279 while (crv) {
08280 if (crv->call == c) {
08281
08282 if (crv->bearer)
08283 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08284 else if (pri->pvts[principle]->owner)
08285 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08286 else {
08287
08288
08289 dahdi_close_sub(crv, SUB_REAL);
08290 pri->pvts[principle]->call = crv->call;
08291 pri_assign_bearer(crv, pri, pri->pvts[principle]);
08292 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08293 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08294 pri->trunkgroup, crv->channel);
08295 wakeup_sub(crv, SUB_REAL, pri);
08296 }
08297 return principle;
08298 }
08299 crv = crv->next;
08300 }
08301 ast_log(LOG_WARNING, "Call specified, but not found?\n");
08302 return -1;
08303 }
08304
08305 static void *do_idle_thread(void *vchan)
08306 {
08307 struct ast_channel *chan = vchan;
08308 struct dahdi_pvt *pvt = chan->tech_pvt;
08309 struct ast_frame *f;
08310 char ex[80];
08311
08312 int newms, ms = 30000;
08313 if (option_verbose > 2)
08314 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08315 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08316 if (ast_call(chan, ex, 0)) {
08317 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08318 ast_hangup(chan);
08319 return NULL;
08320 }
08321 while ((newms = ast_waitfor(chan, ms)) > 0) {
08322 f = ast_read(chan);
08323 if (!f) {
08324
08325 break;
08326 }
08327 if (f->frametype == AST_FRAME_CONTROL) {
08328 switch (f->subclass) {
08329 case AST_CONTROL_ANSWER:
08330
08331 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08332 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08333 chan->priority = 1;
08334 if (option_verbose > 3)
08335 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08336 ast_pbx_run(chan);
08337
08338 return NULL;
08339 case AST_CONTROL_BUSY:
08340 if (option_verbose > 3)
08341 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08342 break;
08343 case AST_CONTROL_CONGESTION:
08344 if (option_verbose > 3)
08345 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08346 break;
08347 };
08348 }
08349 ast_frfree(f);
08350 ms = newms;
08351 }
08352
08353 ast_hangup(chan);
08354 return NULL;
08355 }
08356
08357 #ifndef PRI_RESTART
08358 #error "Upgrade your libpri"
08359 #endif
08360 static void dahdi_pri_message(struct pri *pri, char *s)
08361 {
08362 int x, y;
08363 int dchan = -1, span = -1;
08364 int dchancount = 0;
08365
08366 if (pri) {
08367 for (x = 0; x < NUM_SPANS; x++) {
08368 for (y = 0; y < NUM_DCHANS; y++) {
08369 if (pris[x].dchans[y])
08370 dchancount++;
08371
08372 if (pris[x].dchans[y] == pri)
08373 dchan = y;
08374 }
08375 if (dchan >= 0) {
08376 span = x;
08377 break;
08378 }
08379 dchancount = 0;
08380 }
08381 if ((dchan >= 0) && (span >= 0)) {
08382 if (dchancount > 1)
08383 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08384 else
08385 ast_verbose("%s", s);
08386 } else
08387 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08388 } else
08389 ast_verbose("%s", s);
08390
08391 ast_mutex_lock(&pridebugfdlock);
08392
08393 if (pridebugfd >= 0) {
08394 if (write(pridebugfd, s, strlen(s)) < 0) {
08395 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08396 }
08397 }
08398
08399 ast_mutex_unlock(&pridebugfdlock);
08400 }
08401
08402 static void dahdi_pri_error(struct pri *pri, char *s)
08403 {
08404 int x, y;
08405 int dchan = -1, span = -1;
08406 int dchancount = 0;
08407
08408 if (pri) {
08409 for (x = 0; x < NUM_SPANS; x++) {
08410 for (y = 0; y < NUM_DCHANS; y++) {
08411 if (pris[x].dchans[y])
08412 dchancount++;
08413
08414 if (pris[x].dchans[y] == pri)
08415 dchan = y;
08416 }
08417 if (dchan >= 0) {
08418 span = x;
08419 break;
08420 }
08421 dchancount = 0;
08422 }
08423 if ((dchan >= 0) && (span >= 0)) {
08424 if (dchancount > 1)
08425 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08426 else
08427 ast_log(LOG_ERROR, "%s", s);
08428 } else
08429 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08430 } else
08431 ast_log(LOG_ERROR, "%s", s);
08432
08433 ast_mutex_lock(&pridebugfdlock);
08434
08435 if (pridebugfd >= 0) {
08436 if (write(pridebugfd, s, strlen(s)) < 0) {
08437 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08438 }
08439 }
08440
08441 ast_mutex_unlock(&pridebugfdlock);
08442 }
08443
08444 static int pri_check_restart(struct dahdi_pri *pri)
08445 {
08446 do {
08447 pri->resetpos++;
08448 } while ((pri->resetpos < pri->numchans) &&
08449 (!pri->pvts[pri->resetpos] ||
08450 pri->pvts[pri->resetpos]->call ||
08451 pri->pvts[pri->resetpos]->resetting));
08452 if (pri->resetpos < pri->numchans) {
08453
08454 pri->pvts[pri->resetpos]->resetting = 1;
08455 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08456 } else {
08457 pri->resetting = 0;
08458 time(&pri->lastreset);
08459 }
08460 return 0;
08461 }
08462
08463 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08464 {
08465 int x;
08466 int redo;
08467 ast_mutex_unlock(&pri->lock);
08468 ast_mutex_lock(&p->lock);
08469 do {
08470 redo = 0;
08471 for (x = 0; x < 3; x++) {
08472 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08473 redo++;
08474 DEADLOCK_AVOIDANCE(&p->lock);
08475 }
08476 if (p->subs[x].owner) {
08477 ast_queue_hangup(p->subs[x].owner);
08478 ast_mutex_unlock(&p->subs[x].owner->lock);
08479 }
08480 }
08481 } while (redo);
08482 ast_mutex_unlock(&p->lock);
08483 ast_mutex_lock(&pri->lock);
08484 return 0;
08485 }
08486
08487 static char * redirectingreason2str(int redirectingreason)
08488 {
08489 switch (redirectingreason) {
08490 case 0:
08491 return "UNKNOWN";
08492 case 1:
08493 return "BUSY";
08494 case 2:
08495 return "NO_REPLY";
08496 case 0xF:
08497 return "UNCONDITIONAL";
08498 default:
08499 return "NOREDIRECT";
08500 }
08501 }
08502
08503 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08504 {
08505 switch (plan) {
08506 case PRI_INTERNATIONAL_ISDN:
08507 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08508 break;
08509 case PRI_NATIONAL_ISDN:
08510 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08511 break;
08512 case PRI_LOCAL_ISDN:
08513 snprintf(buf, size, "%s%s", pri->localprefix, number);
08514 break;
08515 case PRI_PRIVATE:
08516 snprintf(buf, size, "%s%s", pri->privateprefix, number);
08517 break;
08518 case PRI_UNKNOWN:
08519 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08520 break;
08521 default:
08522 snprintf(buf, size, "%s", number);
08523 break;
08524 }
08525 }
08526
08527 static int dahdi_setlaw(int dfd, int law)
08528 {
08529 int res;
08530 res = ioctl(dfd, DAHDI_SETLAW, &law);
08531 if (res)
08532 return res;
08533 return 0;
08534 }
08535
08536 static void *pri_dchannel(void *vpri)
08537 {
08538 struct dahdi_pri *pri = vpri;
08539 pri_event *e;
08540 struct pollfd fds[NUM_DCHANS];
08541 int res;
08542 int chanpos = 0;
08543 int x;
08544 int haveidles;
08545 int activeidles;
08546 int nextidle = -1;
08547 struct ast_channel *c;
08548 struct timeval tv, lowest, *next;
08549 struct timeval lastidle = { 0, 0 };
08550 int doidling=0;
08551 char *cc;
08552 char idlen[80];
08553 struct ast_channel *idle;
08554 pthread_t p;
08555 time_t t;
08556 int i, which=-1;
08557 int numdchans;
08558 int cause=0;
08559 struct dahdi_pvt *crv;
08560 pthread_t threadid;
08561 pthread_attr_t attr;
08562 char ani2str[6];
08563 char plancallingnum[256];
08564 char plancallingani[256];
08565 char calledtonstr[10];
08566
08567 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08568
08569 gettimeofday(&lastidle, NULL);
08570 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08571
08572 cc = strchr(pri->idleext, '@');
08573 if (cc) {
08574 *cc = '\0';
08575 cc++;
08576 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08577 #if 0
08578
08579 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08580 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08581 else
08582 #endif
08583 doidling = 1;
08584 } else
08585 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08586 }
08587 for (;;) {
08588 for (i = 0; i < NUM_DCHANS; i++) {
08589 if (!pri->dchannels[i])
08590 break;
08591 fds[i].fd = pri->fds[i];
08592 fds[i].events = POLLIN | POLLPRI;
08593 fds[i].revents = 0;
08594 }
08595 numdchans = i;
08596 time(&t);
08597 ast_mutex_lock(&pri->lock);
08598 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08599 if (pri->resetting && pri_is_up(pri)) {
08600 if (pri->resetpos < 0)
08601 pri_check_restart(pri);
08602 } else {
08603 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
08604 pri->resetting = 1;
08605 pri->resetpos = -1;
08606 }
08607 }
08608 }
08609
08610 if (doidling && pri_is_up(pri)) {
08611 nextidle = -1;
08612 haveidles = 0;
08613 activeidles = 0;
08614 for (x = pri->numchans; x >= 0; x--) {
08615 if (pri->pvts[x] && !pri->pvts[x]->owner &&
08616 !pri->pvts[x]->call) {
08617 if (haveidles < pri->minunused) {
08618 haveidles++;
08619 } else if (!pri->pvts[x]->resetting) {
08620 nextidle = x;
08621 break;
08622 }
08623 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08624 activeidles++;
08625 }
08626 if (nextidle > -1) {
08627 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08628
08629 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08630 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08631 if (idle) {
08632 pri->pvts[nextidle]->isidlecall = 1;
08633 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08634 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08635 dahdi_hangup(idle);
08636 }
08637 } else
08638 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08639 gettimeofday(&lastidle, NULL);
08640 }
08641 } else if ((haveidles < pri->minunused) &&
08642 (activeidles > pri->minidle)) {
08643
08644
08645 for (x = pri->numchans; x >= 0; x--) {
08646
08647 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08648 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08649 haveidles++;
08650
08651
08652 if ((haveidles >= pri->minunused) ||
08653 (activeidles <= pri->minidle))
08654 break;
08655 }
08656 }
08657 }
08658 }
08659
08660 lowest = ast_tv(60, 0);
08661 for (i = 0; i < NUM_DCHANS; i++) {
08662
08663 if (!pri->dchannels[i])
08664 break;
08665 if ((next = pri_schedule_next(pri->dchans[i]))) {
08666
08667 tv = ast_tvsub(*next, ast_tvnow());
08668 if (tv.tv_sec < 0) {
08669 tv = ast_tv(0,0);
08670 }
08671 if (doidling || pri->resetting) {
08672 if (tv.tv_sec > 1) {
08673 tv = ast_tv(1, 0);
08674 }
08675 } else {
08676 if (tv.tv_sec > 60) {
08677 tv = ast_tv(60, 0);
08678 }
08679 }
08680 } else if (doidling || pri->resetting) {
08681
08682
08683 tv = ast_tv(1,0);
08684 } else {
08685
08686 tv = ast_tv(60, 0);
08687 }
08688 if (!i || ast_tvcmp(tv, lowest) < 0) {
08689 lowest = tv;
08690 }
08691 }
08692 ast_mutex_unlock(&pri->lock);
08693
08694 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08695 pthread_testcancel();
08696 e = NULL;
08697 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
08698 pthread_testcancel();
08699 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08700
08701 ast_mutex_lock(&pri->lock);
08702 if (!res) {
08703 for (which = 0; which < NUM_DCHANS; which++) {
08704 if (!pri->dchans[which])
08705 break;
08706
08707 e = pri_schedule_run(pri->dchans[which]);
08708 if (e)
08709 break;
08710 }
08711 } else if (res > -1) {
08712 for (which = 0; which < NUM_DCHANS; which++) {
08713 if (!pri->dchans[which])
08714 break;
08715 if (fds[which].revents & POLLPRI) {
08716
08717 x = 0;
08718 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
08719 if (x)
08720 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
08721
08722 if (x == DAHDI_EVENT_ALARM) {
08723 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
08724 pri_find_dchan(pri);
08725 } else if (x == DAHDI_EVENT_NOALARM) {
08726 pri->dchanavail[which] |= DCHAN_NOTINALARM;
08727 pri_restart(pri->dchans[which]);
08728 }
08729
08730 if (option_debug)
08731 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
08732 } else if (fds[which].revents & POLLIN) {
08733 e = pri_check_event(pri->dchans[which]);
08734 }
08735 if (e)
08736 break;
08737 }
08738 } else if (errno != EINTR)
08739 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
08740
08741 if (e) {
08742 if (pri->debug)
08743 pri_dump_event(pri->dchans[which], e);
08744
08745 if (e->e != PRI_EVENT_DCHAN_DOWN) {
08746 if (!(pri->dchanavail[which] & DCHAN_UP)) {
08747 if (option_verbose > 1)
08748 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
08749 }
08750 pri->dchanavail[which] |= DCHAN_UP;
08751 } else {
08752 if (pri->dchanavail[which] & DCHAN_UP) {
08753 if (option_verbose > 1)
08754 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
08755 }
08756 pri->dchanavail[which] &= ~DCHAN_UP;
08757 }
08758
08759 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
08760
08761 pri->pri = pri->dchans[which];
08762
08763 switch (e->e) {
08764 case PRI_EVENT_DCHAN_UP:
08765 if (!pri->pri) pri_find_dchan(pri);
08766
08767
08768 time(&pri->lastreset);
08769
08770
08771 if (pri->resetinterval > -1) {
08772 pri->lastreset -= pri->resetinterval;
08773 pri->lastreset += 5;
08774 }
08775 pri->resetting = 0;
08776
08777 for (i = 0; i < pri->numchans; i++)
08778 if (pri->pvts[i]) {
08779 pri->pvts[i]->inalarm = 0;
08780 }
08781 break;
08782 case PRI_EVENT_DCHAN_DOWN:
08783 pri_find_dchan(pri);
08784 if (!pri_is_up(pri)) {
08785 pri->resetting = 0;
08786
08787 for (i = 0; i < pri->numchans; i++) {
08788 struct dahdi_pvt *p = pri->pvts[i];
08789 if (p) {
08790 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08791
08792 if (p->call) {
08793 if (p->pri && p->pri->pri) {
08794 pri_hangup(p->pri->pri, p->call, -1);
08795 pri_destroycall(p->pri->pri, p->call);
08796 p->call = NULL;
08797 } else
08798 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
08799 }
08800 if (p->realcall) {
08801 pri_hangup_all(p->realcall, pri);
08802 } else if (p->owner)
08803 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08804 }
08805 p->inalarm = 1;
08806 }
08807 }
08808 }
08809 break;
08810 case PRI_EVENT_RESTART:
08811 if (e->restart.channel > -1) {
08812 chanpos = pri_find_principle(pri, e->restart.channel);
08813 if (chanpos < 0)
08814 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
08815 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08816 else {
08817 if (option_verbose > 2)
08818 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
08819 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08820 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08821 if (pri->pvts[chanpos]->call) {
08822 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
08823 pri->pvts[chanpos]->call = NULL;
08824 }
08825
08826 if (pri->pvts[chanpos]->realcall)
08827 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08828 else if (pri->pvts[chanpos]->owner)
08829 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08830 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08831 }
08832 } else {
08833 if (option_verbose > 2)
08834 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
08835 for (x = 0; x < pri->numchans; x++)
08836 if (pri->pvts[x]) {
08837 ast_mutex_lock(&pri->pvts[x]->lock);
08838 if (pri->pvts[x]->call) {
08839 pri_destroycall(pri->pri, pri->pvts[x]->call);
08840 pri->pvts[x]->call = NULL;
08841 }
08842 if (pri->pvts[chanpos]->realcall)
08843 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08844 else if (pri->pvts[x]->owner)
08845 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08846 ast_mutex_unlock(&pri->pvts[x]->lock);
08847 }
08848 }
08849 break;
08850 case PRI_EVENT_KEYPAD_DIGIT:
08851 chanpos = pri_find_principle(pri, e->digit.channel);
08852 if (chanpos < 0) {
08853 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
08854 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
08855 } else {
08856 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
08857 if (chanpos > -1) {
08858 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08859
08860 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
08861
08862 int digitlen = strlen(e->digit.digits);
08863 char digit;
08864 int i;
08865 for (i = 0; i < digitlen; i++) {
08866 digit = e->digit.digits[i];
08867 {
08868 struct ast_frame f = { AST_FRAME_DTMF, digit, };
08869 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08870 }
08871 }
08872 }
08873 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08874 }
08875 }
08876 break;
08877
08878 case PRI_EVENT_INFO_RECEIVED:
08879 chanpos = pri_find_principle(pri, e->ring.channel);
08880 if (chanpos < 0) {
08881 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
08882 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08883 } else {
08884 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
08885 if (chanpos > -1) {
08886 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08887
08888 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
08889
08890 int digitlen = strlen(e->ring.callednum);
08891 char digit;
08892 int i;
08893 for (i = 0; i < digitlen; i++) {
08894 digit = e->ring.callednum[i];
08895 {
08896 struct ast_frame f = { AST_FRAME_DTMF, digit, };
08897 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08898 }
08899 }
08900 }
08901 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08902 }
08903 }
08904 break;
08905 case PRI_EVENT_RING:
08906 crv = NULL;
08907 if (e->ring.channel == -1)
08908 chanpos = pri_find_empty_chan(pri, 1);
08909 else
08910 chanpos = pri_find_principle(pri, e->ring.channel);
08911
08912 if (chanpos < 0) {
08913 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
08914 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08915 } else {
08916 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08917 if (pri->pvts[chanpos]->owner) {
08918 if (pri->pvts[chanpos]->call == e->ring.call) {
08919 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
08920 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08921 break;
08922 } else {
08923
08924 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
08925 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08926 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08927 chanpos = -1;
08928 }
08929 }
08930 if (chanpos > -1)
08931 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08932 }
08933 if ((chanpos < 0) && (e->ring.flexible))
08934 chanpos = pri_find_empty_chan(pri, 1);
08935 if (chanpos > -1) {
08936 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08937 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
08938
08939 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
08940 if (crv)
08941 ast_mutex_lock(&crv->lock);
08942 if (!crv || crv->owner) {
08943 pri->pvts[chanpos]->call = NULL;
08944 if (crv) {
08945 if (crv->owner)
08946 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08947 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
08948 } else
08949 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
08950 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
08951 if (crv)
08952 ast_mutex_unlock(&crv->lock);
08953 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08954 break;
08955 }
08956 }
08957 pri->pvts[chanpos]->call = e->ring.call;
08958 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
08959 if (pri->pvts[chanpos]->use_callerid) {
08960 ast_shrink_phone_number(plancallingnum);
08961 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
08962 #ifdef PRI_ANI
08963 if (!ast_strlen_zero(e->ring.callingani)) {
08964 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
08965 ast_shrink_phone_number(plancallingani);
08966 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
08967 } else {
08968 pri->pvts[chanpos]->cid_ani[0] = '\0';
08969 }
08970 #endif
08971 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
08972 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
08973 } else {
08974 pri->pvts[chanpos]->cid_num[0] = '\0';
08975 pri->pvts[chanpos]->cid_ani[0] = '\0';
08976 pri->pvts[chanpos]->cid_name[0] = '\0';
08977 pri->pvts[chanpos]->cid_ton = 0;
08978 }
08979 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
08980 e->ring.redirectingnum, e->ring.callingplanrdnis);
08981
08982 if (pri->pvts[chanpos]->immediate) {
08983 if (option_verbose > 2)
08984 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
08985 pri->pvts[chanpos]->exten[0] = 's';
08986 pri->pvts[chanpos]->exten[1] = '\0';
08987 }
08988
08989 else if (!ast_strlen_zero(e->ring.callednum)) {
08990 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
08991 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
08992 } else if (pri->overlapdial)
08993 pri->pvts[chanpos]->exten[0] = '\0';
08994 else {
08995
08996 pri->pvts[chanpos]->exten[0] = 's';
08997 pri->pvts[chanpos]->exten[1] = '\0';
08998 }
08999
09000 if (!ast_strlen_zero(e->ring.callednum))
09001 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09002
09003 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09004 if (option_verbose > 2)
09005 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09006 pri->pvts[chanpos]->exten[0] = 's';
09007 pri->pvts[chanpos]->exten[1] = '\0';
09008 }
09009
09010 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09011 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09012
09013 int law;
09014 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09015
09016 law = 1;
09017 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09018 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09019 }
09020 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09021 law = DAHDI_LAW_ALAW;
09022 else
09023 law = DAHDI_LAW_MULAW;
09024 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09025 if (res < 0)
09026 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09027 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09028 if (res < 0)
09029 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09030 if (e->ring.complete || !pri->overlapdial) {
09031
09032 pri->pvts[chanpos]->proceeding = 1;
09033 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09034 } else {
09035 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
09036 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09037 else
09038 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09039 }
09040
09041 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09042
09043
09044 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09045
09046 ast_mutex_unlock(&pri->lock);
09047 if (crv) {
09048
09049 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09050 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09051 pri->pvts[chanpos]->owner = &inuse;
09052 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09053 } else {
09054 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09055 }
09056
09057 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09058
09059 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09060 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09061 }
09062 if (e->ring.ani2 >= 0) {
09063 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09064 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09065 }
09066
09067 #ifdef SUPPORT_USERUSER
09068 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09069 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09070 }
09071 #endif
09072
09073 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09074 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09075 if (e->ring.redirectingreason >= 0)
09076 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09077
09078 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09079 ast_mutex_lock(&pri->lock);
09080
09081 pthread_attr_init(&attr);
09082 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09083 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09084 if (option_verbose > 2)
09085 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09086 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09087 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09088 } else {
09089 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09090 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09091 if (c)
09092 ast_hangup(c);
09093 else {
09094 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09095 pri->pvts[chanpos]->call = NULL;
09096 }
09097 }
09098 pthread_attr_destroy(&attr);
09099 } else {
09100 ast_mutex_unlock(&pri->lock);
09101
09102 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09103 if (c) {
09104 char calledtonstr[10];
09105
09106 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09107
09108 if (e->ring.ani2 >= 0) {
09109 snprintf(ani2str, 5, "%d", e->ring.ani2);
09110 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09111 }
09112
09113 #ifdef SUPPORT_USERUSER
09114 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09115 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09116 }
09117 #endif
09118
09119 if (e->ring.redirectingreason >= 0)
09120 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09121
09122 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09123 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09124
09125 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09126 ast_mutex_lock(&pri->lock);
09127
09128 if (option_verbose > 2)
09129 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09130 plancallingnum, pri->pvts[chanpos]->exten,
09131 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09132 dahdi_enable_ec(pri->pvts[chanpos]);
09133 } else {
09134
09135 ast_mutex_lock(&pri->lock);
09136
09137 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09138 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09139 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09140 pri->pvts[chanpos]->call = NULL;
09141 }
09142 }
09143 } else {
09144 if (option_verbose > 2)
09145 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
09146 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
09147 pri->pvts[chanpos]->prioffset, pri->span);
09148 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09149 pri->pvts[chanpos]->call = NULL;
09150 pri->pvts[chanpos]->exten[0] = '\0';
09151 }
09152 if (crv)
09153 ast_mutex_unlock(&crv->lock);
09154 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09155 } else {
09156 if (e->ring.flexible)
09157 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09158 else
09159 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09160 }
09161 break;
09162 case PRI_EVENT_RINGING:
09163 chanpos = pri_find_principle(pri, e->ringing.channel);
09164 if (chanpos < 0) {
09165 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
09166 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09167 } else {
09168 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09169 if (chanpos < 0) {
09170 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
09171 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09172 } else {
09173 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09174 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09175 dahdi_enable_ec(pri->pvts[chanpos]);
09176 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09177 pri->pvts[chanpos]->alerting = 1;
09178 } else
09179 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09180 #ifdef PRI_PROGRESS_MASK
09181 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09182 #else
09183 if (e->ringing.progress == 8) {
09184 #endif
09185
09186 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09187
09188 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09189 pri->pvts[chanpos]->dsp_features = 0;
09190 }
09191 }
09192
09193 #ifdef SUPPORT_USERUSER
09194 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09195 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09196 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09197 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09198 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09199 }
09200 #endif
09201
09202 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09203 }
09204 }
09205 break;
09206 case PRI_EVENT_PROGRESS:
09207
09208 chanpos = pri_find_principle(pri, e->proceeding.channel);
09209 if (chanpos > -1) {
09210 #ifdef PRI_PROGRESS_MASK
09211 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09212 #else
09213 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09214 #endif
09215 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09216
09217 if (e->proceeding.cause > -1) {
09218 if (option_verbose > 2)
09219 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09220
09221
09222 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09223 if (pri->pvts[chanpos]->owner) {
09224 if (option_verbose > 2)
09225 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09226
09227 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09228 f.subclass = AST_CONTROL_BUSY;
09229 }
09230 }
09231 }
09232
09233 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09234 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09235 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09236 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09237 #ifdef PRI_PROGRESS_MASK
09238 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09239 #else
09240 if (e->proceeding.progress == 8) {
09241 #endif
09242
09243 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09244 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09245 pri->pvts[chanpos]->dsp_features = 0;
09246 }
09247 }
09248 pri->pvts[chanpos]->progress = 1;
09249 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09250 }
09251 }
09252 break;
09253 case PRI_EVENT_PROCEEDING:
09254 chanpos = pri_find_principle(pri, e->proceeding.channel);
09255 if (chanpos > -1) {
09256 if (!pri->pvts[chanpos]->proceeding) {
09257 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09258
09259 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09260 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09261 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09262 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09263 #ifdef PRI_PROGRESS_MASK
09264 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09265 #else
09266 if (e->proceeding.progress == 8) {
09267 #endif
09268
09269 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09270 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09271 pri->pvts[chanpos]->dsp_features = 0;
09272 }
09273
09274 f.subclass = AST_CONTROL_PROGRESS;
09275 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09276 }
09277 pri->pvts[chanpos]->proceeding = 1;
09278 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09279 }
09280 }
09281 break;
09282 case PRI_EVENT_FACNAME:
09283 chanpos = pri_find_principle(pri, e->facname.channel);
09284 if (chanpos < 0) {
09285 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
09286 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09287 } else {
09288 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09289 if (chanpos < 0) {
09290 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
09291 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09292 } else {
09293
09294 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09295 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09296 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09297 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09298 dahdi_enable_ec(pri->pvts[chanpos]);
09299 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09300 }
09301 }
09302 break;
09303 case PRI_EVENT_ANSWER:
09304 chanpos = pri_find_principle(pri, e->answer.channel);
09305 if (chanpos < 0) {
09306 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
09307 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09308 } else {
09309 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09310 if (chanpos < 0) {
09311 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
09312 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09313 } else {
09314 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09315
09316
09317
09318
09319
09320 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09321 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09322 pri->pvts[chanpos]->dsp_features = 0;
09323 }
09324 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09325 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09326 x = DAHDI_START;
09327 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09328 if (res < 0) {
09329 if (errno != EINPROGRESS) {
09330 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09331 }
09332 }
09333 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09334 pri->pvts[chanpos]->dialing = 1;
09335
09336 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09337 if (res < 0) {
09338 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09339 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09340 } else
09341 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09342 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09343 } else if (pri->pvts[chanpos]->confirmanswer) {
09344 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09345 } else {
09346 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09347
09348 dahdi_enable_ec(pri->pvts[chanpos]);
09349 }
09350
09351 #ifdef SUPPORT_USERUSER
09352 if (!ast_strlen_zero(e->answer.useruserinfo)) {
09353 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09354 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09355 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09356 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09357 }
09358 #endif
09359
09360 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09361 }
09362 }
09363 break;
09364 case PRI_EVENT_HANGUP:
09365 chanpos = pri_find_principle(pri, e->hangup.channel);
09366 if (chanpos < 0) {
09367 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
09368 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09369 } else {
09370 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09371 if (chanpos > -1) {
09372 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09373 if (!pri->pvts[chanpos]->alreadyhungup) {
09374
09375 pri->pvts[chanpos]->alreadyhungup = 1;
09376 if (pri->pvts[chanpos]->realcall)
09377 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09378 else if (pri->pvts[chanpos]->owner) {
09379
09380 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09381 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09382 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09383 else {
09384 switch (e->hangup.cause) {
09385 case PRI_CAUSE_USER_BUSY:
09386 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09387 break;
09388 case PRI_CAUSE_CALL_REJECTED:
09389 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09390 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09391 case PRI_CAUSE_SWITCH_CONGESTION:
09392 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09393 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09394 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09395 break;
09396 default:
09397 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09398 }
09399 }
09400 }
09401 if (option_verbose > 2)
09402 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
09403 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09404 } else {
09405 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09406 pri->pvts[chanpos]->call = NULL;
09407 }
09408 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09409 if (option_verbose > 2)
09410 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
09411 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09412 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09413 pri->pvts[chanpos]->resetting = 1;
09414 }
09415 if (e->hangup.aoc_units > -1)
09416 if (option_verbose > 2)
09417 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09418 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09419
09420 #ifdef SUPPORT_USERUSER
09421 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09422 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09423 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09424 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09425 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09426 }
09427 #endif
09428
09429 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09430 } else {
09431 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
09432 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09433 }
09434 }
09435 break;
09436 #ifndef PRI_EVENT_HANGUP_REQ
09437 #error please update libpri
09438 #endif
09439 case PRI_EVENT_HANGUP_REQ:
09440 chanpos = pri_find_principle(pri, e->hangup.channel);
09441 if (chanpos < 0) {
09442 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
09443 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09444 } else {
09445 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09446 if (chanpos > -1) {
09447 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09448 if (pri->pvts[chanpos]->realcall)
09449 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09450 else if (pri->pvts[chanpos]->owner) {
09451 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09452 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09453 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09454 else {
09455 switch (e->hangup.cause) {
09456 case PRI_CAUSE_USER_BUSY:
09457 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09458 break;
09459 case PRI_CAUSE_CALL_REJECTED:
09460 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09461 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09462 case PRI_CAUSE_SWITCH_CONGESTION:
09463 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09464 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09465 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09466 break;
09467 default:
09468 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09469 }
09470 }
09471 if (option_verbose > 2)
09472 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
09473 if (e->hangup.aoc_units > -1)
09474 if (option_verbose > 2)
09475 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09476 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09477 } else {
09478 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09479 pri->pvts[chanpos]->call = NULL;
09480 }
09481 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09482 if (option_verbose > 2)
09483 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
09484 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09485 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09486 pri->pvts[chanpos]->resetting = 1;
09487 }
09488
09489 #ifdef SUPPORT_USERUSER
09490 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09491 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09492 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09493 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09494 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09495 }
09496 #endif
09497
09498 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09499 } else {
09500 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09501 }
09502 }
09503 break;
09504 case PRI_EVENT_HANGUP_ACK:
09505 chanpos = pri_find_principle(pri, e->hangup.channel);
09506 if (chanpos < 0) {
09507 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
09508 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09509 } else {
09510 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09511 if (chanpos > -1) {
09512 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09513 pri->pvts[chanpos]->call = NULL;
09514 pri->pvts[chanpos]->resetting = 0;
09515 if (pri->pvts[chanpos]->owner) {
09516 if (option_verbose > 2)
09517 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09518 }
09519
09520 #ifdef SUPPORT_USERUSER
09521 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09522 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09523 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09524 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09525 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09526 }
09527 #endif
09528
09529 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09530 }
09531 }
09532 break;
09533 case PRI_EVENT_CONFIG_ERR:
09534 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09535 break;
09536 case PRI_EVENT_RESTART_ACK:
09537 chanpos = pri_find_principle(pri, e->restartack.channel);
09538 if (chanpos < 0) {
09539
09540
09541
09542 for (x = 0; x < pri->numchans; x++) {
09543 if (pri->pvts[x] && pri->pvts[x]->resetting) {
09544 chanpos = x;
09545 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09546 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
09547 pri->pvts[chanpos]->prioffset, pri->span);
09548 if (pri->pvts[chanpos]->realcall)
09549 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09550 else if (pri->pvts[chanpos]->owner) {
09551 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
09552 pri->pvts[chanpos]->prioffset, pri->span);
09553 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09554 }
09555 pri->pvts[chanpos]->resetting = 0;
09556 if (option_verbose > 2)
09557 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09558 pri->pvts[chanpos]->prioffset, pri->span);
09559 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09560 if (pri->resetting)
09561 pri_check_restart(pri);
09562 break;
09563 }
09564 }
09565 if (chanpos < 0) {
09566 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
09567 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09568 }
09569 } else {
09570 if (pri->pvts[chanpos]) {
09571 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09572 if (pri->pvts[chanpos]->realcall)
09573 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09574 else if (pri->pvts[chanpos]->owner) {
09575 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09576 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09577 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09578 }
09579 pri->pvts[chanpos]->resetting = 0;
09580 if (option_verbose > 2)
09581 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09582 pri->pvts[chanpos]->prioffset, pri->span);
09583 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09584 if (pri->resetting)
09585 pri_check_restart(pri);
09586 }
09587 }
09588 break;
09589 case PRI_EVENT_SETUP_ACK:
09590 chanpos = pri_find_principle(pri, e->setup_ack.channel);
09591 if (chanpos < 0) {
09592 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
09593 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09594 } else {
09595 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09596 if (chanpos > -1) {
09597 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09598 pri->pvts[chanpos]->setup_ack = 1;
09599
09600 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09601 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09602 pri_information(pri->pri, pri->pvts[chanpos]->call,
09603 pri->pvts[chanpos]->dialdest[x]);
09604 }
09605 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09606 } else
09607 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09608 }
09609 break;
09610 case PRI_EVENT_NOTIFY:
09611 chanpos = pri_find_principle(pri, e->notify.channel);
09612 if (chanpos < 0) {
09613 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09614 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09615 } else {
09616 struct ast_frame f = { AST_FRAME_CONTROL, };
09617 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09618 switch (e->notify.info) {
09619 case PRI_NOTIFY_REMOTE_HOLD:
09620 f.subclass = AST_CONTROL_HOLD;
09621 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09622 break;
09623 case PRI_NOTIFY_REMOTE_RETRIEVAL:
09624 f.subclass = AST_CONTROL_UNHOLD;
09625 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09626 break;
09627 }
09628 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09629 }
09630 break;
09631 default:
09632 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09633 }
09634 }
09635 ast_mutex_unlock(&pri->lock);
09636 }
09637
09638 return NULL;
09639 }
09640
09641 static int start_pri(struct dahdi_pri *pri)
09642 {
09643 int res, x;
09644 struct dahdi_params p;
09645 struct dahdi_bufferinfo bi;
09646 struct dahdi_spaninfo si;
09647 int i;
09648
09649 for (i = 0; i < NUM_DCHANS; i++) {
09650 if (!pri->dchannels[i])
09651 break;
09652 pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
09653 x = pri->dchannels[i];
09654 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09655 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09656 return -1;
09657 }
09658 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09659 if (res) {
09660 dahdi_close_pri_fd(pri, i);
09661 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09662 return -1;
09663 }
09664 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
09665 dahdi_close_pri_fd(pri, i);
09666 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
09667 return -1;
09668 }
09669 memset(&si, 0, sizeof(si));
09670 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
09671 if (res) {
09672 dahdi_close_pri_fd(pri, i);
09673 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
09674 }
09675 if (!si.alarms)
09676 pri->dchanavail[i] |= DCHAN_NOTINALARM;
09677 else
09678 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
09679 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
09680 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
09681 bi.numbufs = 32;
09682 bi.bufsize = 1024;
09683 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
09684 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
09685 dahdi_close_pri_fd(pri, i);
09686 return -1;
09687 }
09688 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
09689
09690 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
09691 pri->overlapdial = 1;
09692 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
09693 #ifdef HAVE_PRI_INBANDDISCONNECT
09694 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
09695 #endif
09696
09697 if (i)
09698 pri_enslave(pri->dchans[0], pri->dchans[i]);
09699 if (!pri->dchans[i]) {
09700 dahdi_close_pri_fd(pri, i);
09701 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
09702 return -1;
09703 }
09704 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
09705 pri_set_nsf(pri->dchans[i], pri->nsf);
09706 #ifdef PRI_GETSET_TIMERS
09707 for (x = 0; x < PRI_MAX_TIMERS; x++) {
09708 if (pritimers[x] != 0)
09709 pri_set_timer(pri->dchans[i], x, pritimers[x]);
09710 }
09711 #endif
09712 }
09713
09714 pri->pri = pri->dchans[0];
09715 pri->resetpos = -1;
09716 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
09717 for (i = 0; i < NUM_DCHANS; i++) {
09718 if (!pri->dchannels[i])
09719 break;
09720 dahdi_close_pri_fd(pri, i);
09721 }
09722 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
09723 return -1;
09724 }
09725 return 0;
09726 }
09727
09728 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
09729 {
09730 int which, span;
09731 char *ret = NULL;
09732
09733 if (pos != rpos)
09734 return ret;
09735
09736 for (which = span = 0; span < NUM_SPANS; span++) {
09737 if (pris[span].pri && ++which > state) {
09738 if (asprintf(&ret, "%d", span + 1) < 0) {
09739 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
09740 }
09741 break;
09742 }
09743 }
09744 return ret;
09745 }
09746
09747 static char *complete_span_4(const char *line, const char *word, int pos, int state)
09748 {
09749 return complete_span_helper(line,word,pos,state,3);
09750 }
09751
09752 static char *complete_span_5(const char *line, const char *word, int pos, int state)
09753 {
09754 return complete_span_helper(line,word,pos,state,4);
09755 }
09756
09757 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
09758 {
09759 int myfd;
09760
09761 if (!strncasecmp(argv[1], "set", 3)) {
09762 if (argc < 5)
09763 return RESULT_SHOWUSAGE;
09764
09765 if (ast_strlen_zero(argv[4]))
09766 return RESULT_SHOWUSAGE;
09767
09768 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
09769 if (myfd < 0) {
09770 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
09771 return RESULT_SUCCESS;
09772 }
09773
09774 ast_mutex_lock(&pridebugfdlock);
09775
09776 if (pridebugfd >= 0)
09777 close(pridebugfd);
09778
09779 pridebugfd = myfd;
09780 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
09781
09782 ast_mutex_unlock(&pridebugfdlock);
09783
09784 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
09785 } else {
09786
09787 ast_mutex_lock(&pridebugfdlock);
09788 close(pridebugfd);
09789 pridebugfd = -1;
09790 ast_cli(fd, "PRI debug output to file disabled\n");
09791 ast_mutex_unlock(&pridebugfdlock);
09792 }
09793
09794 return RESULT_SUCCESS;
09795 }
09796
09797 #ifdef HAVE_PRI_VERSION
09798 static int handle_pri_version(int fd, int agc, char *argv[]) {
09799 ast_cli(fd, "libpri version: %s\n", pri_get_version());
09800 return RESULT_SUCCESS;
09801 }
09802 #endif
09803
09804 static int handle_pri_debug(int fd, int argc, char *argv[])
09805 {
09806 int span;
09807 int x;
09808 if (argc < 4) {
09809 return RESULT_SHOWUSAGE;
09810 }
09811 span = atoi(argv[3]);
09812 if ((span < 1) || (span > NUM_SPANS)) {
09813 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
09814 return RESULT_SUCCESS;
09815 }
09816 if (!pris[span-1].pri) {
09817 ast_cli(fd, "No PRI running on span %d\n", span);
09818 return RESULT_SUCCESS;
09819 }
09820 for (x = 0; x < NUM_DCHANS; x++) {
09821 if (pris[span-1].dchans[x])
09822 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09823 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09824 PRI_DEBUG_Q921_STATE);
09825 }
09826 ast_cli(fd, "Enabled debugging on span %d\n", span);
09827 return RESULT_SUCCESS;
09828 }
09829
09830
09831
09832 static int handle_pri_no_debug(int fd, int argc, char *argv[])
09833 {
09834 int span;
09835 int x;
09836 if (argc < 5)
09837 return RESULT_SHOWUSAGE;
09838 span = atoi(argv[4]);
09839 if ((span < 1) || (span > NUM_SPANS)) {
09840 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09841 return RESULT_SUCCESS;
09842 }
09843 if (!pris[span-1].pri) {
09844 ast_cli(fd, "No PRI running on span %d\n", span);
09845 return RESULT_SUCCESS;
09846 }
09847 for (x = 0; x < NUM_DCHANS; x++) {
09848 if (pris[span-1].dchans[x])
09849 pri_set_debug(pris[span-1].dchans[x], 0);
09850 }
09851 ast_cli(fd, "Disabled debugging on span %d\n", span);
09852 return RESULT_SUCCESS;
09853 }
09854
09855 static int handle_pri_really_debug(int fd, int argc, char *argv[])
09856 {
09857 int span;
09858 int x;
09859 if (argc < 5)
09860 return RESULT_SHOWUSAGE;
09861 span = atoi(argv[4]);
09862 if ((span < 1) || (span > NUM_SPANS)) {
09863 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09864 return RESULT_SUCCESS;
09865 }
09866 if (!pris[span-1].pri) {
09867 ast_cli(fd, "No PRI running on span %d\n", span);
09868 return RESULT_SUCCESS;
09869 }
09870 for (x = 0; x < NUM_DCHANS; x++) {
09871 if (pris[span-1].dchans[x])
09872 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09873 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09874 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
09875 }
09876 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
09877 return RESULT_SUCCESS;
09878 }
09879
09880 static void build_status(char *s, size_t len, int status, int active)
09881 {
09882 if (!s || len < 1) {
09883 return;
09884 }
09885 s[0] = '\0';
09886 if (status & DCHAN_PROVISIONED)
09887 strncat(s, "Provisioned, ", len - strlen(s) - 1);
09888 if (!(status & DCHAN_NOTINALARM))
09889 strncat(s, "In Alarm, ", len - strlen(s) - 1);
09890 if (status & DCHAN_UP)
09891 strncat(s, "Up", len - strlen(s) - 1);
09892 else
09893 strncat(s, "Down", len - strlen(s) - 1);
09894 if (active)
09895 strncat(s, ", Active", len - strlen(s) - 1);
09896 else
09897 strncat(s, ", Standby", len - strlen(s) - 1);
09898 s[len - 1] = '\0';
09899 }
09900
09901 static int handle_pri_show_spans(int fd, int argc, char *argv[])
09902 {
09903 int span;
09904 int x;
09905 char status[256];
09906 if (argc != 3)
09907 return RESULT_SHOWUSAGE;
09908
09909 for (span = 0; span < NUM_SPANS; span++) {
09910 if (pris[span].pri) {
09911 for (x = 0; x < NUM_DCHANS; x++) {
09912 if (pris[span].dchannels[x]) {
09913 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
09914 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
09915 }
09916 }
09917 }
09918 }
09919 return RESULT_SUCCESS;
09920 }
09921
09922 static int handle_pri_show_span(int fd, int argc, char *argv[])
09923 {
09924 int span;
09925 int x;
09926 char status[256];
09927 if (argc < 4)
09928 return RESULT_SHOWUSAGE;
09929 span = atoi(argv[3]);
09930 if ((span < 1) || (span > NUM_SPANS)) {
09931 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
09932 return RESULT_SUCCESS;
09933 }
09934 if (!pris[span-1].pri) {
09935 ast_cli(fd, "No PRI running on span %d\n", span);
09936 return RESULT_SUCCESS;
09937 }
09938 for (x = 0; x < NUM_DCHANS; x++) {
09939 if (pris[span-1].dchannels[x]) {
09940 #ifdef PRI_DUMP_INFO_STR
09941 char *info_str = NULL;
09942 #endif
09943 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
09944 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
09945 ast_cli(fd, "Status: %s\n", status);
09946 #ifdef PRI_DUMP_INFO_STR
09947 info_str = pri_dump_info_str(pris[span-1].pri);
09948 if (info_str) {
09949 ast_cli(fd, "%s", info_str);
09950 free(info_str);
09951 }
09952 #else
09953 pri_dump_info(pris[span-1].pri);
09954 #endif
09955 ast_cli(fd, "\n");
09956 }
09957 }
09958 return RESULT_SUCCESS;
09959 }
09960
09961 static int handle_pri_show_debug(int fd, int argc, char *argv[])
09962 {
09963 int x;
09964 int span;
09965 int count=0;
09966 int debug=0;
09967
09968 for (span = 0; span < NUM_SPANS; span++) {
09969 if (pris[span].pri) {
09970 for (x = 0; x < NUM_DCHANS; x++) {
09971 debug = 0;
09972 if (pris[span].dchans[x]) {
09973 debug = pri_get_debug(pris[span].dchans[x]);
09974 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
09975 count++;
09976 }
09977 }
09978 }
09979
09980 }
09981 ast_mutex_lock(&pridebugfdlock);
09982 if (pridebugfd >= 0)
09983 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
09984 ast_mutex_unlock(&pridebugfdlock);
09985
09986 if (!count)
09987 ast_cli(fd, "No debug set or no PRI running\n");
09988 return RESULT_SUCCESS;
09989 }
09990
09991 static const char pri_debug_help[] =
09992 "Usage: pri debug span <span>\n"
09993 " Enables debugging on a given PRI span\n";
09994
09995 static const char pri_no_debug_help[] =
09996 "Usage: pri no debug span <span>\n"
09997 " Disables debugging on a given PRI span\n";
09998
09999 static const char pri_really_debug_help[] =
10000 "Usage: pri intensive debug span <span>\n"
10001 " Enables debugging down to the Q.921 level\n";
10002
10003 static const char pri_show_span_help[] =
10004 "Usage: pri show span <span>\n"
10005 " Displays PRI Information on a given PRI span\n";
10006
10007 static const char pri_show_spans_help[] =
10008 "Usage: pri show spans\n"
10009 " Displays PRI Information\n";
10010
10011 static struct ast_cli_entry dahdi_pri_cli[] = {
10012 { { "pri", "debug", "span", NULL },
10013 handle_pri_debug, "Enables PRI debugging on a span",
10014 pri_debug_help, complete_span_4 },
10015
10016 { { "pri", "no", "debug", "span", NULL },
10017 handle_pri_no_debug, "Disables PRI debugging on a span",
10018 pri_no_debug_help, complete_span_5 },
10019
10020 { { "pri", "intense", "debug", "span", NULL },
10021 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10022 pri_really_debug_help, complete_span_5 },
10023
10024 { { "pri", "show", "spans", NULL },
10025 handle_pri_show_spans, "Displays PRI Information",
10026 pri_show_spans_help },
10027
10028 { { "pri", "show", "span", NULL },
10029 handle_pri_show_span, "Displays PRI Information",
10030 pri_show_span_help, complete_span_4 },
10031
10032 { { "pri", "show", "debug", NULL },
10033 handle_pri_show_debug, "Displays current PRI debug settings" },
10034
10035 { { "pri", "set", "debug", "file", NULL },
10036 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10037
10038 { { "pri", "unset", "debug", "file", NULL },
10039 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10040
10041 #ifdef HAVE_PRI_VERSION
10042 { { "pri", "show", "version", NULL },
10043 handle_pri_version, "Displays version of libpri" },
10044 #endif
10045 };
10046
10047 #endif
10048
10049 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10050 {
10051 int channel;
10052
10053 if (argc != 4)
10054 return RESULT_SHOWUSAGE;
10055
10056 channel = atoi(argv[3]);
10057
10058 return dahdi_destroy_channel_bynum(channel);
10059 }
10060
10061 static void dahdi_softhangup_all(void)
10062 {
10063 struct dahdi_pvt *p;
10064 retry:
10065 ast_mutex_lock(&iflock);
10066 for (p = iflist; p; p = p->next) {
10067 ast_mutex_lock(&p->lock);
10068 if (p->owner && !p->restartpending) {
10069 if (ast_channel_trylock(p->owner)) {
10070 if (option_debug > 2)
10071 ast_verbose("Avoiding deadlock\n");
10072
10073 ast_mutex_unlock(&p->lock);
10074 ast_mutex_unlock(&iflock);
10075 goto retry;
10076 }
10077 if (option_debug > 2)
10078 ast_verbose("Softhanging up on %s\n", p->owner->name);
10079 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10080 p->restartpending = 1;
10081 num_restart_pending++;
10082 ast_channel_unlock(p->owner);
10083 }
10084 ast_mutex_unlock(&p->lock);
10085 }
10086 ast_mutex_unlock(&iflock);
10087 }
10088
10089 static int setup_dahdi(int reload);
10090 static int dahdi_restart(void)
10091 {
10092 #if defined(HAVE_PRI)
10093 int i, j;
10094 #endif
10095 int cancel_code;
10096 struct dahdi_pvt *p;
10097
10098 ast_mutex_lock(&restart_lock);
10099
10100 if (option_verbose)
10101 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10102 dahdi_softhangup_all();
10103 if (option_verbose > 3)
10104 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10105
10106 #if defined(HAVE_PRI)
10107 for (i = 0; i < NUM_SPANS; i++) {
10108 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10109 cancel_code = pthread_cancel(pris[i].master);
10110 pthread_kill(pris[i].master, SIGURG);
10111 if (option_debug > 3)
10112 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10113 pthread_join(pris[i].master, NULL);
10114 if (option_debug > 3)
10115 ast_verbose("Joined thread of span %d\n", i);
10116 }
10117 }
10118 #endif
10119
10120 ast_mutex_lock(&monlock);
10121 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10122 cancel_code = pthread_cancel(monitor_thread);
10123 pthread_kill(monitor_thread, SIGURG);
10124 if (option_debug > 3)
10125 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10126 pthread_join(monitor_thread, NULL);
10127 if (option_debug > 3)
10128 ast_verbose("Joined monitor thread\n");
10129 }
10130 monitor_thread = AST_PTHREADT_NULL;
10131
10132 ast_mutex_lock(&ss_thread_lock);
10133 while (ss_thread_count > 0) {
10134 int x = DAHDI_FLASH;
10135 if (option_debug > 2)
10136 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10137
10138 for (p = iflist; p; p = p->next) {
10139 if (p->owner)
10140 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10141 }
10142 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10143 }
10144
10145
10146 dahdi_softhangup_all();
10147 if (option_verbose > 3)
10148 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10149 destroy_all_channels();
10150 if (option_debug)
10151 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10152
10153 ast_mutex_unlock(&monlock);
10154
10155 #ifdef HAVE_PRI
10156 for (i = 0; i < NUM_SPANS; i++) {
10157 for (j = 0; j < NUM_DCHANS; j++)
10158 dahdi_close_pri_fd(&(pris[i]), j);
10159 }
10160
10161 memset(pris, 0, sizeof(pris));
10162 for (i = 0; i < NUM_SPANS; i++) {
10163 ast_mutex_init(&pris[i].lock);
10164 pris[i].offset = -1;
10165 pris[i].master = AST_PTHREADT_NULL;
10166 for (j = 0; j < NUM_DCHANS; j++)
10167 pris[i].fds[j] = -1;
10168 }
10169 pri_set_error(dahdi_pri_error);
10170 pri_set_message(dahdi_pri_message);
10171 #endif
10172
10173 if (setup_dahdi(2) != 0) {
10174 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10175 ast_mutex_unlock(&ss_thread_lock);
10176 return 1;
10177 }
10178 ast_mutex_unlock(&ss_thread_lock);
10179 ast_mutex_unlock(&restart_lock);
10180 return 0;
10181 }
10182
10183 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10184 {
10185 if (argc != 2) {
10186 return RESULT_SHOWUSAGE;
10187 }
10188
10189 if (dahdi_restart() != 0)
10190 return RESULT_FAILURE;
10191 return RESULT_SUCCESS;
10192 }
10193
10194 static int dahdi_show_channels(int fd, int argc, char **argv)
10195 {
10196 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10197 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10198 struct dahdi_pvt *tmp = NULL;
10199 char tmps[20] = "";
10200 ast_mutex_t *lock;
10201 struct dahdi_pvt *start;
10202 #ifdef HAVE_PRI
10203 int trunkgroup;
10204 struct dahdi_pri *pri = NULL;
10205 int x;
10206 #endif
10207
10208 lock = &iflock;
10209 start = iflist;
10210
10211 #ifdef HAVE_PRI
10212 if (argc == 4) {
10213 if ((trunkgroup = atoi(argv[3])) < 1)
10214 return RESULT_SHOWUSAGE;
10215 for (x = 0; x < NUM_SPANS; x++) {
10216 if (pris[x].trunkgroup == trunkgroup) {
10217 pri = pris + x;
10218 break;
10219 }
10220 }
10221 if (pri) {
10222 start = pri->crvs;
10223 lock = &pri->lock;
10224 } else {
10225 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10226 return RESULT_FAILURE;
10227 }
10228 } else
10229 #endif
10230 if (argc != 3)
10231 return RESULT_SHOWUSAGE;
10232
10233 ast_mutex_lock(lock);
10234 #ifdef HAVE_PRI
10235 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10236 #else
10237 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10238 #endif
10239
10240 tmp = start;
10241 while (tmp) {
10242 if (tmp->channel > 0) {
10243 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10244 } else
10245 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10246 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10247 tmp = tmp->next;
10248 }
10249 ast_mutex_unlock(lock);
10250 return RESULT_SUCCESS;
10251 #undef FORMAT
10252 #undef FORMAT2
10253 }
10254
10255 static int dahdi_show_channel(int fd, int argc, char **argv)
10256 {
10257 int channel;
10258 struct dahdi_pvt *tmp = NULL;
10259 struct dahdi_confinfo ci;
10260 struct dahdi_params ps;
10261 int x;
10262 ast_mutex_t *lock;
10263 struct dahdi_pvt *start;
10264 #ifdef HAVE_PRI
10265 char *c;
10266 int trunkgroup;
10267 struct dahdi_pri *pri=NULL;
10268 #endif
10269
10270 lock = &iflock;
10271 start = iflist;
10272
10273 if (argc != 4)
10274 return RESULT_SHOWUSAGE;
10275 #ifdef HAVE_PRI
10276 if ((c = strchr(argv[3], ':'))) {
10277 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10278 return RESULT_SHOWUSAGE;
10279 if ((trunkgroup < 1) || (channel < 1))
10280 return RESULT_SHOWUSAGE;
10281 for (x = 0; x < NUM_SPANS; x++) {
10282 if (pris[x].trunkgroup == trunkgroup) {
10283 pri = pris + x;
10284 break;
10285 }
10286 }
10287 if (pri) {
10288 start = pri->crvs;
10289 lock = &pri->lock;
10290 } else {
10291 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10292 return RESULT_FAILURE;
10293 }
10294 } else
10295 #endif
10296 channel = atoi(argv[3]);
10297
10298 ast_mutex_lock(lock);
10299 tmp = start;
10300 while (tmp) {
10301 if (tmp->channel == channel) {
10302 #ifdef HAVE_PRI
10303 if (pri)
10304 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10305 else
10306 #endif
10307 ast_cli(fd, "Channel: %d\n", tmp->channel);
10308 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10309 ast_cli(fd, "Span: %d\n", tmp->span);
10310 ast_cli(fd, "Extension: %s\n", tmp->exten);
10311 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10312 ast_cli(fd, "Context: %s\n", tmp->context);
10313 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10314 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10315 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10316 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10317 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10318 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10319 ast_cli(fd, "Radio: %d\n", tmp->radio);
10320 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10321 ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
10322 ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
10323 ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
10324 ast_cli(fd, "Confno: %d\n", tmp->confno);
10325 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10326 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10327 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10328 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10329 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10330 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10331 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10332 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10333 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10334 if (tmp->master)
10335 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10336 for (x = 0; x < MAX_SLAVES; x++) {
10337 if (tmp->slaves[x])
10338 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10339 }
10340 #ifdef HAVE_PRI
10341 if (tmp->pri) {
10342 ast_cli(fd, "PRI Flags: ");
10343 if (tmp->resetting)
10344 ast_cli(fd, "Resetting ");
10345 if (tmp->call)
10346 ast_cli(fd, "Call ");
10347 if (tmp->bearer)
10348 ast_cli(fd, "Bearer ");
10349 ast_cli(fd, "\n");
10350 if (tmp->logicalspan)
10351 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10352 else
10353 ast_cli(fd, "PRI Logical Span: Implicit\n");
10354 }
10355
10356 #endif
10357 memset(&ci, 0, sizeof(ci));
10358 ps.channo = tmp->channel;
10359 if (tmp->subs[SUB_REAL].dfd > -1) {
10360 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10361 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10362 }
10363 #ifdef DAHDI_GETCONFMUTE
10364 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10365 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10366 }
10367 #endif
10368 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10369 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10370 } else {
10371 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10372 }
10373 }
10374 if (ISTRUNK(tmp)) {
10375 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
10376 if (!ast_strlen_zero(progzone))
10377 ast_cli(fd, "Progress Zone: %s\n", progzone);
10378 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
10379 if(tmp->busydetect) {
10380 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10381 if(tmp->busytonelength > 0) {
10382 ast_cli(fd, "Busy Pattern:\n");
10383 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10384 if (tmp->busyquietlength > 0)
10385 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10386 else
10387 ast_cli(fd, " -- Detect Tone Only\n");
10388 if(tmp->busyfuzziness > 0)
10389 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10390 }
10391 }
10392 }
10393 ast_mutex_unlock(lock);
10394 return RESULT_SUCCESS;
10395 }
10396 tmp = tmp->next;
10397 }
10398
10399 ast_cli(fd, "Unable to find given channel %d\n", channel);
10400 ast_mutex_unlock(lock);
10401 return RESULT_FAILURE;
10402 }
10403
10404 static char dahdi_show_cadences_usage[] =
10405 "Usage: dahdi show cadences\n"
10406 " Shows all cadences currently defined\n";
10407
10408 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10409 {
10410 int i, j;
10411 for (i = 0; i < num_cadence; i++) {
10412 char output[1024];
10413 char tmp[16], tmp2[64];
10414 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10415 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10416
10417 for (j = 0; j < 16; j++) {
10418 if (cadences[i].ringcadence[j] == 0)
10419 break;
10420 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10421 if (cidrings[i] * 2 - 1 == j)
10422 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10423 else
10424 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10425 if (j != 0)
10426 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10427 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10428 }
10429 ast_cli(fd,"%s\n",output);
10430 }
10431 return 0;
10432 }
10433
10434
10435 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10436 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10437 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10438
10439 int span;
10440 int res;
10441 char alarms[50];
10442
10443 int ctl;
10444 struct dahdi_spaninfo s;
10445
10446 if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10447 ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10448 ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10449 return RESULT_FAILURE;
10450 }
10451 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10452
10453 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10454 s.spanno = span;
10455 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10456 if (res) {
10457 continue;
10458 }
10459 alarms[0] = '\0';
10460 if (s.alarms > 0) {
10461 if (s.alarms & DAHDI_ALARM_BLUE)
10462 strcat(alarms, "BLU/");
10463 if (s.alarms & DAHDI_ALARM_YELLOW)
10464 strcat(alarms, "YEL/");
10465 if (s.alarms & DAHDI_ALARM_RED)
10466 strcat(alarms, "RED/");
10467 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10468 strcat(alarms, "LB/");
10469 if (s.alarms & DAHDI_ALARM_RECOVER)
10470 strcat(alarms, "REC/");
10471 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10472 strcat(alarms, "NOP/");
10473 if (!strlen(alarms))
10474 strcat(alarms, "UUU/");
10475 if (strlen(alarms)) {
10476
10477 alarms[strlen(alarms) - 1] = '\0';
10478 }
10479 } else {
10480 if (s.numchans)
10481 strcpy(alarms, "OK");
10482 else
10483 strcpy(alarms, "UNCONFIGURED");
10484 }
10485
10486 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10487 }
10488 close(ctl);
10489
10490 return RESULT_SUCCESS;
10491 #undef FORMAT
10492 #undef FORMAT2
10493 }
10494
10495 static char show_channels_usage[] =
10496 "Usage: dahdi show channels\n"
10497 " Shows a list of available channels\n";
10498
10499 static char show_channel_usage[] =
10500 "Usage: dahdi show channel <chan num>\n"
10501 " Detailed information about a given channel\n";
10502
10503 static char dahdi_show_status_usage[] =
10504 "Usage: dahdi show status\n"
10505 " Shows a list of DAHDI cards with status\n";
10506
10507 static char destroy_channel_usage[] =
10508 "Usage: dahdi destroy channel <chan num>\n"
10509 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10510
10511 static char dahdi_restart_usage[] =
10512 "Usage: dahdi restart\n"
10513 " Restarts the DAHDI channels: destroys them all and then\n"
10514 " re-reads them from chan_dahdi.conf.\n"
10515 " Note that this will STOP any running CALL on DAHDI channels.\n"
10516 "";
10517
10518 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10519 { "zap", "show", "cadences", NULL },
10520 handle_dahdi_show_cadences, NULL,
10521 NULL };
10522
10523 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10524 { "zap", "show", "channels", NULL },
10525 dahdi_show_channels, NULL,
10526 NULL };
10527
10528 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10529 { "zap", "show", "channel", NULL },
10530 dahdi_show_channel, NULL,
10531 NULL };
10532
10533 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10534 { "zap", "destroy", "channel", NULL },
10535 dahdi_destroy_channel, NULL,
10536 NULL };
10537
10538 static struct ast_cli_entry cli_zap_restart_deprecated = {
10539 { "zap", "restart", NULL },
10540 dahdi_restart_cmd, NULL,
10541 NULL };
10542
10543 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10544 { "zap", "show", "status", NULL },
10545 dahdi_show_status, NULL,
10546 NULL };
10547
10548 static struct ast_cli_entry dahdi_cli[] = {
10549 { { "dahdi", "show", "cadences", NULL },
10550 handle_dahdi_show_cadences, "List cadences",
10551 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10552
10553 { { "dahdi", "show", "channels", NULL},
10554 dahdi_show_channels, "Show active DAHDI channels",
10555 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10556
10557 { { "dahdi", "show", "channel", NULL},
10558 dahdi_show_channel, "Show information on a channel",
10559 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10560
10561 { { "dahdi", "destroy", "channel", NULL},
10562 dahdi_destroy_channel, "Destroy a channel",
10563 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10564
10565 { { "dahdi", "restart", NULL},
10566 dahdi_restart_cmd, "Fully restart DAHDI channels",
10567 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10568
10569 { { "dahdi", "show", "status", NULL},
10570 dahdi_show_status, "Show all DAHDI cards status",
10571 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10572 };
10573
10574 #define TRANSFER 0
10575 #define HANGUP 1
10576
10577 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10578 {
10579 if (p) {
10580 switch (mode) {
10581 case TRANSFER:
10582 p->fake_event = DAHDI_EVENT_WINKFLASH;
10583 break;
10584 case HANGUP:
10585 p->fake_event = DAHDI_EVENT_ONHOOK;
10586 break;
10587 default:
10588 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10589 }
10590 }
10591 return 0;
10592 }
10593 static struct dahdi_pvt *find_channel(int channel)
10594 {
10595 struct dahdi_pvt *p = iflist;
10596 while (p) {
10597 if (p->channel == channel) {
10598 break;
10599 }
10600 p = p->next;
10601 }
10602 return p;
10603 }
10604
10605 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10606 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10607
10608 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10609 {
10610 struct dahdi_pvt *p = NULL;
10611 const char *channel = local_astman_header(m, "Channel", zap_mode);
10612
10613 if (ast_strlen_zero(channel)) {
10614 astman_send_error(s, m, "No channel specified");
10615 return 0;
10616 }
10617 if (!(p = find_channel(atoi(channel)))) {
10618 astman_send_error(s, m, "No such channel");
10619 return 0;
10620 }
10621 p->dnd = dnd;
10622 local_astman_ack(s, m, "DND", zap_mode);
10623
10624 return 0;
10625 }
10626
10627 static int zap_action_dndon(struct mansession *s, const struct message *m)
10628 {
10629 return __action_dnd(s, m, 1, 1);
10630 }
10631
10632 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10633 {
10634 return __action_dnd(s, m, 0, 1);
10635 }
10636
10637 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10638 {
10639 return __action_dnd(s, m, 1, 0);
10640 }
10641
10642 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10643 {
10644 return __action_dnd(s, m, 0, 0);
10645 }
10646
10647 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10648 {
10649 struct dahdi_pvt *p = NULL;
10650 const char *channel = local_astman_header(m, "Channel", zap_mode);
10651
10652 if (ast_strlen_zero(channel)) {
10653 astman_send_error(s, m, "No channel specified");
10654 return 0;
10655 }
10656 if (!(p = find_channel(atoi(channel)))) {
10657 astman_send_error(s, m, "No such channel");
10658 return 0;
10659 }
10660 dahdi_fake_event(p,TRANSFER);
10661 local_astman_ack(s, m, "Transfer", zap_mode);
10662
10663 return 0;
10664 }
10665
10666 static int zap_action_transfer(struct mansession *s, const struct message *m)
10667 {
10668 return __action_transfer(s, m, 1);
10669 }
10670
10671 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10672 {
10673 return __action_transfer(s, m, 0);
10674 }
10675
10676 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10677 {
10678 struct dahdi_pvt *p = NULL;
10679 const char *channel = local_astman_header(m, "Channel", zap_mode);
10680
10681 if (ast_strlen_zero(channel)) {
10682 astman_send_error(s, m, "No channel specified");
10683 return 0;
10684 }
10685 if (!(p = find_channel(atoi(channel)))) {
10686 astman_send_error(s, m, "No such channel");
10687 return 0;
10688 }
10689 dahdi_fake_event(p, HANGUP);
10690 local_astman_ack(s, m, "Hangup", zap_mode);
10691 return 0;
10692 }
10693
10694 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10695 {
10696 return __action_transferhangup(s, m, 1);
10697 }
10698
10699 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10700 {
10701 return __action_transferhangup(s, m, 0);
10702 }
10703
10704 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10705 {
10706 struct dahdi_pvt *p = NULL;
10707 const char *channel = local_astman_header(m, "Channel", zap_mode);
10708 const char *number = astman_get_header(m, "Number");
10709 int i;
10710
10711 if (ast_strlen_zero(channel)) {
10712 astman_send_error(s, m, "No channel specified");
10713 return 0;
10714 }
10715 if (ast_strlen_zero(number)) {
10716 astman_send_error(s, m, "No number specified");
10717 return 0;
10718 }
10719 if (!(p = find_channel(atoi(channel)))) {
10720 astman_send_error(s, m, "No such channel");
10721 return 0;
10722 }
10723 if (!p->owner) {
10724 astman_send_error(s, m, "Channel does not have an owner");
10725 return 0;
10726 }
10727 for (i = 0; i < strlen(number); i++) {
10728 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10729
10730 dahdi_queue_frame(p, &f, NULL);
10731 }
10732 local_astman_ack(s, m, "DialOffHook", zap_mode);
10733
10734 return 0;
10735 }
10736
10737 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10738 {
10739 return __action_dialoffhook(s, m, 1);
10740 }
10741
10742 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10743 {
10744 return __action_dialoffhook(s, m, 0);
10745 }
10746
10747 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10748 {
10749 struct dahdi_pvt *tmp = NULL;
10750 const char *id = astman_get_header(m, "ActionID");
10751 char idText[256] = "";
10752
10753 local_astman_ack(s, m, " channel status will follow", zap_mode);
10754 if (!ast_strlen_zero(id))
10755 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10756
10757 ast_mutex_lock(&iflock);
10758
10759 tmp = iflist;
10760 while (tmp) {
10761 if (tmp->channel > 0) {
10762 int alarm = get_alarms(tmp);
10763 astman_append(s,
10764 "Event: %sShowChannels\r\n"
10765 "Channel: %d\r\n"
10766 "Signalling: %s\r\n"
10767 "Context: %s\r\n"
10768 "DND: %s\r\n"
10769 "Alarm: %s\r\n"
10770 "%s"
10771 "\r\n",
10772 dahdi_chan_name,
10773 tmp->channel, sig2str(tmp->sig), tmp->context,
10774 tmp->dnd ? "Enabled" : "Disabled",
10775 alarm2str(alarm), idText);
10776 }
10777
10778 tmp = tmp->next;
10779 }
10780
10781 ast_mutex_unlock(&iflock);
10782
10783 astman_append(s,
10784 "Event: %sShowChannelsComplete\r\n"
10785 "%s"
10786 "\r\n",
10787 dahdi_chan_name,
10788 idText);
10789 return 0;
10790 }
10791
10792 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10793 {
10794 return __action_showchannels(s, m, 1);
10795 }
10796
10797 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10798 {
10799 return __action_showchannels(s, m, 0);
10800 }
10801
10802 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10803 {
10804 if (dahdi_restart() != 0) {
10805 if (zap_mode) {
10806 astman_send_error(s, m, "Failed to restart Zap");
10807 } else {
10808 astman_send_error(s, m, "Failed to restart DAHDI");
10809 }
10810 return 1;
10811 }
10812 local_astman_ack(s, m, "Restart: Success", zap_mode);
10813 return 0;
10814 }
10815
10816 static int zap_action_restart(struct mansession *s, const struct message *m)
10817 {
10818 return __action_restart(s, m, 1);
10819 }
10820
10821 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10822 {
10823 return __action_restart(s, m, 0);
10824 }
10825
10826 #define local_astman_unregister(a) do { \
10827 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10828 ast_manager_unregister("DAHDI" a); \
10829 } \
10830 ast_manager_unregister("Zap" a); \
10831 } while (0)
10832
10833 static int __unload_module(void)
10834 {
10835 struct dahdi_pvt *p;
10836
10837 #ifdef HAVE_PRI
10838 int i, j;
10839 for (i = 0; i < NUM_SPANS; i++) {
10840 if (pris[i].master != AST_PTHREADT_NULL)
10841 pthread_cancel(pris[i].master);
10842 }
10843 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10844
10845 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10846 ast_unregister_application(dahdi_send_keypad_facility_app);
10847 }
10848 ast_unregister_application(zap_send_keypad_facility_app);
10849 #endif
10850 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10851 local_astman_unregister("DialOffHook");
10852 local_astman_unregister("Hangup");
10853 local_astman_unregister("Transfer");
10854 local_astman_unregister("DNDoff");
10855 local_astman_unregister("DNDon");
10856 local_astman_unregister("ShowChannels");
10857 local_astman_unregister("Restart");
10858 ast_channel_unregister(chan_tech);
10859 ast_mutex_lock(&iflock);
10860
10861 p = iflist;
10862 while (p) {
10863 if (p->owner)
10864 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10865 p = p->next;
10866 }
10867 ast_mutex_unlock(&iflock);
10868 ast_mutex_lock(&monlock);
10869 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10870 pthread_cancel(monitor_thread);
10871 pthread_kill(monitor_thread, SIGURG);
10872 pthread_join(monitor_thread, NULL);
10873 }
10874 monitor_thread = AST_PTHREADT_STOP;
10875 ast_mutex_unlock(&monlock);
10876
10877 destroy_all_channels();
10878 #ifdef HAVE_PRI
10879 for (i = 0; i < NUM_SPANS; i++) {
10880 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10881 pthread_join(pris[i].master, NULL);
10882 for (j = 0; j < NUM_DCHANS; j++) {
10883 dahdi_close_pri_fd(&(pris[i]), j);
10884 }
10885 }
10886 #endif
10887 ast_cond_destroy(&ss_thread_complete);
10888 return 0;
10889 }
10890
10891 static int unload_module(void)
10892 {
10893 #ifdef HAVE_PRI
10894 int y;
10895 for (y = 0; y < NUM_SPANS; y++)
10896 ast_mutex_destroy(&pris[y].lock);
10897 #endif
10898 return __unload_module();
10899 }
10900
10901 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10902 {
10903 char *c, *chan;
10904 int x, start, finish;
10905 struct dahdi_pvt *tmp;
10906 #ifdef HAVE_PRI
10907 struct dahdi_pri *pri;
10908 int trunkgroup, y;
10909 #endif
10910
10911 if ((reload == 0) && (conf->chan.sig < 0)) {
10912 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10913 return -1;
10914 }
10915
10916 c = ast_strdupa(value);
10917
10918 #ifdef HAVE_PRI
10919 pri = NULL;
10920 if (iscrv) {
10921 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10922 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10923 return -1;
10924 }
10925 if (trunkgroup < 1) {
10926 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10927 return -1;
10928 }
10929 c += y;
10930 for (y = 0; y < NUM_SPANS; y++) {
10931 if (pris[y].trunkgroup == trunkgroup) {
10932 pri = pris + y;
10933 break;
10934 }
10935 }
10936 if (!pri) {
10937 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10938 return -1;
10939 }
10940 }
10941 #endif
10942
10943 while ((chan = strsep(&c, ","))) {
10944 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10945
10946 } else if (sscanf(chan, "%d", &start)) {
10947
10948 finish = start;
10949 } else if (!strcasecmp(chan, "pseudo")) {
10950 finish = start = CHAN_PSEUDO;
10951 if (found_pseudo)
10952 *found_pseudo = 1;
10953 } else {
10954 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10955 return -1;
10956 }
10957 if (finish < start) {
10958 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10959 x = finish;
10960 finish = start;
10961 start = x;
10962 }
10963
10964 for (x = start; x <= finish; x++) {
10965 #ifdef HAVE_PRI
10966 tmp = mkintf(x, conf, pri, reload);
10967 #else
10968 tmp = mkintf(x, conf, NULL, reload);
10969 #endif
10970
10971 if (tmp) {
10972 if (option_verbose > 2) {
10973 #ifdef HAVE_PRI
10974 if (pri)
10975 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10976 else
10977 #endif
10978 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10979 }
10980 } else {
10981 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10982 (reload == 1) ? "reconfigure" : "register", value);
10983 return -1;
10984 }
10985 }
10986 }
10987
10988 return 0;
10989 }
10990
10991
10992
10993 #define MAX_CHANLIST_LEN 80
10994 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10995 {
10996 struct dahdi_pvt *tmp;
10997 int y;
10998 int found_pseudo = 0;
10999 char dahdichan[MAX_CHANLIST_LEN] = {};
11000
11001 for (; v; v = v->next) {
11002 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11003 continue;
11004
11005
11006 if (!strcasecmp(v->name, "channel")
11007 #ifdef HAVE_PRI
11008 || !strcasecmp(v->name, "crv")
11009 #endif
11010 ) {
11011 int iscrv;
11012 if (skipchannels)
11013 continue;
11014 iscrv = !strcasecmp(v->name, "crv");
11015 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11016 return -1;
11017 } else if (!strcasecmp(v->name, "buffers")) {
11018 int res;
11019 char policy[21] = "";
11020
11021 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
11022 if (res != 2) {
11023 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11024 confp->chan.buf_no = numbufs;
11025 continue;
11026 }
11027 if (confp->chan.buf_no < 0)
11028 confp->chan.buf_no = numbufs;
11029 if (!strcasecmp(policy, "full")) {
11030 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11031 } else if (!strcasecmp(policy, "immediate")) {
11032 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11033 } else {
11034 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11035 }
11036 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11037 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11038 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11039 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11040 }
11041 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11042 if (ast_true(v->value))
11043 confp->chan.usedistinctiveringdetection = 1;
11044 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11045 if (ast_true(v->value))
11046 distinctiveringaftercid = 1;
11047 } else if (!strcasecmp(v->name, "dring1context")) {
11048 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11049 } else if (!strcasecmp(v->name, "dring2context")) {
11050 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11051 } else if (!strcasecmp(v->name, "dring3context")) {
11052 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11053 } else if (!strcasecmp(v->name, "dring1")) {
11054 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11055 } else if (!strcasecmp(v->name, "dring2")) {
11056 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11057 } else if (!strcasecmp(v->name, "dring3")) {
11058 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11059 } else if (!strcasecmp(v->name, "usecallerid")) {
11060 confp->chan.use_callerid = ast_true(v->value);
11061 } else if (!strcasecmp(v->name, "cidsignalling")) {
11062 if (!strcasecmp(v->value, "bell"))
11063 confp->chan.cid_signalling = CID_SIG_BELL;
11064 else if (!strcasecmp(v->value, "v23"))
11065 confp->chan.cid_signalling = CID_SIG_V23;
11066 else if (!strcasecmp(v->value, "dtmf"))
11067 confp->chan.cid_signalling = CID_SIG_DTMF;
11068 else if (!strcasecmp(v->value, "smdi"))
11069 confp->chan.cid_signalling = CID_SIG_SMDI;
11070 else if (!strcasecmp(v->value, "v23_jp"))
11071 confp->chan.cid_signalling = CID_SIG_V23_JP;
11072 else if (ast_true(v->value))
11073 confp->chan.cid_signalling = CID_SIG_BELL;
11074 } else if (!strcasecmp(v->name, "cidstart")) {
11075 if (!strcasecmp(v->value, "ring"))
11076 confp->chan.cid_start = CID_START_RING;
11077 else if (!strcasecmp(v->value, "polarity"))
11078 confp->chan.cid_start = CID_START_POLARITY;
11079 else if (ast_true(v->value))
11080 confp->chan.cid_start = CID_START_RING;
11081 } else if (!strcasecmp(v->name, "threewaycalling")) {
11082 confp->chan.threewaycalling = ast_true(v->value);
11083 } else if (!strcasecmp(v->name, "cancallforward")) {
11084 confp->chan.cancallforward = ast_true(v->value);
11085 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11086 if (ast_true(v->value))
11087 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11088 else
11089 confp->chan.dtmfrelax = 0;
11090 } else if (!strcasecmp(v->name, "mailbox")) {
11091 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11092 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11093 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11094 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11095 }
11096 } else if (!strcasecmp(v->name, "adsi")) {
11097 confp->chan.adsi = ast_true(v->value);
11098 } else if (!strcasecmp(v->name, "usesmdi")) {
11099 confp->chan.use_smdi = ast_true(v->value);
11100 } else if (!strcasecmp(v->name, "smdiport")) {
11101 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11102 } else if (!strcasecmp(v->name, "transfer")) {
11103 confp->chan.transfer = ast_true(v->value);
11104 } else if (!strcasecmp(v->name, "canpark")) {
11105 confp->chan.canpark = ast_true(v->value);
11106 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11107 confp->chan.echocanbridged = ast_true(v->value);
11108 } else if (!strcasecmp(v->name, "busydetect")) {
11109 confp->chan.busydetect = ast_true(v->value);
11110 } else if (!strcasecmp(v->name, "busycount")) {
11111 confp->chan.busycount = atoi(v->value);
11112 } else if (!strcasecmp(v->name, "silencethreshold")) {
11113 confp->chan.silencethreshold = atoi(v->value);
11114 } else if (!strcasecmp(v->name, "busycompare")) {
11115 confp->chan.busycompare = ast_true(v->value);
11116 } else if (!strcasecmp(v->name, "busypattern")) {
11117 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11118 if (count == 1)
11119 confp->chan.busyquietlength = 0;
11120 else if (count < 1)
11121 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11122 } else if (!strcasecmp(v->name, "busyfuzziness")) {
11123 confp->chan.busyfuzziness = atoi(v->value);
11124 } else if (!strcasecmp(v->name, "callprogress")) {
11125 if (ast_true(v->value))
11126 confp->chan.callprogress |= 1;
11127 else
11128 confp->chan.callprogress &= ~1;
11129 } else if (!strcasecmp(v->name, "faxdetect")) {
11130 if (!strcasecmp(v->value, "incoming")) {
11131 confp->chan.callprogress |= 4;
11132 confp->chan.callprogress &= ~2;
11133 } else if (!strcasecmp(v->value, "outgoing")) {
11134 confp->chan.callprogress &= ~4;
11135 confp->chan.callprogress |= 2;
11136 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11137 confp->chan.callprogress |= 6;
11138 else
11139 confp->chan.callprogress &= ~6;
11140 } else if (!strcasecmp(v->name, "echocancel")) {
11141 if (!ast_strlen_zero(v->value)) {
11142 y = atoi(v->value);
11143 } else
11144 y = 0;
11145 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11146 confp->chan.echocancel = y;
11147 else {
11148 confp->chan.echocancel = ast_true(v->value);
11149 if (confp->chan.echocancel)
11150 confp->chan.echocancel=128;
11151 }
11152 } else if (!strcasecmp(v->name, "echotraining")) {
11153 if (sscanf(v->value, "%d", &y) == 1) {
11154 if ((y < 10) || (y > 4000)) {
11155 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11156 } else {
11157 confp->chan.echotraining = y;
11158 }
11159 } else if (ast_true(v->value)) {
11160 confp->chan.echotraining = 400;
11161 } else
11162 confp->chan.echotraining = 0;
11163 } else if (!strcasecmp(v->name, "hidecallerid")) {
11164 confp->chan.hidecallerid = ast_true(v->value);
11165 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11166 confp->chan.hidecalleridname = ast_true(v->value);
11167 } else if (!strcasecmp(v->name, "pulsedial")) {
11168 confp->chan.pulse = ast_true(v->value);
11169 } else if (!strcasecmp(v->name, "callreturn")) {
11170 confp->chan.callreturn = ast_true(v->value);
11171 } else if (!strcasecmp(v->name, "callwaiting")) {
11172 confp->chan.callwaiting = ast_true(v->value);
11173 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11174 confp->chan.callwaitingcallerid = ast_true(v->value);
11175 } else if (!strcasecmp(v->name, "context")) {
11176 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11177 } else if (!strcasecmp(v->name, "language")) {
11178 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11179 } else if (!strcasecmp(v->name, "progzone")) {
11180 ast_copy_string(progzone, v->value, sizeof(progzone));
11181 } else if (!strcasecmp(v->name, "mohinterpret")
11182 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11183 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11184 } else if (!strcasecmp(v->name, "mohsuggest")) {
11185 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11186 } else if (!strcasecmp(v->name, "stripmsd")) {
11187 confp->chan.stripmsd = atoi(v->value);
11188 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11189 numbufs = atoi(v->value);
11190 } else if (!strcasecmp(v->name, "group")) {
11191 confp->chan.group = ast_get_group(v->value);
11192 } else if (!strcasecmp(v->name, "callgroup")) {
11193 confp->chan.callgroup = ast_get_group(v->value);
11194 } else if (!strcasecmp(v->name, "pickupgroup")) {
11195 confp->chan.pickupgroup = ast_get_group(v->value);
11196 } else if (!strcasecmp(v->name, "immediate")) {
11197 confp->chan.immediate = ast_true(v->value);
11198 } else if (!strcasecmp(v->name, "transfertobusy")) {
11199 confp->chan.transfertobusy = ast_true(v->value);
11200 } else if (!strcasecmp(v->name, "rxgain")) {
11201 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11202 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11203 }
11204 } else if (!strcasecmp(v->name, "txgain")) {
11205 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11206 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11207 }
11208 } else if (!strcasecmp(v->name, "tonezone")) {
11209 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11210 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11211 }
11212 } else if (!strcasecmp(v->name, "callerid")) {
11213 if (!strcasecmp(v->value, "asreceived")) {
11214 confp->chan.cid_num[0] = '\0';
11215 confp->chan.cid_name[0] = '\0';
11216 } else {
11217 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11218 }
11219 } else if (!strcasecmp(v->name, "fullname")) {
11220 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11221 } else if (!strcasecmp(v->name, "cid_number")) {
11222 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11223 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11224 confp->chan.dahditrcallerid = ast_true(v->value);
11225 if (strstr(v->name, "zap")) {
11226 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11227 }
11228 } else if (!strcasecmp(v->name, "restrictcid")) {
11229 confp->chan.restrictcid = ast_true(v->value);
11230 } else if (!strcasecmp(v->name, "usecallingpres")) {
11231 confp->chan.use_callingpres = ast_true(v->value);
11232 } else if (!strcasecmp(v->name, "accountcode")) {
11233 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11234 } else if (!strcasecmp(v->name, "amaflags")) {
11235 y = ast_cdr_amaflags2int(v->value);
11236 if (y < 0)
11237 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11238 else
11239 confp->chan.amaflags = y;
11240 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11241 confp->chan.polarityonanswerdelay = atoi(v->value);
11242 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11243 confp->chan.answeronpolarityswitch = ast_true(v->value);
11244 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11245 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11246 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11247 confp->chan.sendcalleridafter = atoi(v->value);
11248 } else if (reload != 1){
11249 if (!strcasecmp(v->name, "signalling")) {
11250 confp->chan.outsigmod = -1;
11251 if (!strcasecmp(v->value, "em")) {
11252 confp->chan.sig = SIG_EM;
11253 } else if (!strcasecmp(v->value, "em_e1")) {
11254 confp->chan.sig = SIG_EM_E1;
11255 } else if (!strcasecmp(v->value, "em_w")) {
11256 confp->chan.sig = SIG_EMWINK;
11257 confp->chan.radio = 0;
11258 } else if (!strcasecmp(v->value, "fxs_ls")) {
11259 confp->chan.sig = SIG_FXSLS;
11260 confp->chan.radio = 0;
11261 } else if (!strcasecmp(v->value, "fxs_gs")) {
11262 confp->chan.sig = SIG_FXSGS;
11263 confp->chan.radio = 0;
11264 } else if (!strcasecmp(v->value, "fxs_ks")) {
11265 confp->chan.sig = SIG_FXSKS;
11266 confp->chan.radio = 0;
11267 } else if (!strcasecmp(v->value, "fxo_ls")) {
11268 confp->chan.sig = SIG_FXOLS;
11269 confp->chan.radio = 0;
11270 } else if (!strcasecmp(v->value, "fxo_gs")) {
11271 confp->chan.sig = SIG_FXOGS;
11272 confp->chan.radio = 0;
11273 } else if (!strcasecmp(v->value, "fxo_ks")) {
11274 confp->chan.sig = SIG_FXOKS;
11275 confp->chan.radio = 0;
11276 } else if (!strcasecmp(v->value, "fxs_rx")) {
11277 confp->chan.sig = SIG_FXSKS;
11278 confp->chan.radio = 1;
11279 } else if (!strcasecmp(v->value, "fxo_rx")) {
11280 confp->chan.sig = SIG_FXOLS;
11281 confp->chan.radio = 1;
11282 } else if (!strcasecmp(v->value, "fxs_tx")) {
11283 confp->chan.sig = SIG_FXSLS;
11284 confp->chan.radio = 1;
11285 } else if (!strcasecmp(v->value, "fxo_tx")) {
11286 confp->chan.sig = SIG_FXOGS;
11287 confp->chan.radio = 1;
11288 } else if (!strcasecmp(v->value, "em_rx")) {
11289 confp->chan.sig = SIG_EM;
11290 confp->chan.radio = 1;
11291 } else if (!strcasecmp(v->value, "em_tx")) {
11292 confp->chan.sig = SIG_EM;
11293 confp->chan.radio = 1;
11294 } else if (!strcasecmp(v->value, "em_rxtx")) {
11295 confp->chan.sig = SIG_EM;
11296 confp->chan.radio = 2;
11297 } else if (!strcasecmp(v->value, "em_txrx")) {
11298 confp->chan.sig = SIG_EM;
11299 confp->chan.radio = 2;
11300 } else if (!strcasecmp(v->value, "sf")) {
11301 confp->chan.sig = SIG_SF;
11302 confp->chan.radio = 0;
11303 } else if (!strcasecmp(v->value, "sf_w")) {
11304 confp->chan.sig = SIG_SFWINK;
11305 confp->chan.radio = 0;
11306 } else if (!strcasecmp(v->value, "sf_featd")) {
11307 confp->chan.sig = SIG_FEATD;
11308 confp->chan.radio = 0;
11309 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11310 confp->chan.sig = SIG_FEATDMF;
11311 confp->chan.radio = 0;
11312 } else if (!strcasecmp(v->value, "sf_featb")) {
11313 confp->chan.sig = SIG_SF_FEATB;
11314 confp->chan.radio = 0;
11315 } else if (!strcasecmp(v->value, "sf")) {
11316 confp->chan.sig = SIG_SF;
11317 confp->chan.radio = 0;
11318 } else if (!strcasecmp(v->value, "sf_rx")) {
11319 confp->chan.sig = SIG_SF;
11320 confp->chan.radio = 1;
11321 } else if (!strcasecmp(v->value, "sf_tx")) {
11322 confp->chan.sig = SIG_SF;
11323 confp->chan.radio = 1;
11324 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11325 confp->chan.sig = SIG_SF;
11326 confp->chan.radio = 2;
11327 } else if (!strcasecmp(v->value, "sf_txrx")) {
11328 confp->chan.sig = SIG_SF;
11329 confp->chan.radio = 2;
11330 } else if (!strcasecmp(v->value, "featd")) {
11331 confp->chan.sig = SIG_FEATD;
11332 confp->chan.radio = 0;
11333 } else if (!strcasecmp(v->value, "featdmf")) {
11334 confp->chan.sig = SIG_FEATDMF;
11335 confp->chan.radio = 0;
11336 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11337 confp->chan.sig = SIG_FEATDMF_TA;
11338 confp->chan.radio = 0;
11339 } else if (!strcasecmp(v->value, "e911")) {
11340 confp->chan.sig = SIG_E911;
11341 confp->chan.radio = 0;
11342 } else if (!strcasecmp(v->value, "fgccama")) {
11343 confp->chan.sig = SIG_FGC_CAMA;
11344 confp->chan.radio = 0;
11345 } else if (!strcasecmp(v->value, "fgccamamf")) {
11346 confp->chan.sig = SIG_FGC_CAMAMF;
11347 confp->chan.radio = 0;
11348 } else if (!strcasecmp(v->value, "featb")) {
11349 confp->chan.sig = SIG_FEATB;
11350 confp->chan.radio = 0;
11351 #ifdef HAVE_PRI
11352 } else if (!strcasecmp(v->value, "pri_net")) {
11353 confp->chan.radio = 0;
11354 confp->chan.sig = SIG_PRI;
11355 confp->pri.nodetype = PRI_NETWORK;
11356 } else if (!strcasecmp(v->value, "pri_cpe")) {
11357 confp->chan.sig = SIG_PRI;
11358 confp->chan.radio = 0;
11359 confp->pri.nodetype = PRI_CPE;
11360 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11361 confp->chan.sig = SIG_GR303FXOKS;
11362 confp->chan.radio = 0;
11363 confp->pri.nodetype = PRI_NETWORK;
11364 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11365 confp->chan.sig = SIG_GR303FXSKS;
11366 confp->chan.radio = 0;
11367 confp->pri.nodetype = PRI_CPE;
11368 #endif
11369 } else {
11370 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11371 }
11372 } else if (!strcasecmp(v->name, "outsignalling")) {
11373 if (!strcasecmp(v->value, "em")) {
11374 confp->chan.outsigmod = SIG_EM;
11375 } else if (!strcasecmp(v->value, "em_e1")) {
11376 confp->chan.outsigmod = SIG_EM_E1;
11377 } else if (!strcasecmp(v->value, "em_w")) {
11378 confp->chan.outsigmod = SIG_EMWINK;
11379 } else if (!strcasecmp(v->value, "sf")) {
11380 confp->chan.outsigmod = SIG_SF;
11381 } else if (!strcasecmp(v->value, "sf_w")) {
11382 confp->chan.outsigmod = SIG_SFWINK;
11383 } else if (!strcasecmp(v->value, "sf_featd")) {
11384 confp->chan.outsigmod = SIG_FEATD;
11385 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11386 confp->chan.outsigmod = SIG_FEATDMF;
11387 } else if (!strcasecmp(v->value, "sf_featb")) {
11388 confp->chan.outsigmod = SIG_SF_FEATB;
11389 } else if (!strcasecmp(v->value, "sf")) {
11390 confp->chan.outsigmod = SIG_SF;
11391 } else if (!strcasecmp(v->value, "featd")) {
11392 confp->chan.outsigmod = SIG_FEATD;
11393 } else if (!strcasecmp(v->value, "featdmf")) {
11394 confp->chan.outsigmod = SIG_FEATDMF;
11395 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11396 confp->chan.outsigmod = SIG_FEATDMF_TA;
11397 } else if (!strcasecmp(v->value, "e911")) {
11398 confp->chan.outsigmod = SIG_E911;
11399 } else if (!strcasecmp(v->value, "fgccama")) {
11400 confp->chan.outsigmod = SIG_FGC_CAMA;
11401 } else if (!strcasecmp(v->value, "fgccamamf")) {
11402 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11403 } else if (!strcasecmp(v->value, "featb")) {
11404 confp->chan.outsigmod = SIG_FEATB;
11405 } else {
11406 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11407 }
11408 #ifdef HAVE_PRI
11409 } else if (!strcasecmp(v->name, "pridialplan")) {
11410 if (!strcasecmp(v->value, "national")) {
11411 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11412 } else if (!strcasecmp(v->value, "unknown")) {
11413 confp->pri.dialplan = PRI_UNKNOWN + 1;
11414 } else if (!strcasecmp(v->value, "private")) {
11415 confp->pri.dialplan = PRI_PRIVATE + 1;
11416 } else if (!strcasecmp(v->value, "international")) {
11417 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11418 } else if (!strcasecmp(v->value, "local")) {
11419 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11420 } else if (!strcasecmp(v->value, "dynamic")) {
11421 confp->pri.dialplan = -1;
11422 } else {
11423 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11424 }
11425 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11426 if (!strcasecmp(v->value, "national")) {
11427 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11428 } else if (!strcasecmp(v->value, "unknown")) {
11429 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11430 } else if (!strcasecmp(v->value, "private")) {
11431 confp->pri.localdialplan = PRI_PRIVATE + 1;
11432 } else if (!strcasecmp(v->value, "international")) {
11433 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11434 } else if (!strcasecmp(v->value, "local")) {
11435 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11436 } else if (!strcasecmp(v->value, "dynamic")) {
11437 confp->pri.localdialplan = -1;
11438 } else {
11439 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11440 }
11441 } else if (!strcasecmp(v->name, "switchtype")) {
11442 if (!strcasecmp(v->value, "national"))
11443 confp->pri.switchtype = PRI_SWITCH_NI2;
11444 else if (!strcasecmp(v->value, "ni1"))
11445 confp->pri.switchtype = PRI_SWITCH_NI1;
11446 else if (!strcasecmp(v->value, "dms100"))
11447 confp->pri.switchtype = PRI_SWITCH_DMS100;
11448 else if (!strcasecmp(v->value, "4ess"))
11449 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11450 else if (!strcasecmp(v->value, "5ess"))
11451 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11452 else if (!strcasecmp(v->value, "euroisdn"))
11453 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11454 else if (!strcasecmp(v->value, "qsig"))
11455 confp->pri.switchtype = PRI_SWITCH_QSIG;
11456 else {
11457 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11458 return -1;
11459 }
11460 } else if (!strcasecmp(v->name, "nsf")) {
11461 if (!strcasecmp(v->value, "sdn"))
11462 confp->pri.nsf = PRI_NSF_SDN;
11463 else if (!strcasecmp(v->value, "megacom"))
11464 confp->pri.nsf = PRI_NSF_MEGACOM;
11465 else if (!strcasecmp(v->value, "tollfreemegacom"))
11466 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11467 else if (!strcasecmp(v->value, "accunet"))
11468 confp->pri.nsf = PRI_NSF_ACCUNET;
11469 else if (!strcasecmp(v->value, "none"))
11470 confp->pri.nsf = PRI_NSF_NONE;
11471 else {
11472 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11473 confp->pri.nsf = PRI_NSF_NONE;
11474 }
11475 } else if (!strcasecmp(v->name, "priindication")) {
11476 if (!strcasecmp(v->value, "outofband"))
11477 confp->chan.priindication_oob = 1;
11478 else if (!strcasecmp(v->value, "inband"))
11479 confp->chan.priindication_oob = 0;
11480 else
11481 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11482 v->value, v->lineno);
11483 } else if (!strcasecmp(v->name, "priexclusive")) {
11484 confp->chan.priexclusive = ast_true(v->value);
11485 } else if (!strcasecmp(v->name, "internationalprefix")) {
11486 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11487 } else if (!strcasecmp(v->name, "nationalprefix")) {
11488 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11489 } else if (!strcasecmp(v->name, "localprefix")) {
11490 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11491 } else if (!strcasecmp(v->name, "privateprefix")) {
11492 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11493 } else if (!strcasecmp(v->name, "unknownprefix")) {
11494 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11495 } else if (!strcasecmp(v->name, "resetinterval")) {
11496 if (!strcasecmp(v->value, "never"))
11497 confp->pri.resetinterval = -1;
11498 else if (atoi(v->value) >= 60)
11499 confp->pri.resetinterval = atoi(v->value);
11500 else
11501 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11502 v->value, v->lineno);
11503 } else if (!strcasecmp(v->name, "minunused")) {
11504 confp->pri.minunused = atoi(v->value);
11505 } else if (!strcasecmp(v->name, "minidle")) {
11506 confp->pri.minidle = atoi(v->value);
11507 } else if (!strcasecmp(v->name, "idleext")) {
11508 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11509 } else if (!strcasecmp(v->name, "idledial")) {
11510 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11511 } else if (!strcasecmp(v->name, "overlapdial")) {
11512 confp->pri.overlapdial = ast_true(v->value);
11513 #ifdef HAVE_PRI_INBANDDISCONNECT
11514 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11515 confp->pri.inbanddisconnect = ast_true(v->value);
11516 #endif
11517 } else if (!strcasecmp(v->name, "pritimer")) {
11518 #ifdef PRI_GETSET_TIMERS
11519 char *timerc, *c;
11520 int timer, timeridx;
11521 c = v->value;
11522 timerc = strsep(&c, ",");
11523 if (timerc) {
11524 timer = atoi(c);
11525 if (!timer)
11526 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11527 else {
11528 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11529 pritimers[timeridx] = timer;
11530 else
11531 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11532 }
11533 } else
11534 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11535
11536 } else if (!strcasecmp(v->name, "facilityenable")) {
11537 confp->pri.facilityenable = ast_true(v->value);
11538 #endif
11539 #endif
11540 } else if (!strcasecmp(v->name, "cadence")) {
11541
11542 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11543 int i;
11544 struct dahdi_ring_cadence new_cadence;
11545 int cid_location = -1;
11546 int firstcadencepos = 0;
11547 char original_args[80];
11548 int cadence_is_ok = 1;
11549
11550 ast_copy_string(original_args, v->value, sizeof(original_args));
11551
11552 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &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]);
11553
11554
11555 if (element_count % 2 == 1) {
11556 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11557 cadence_is_ok = 0;
11558 }
11559
11560
11561 for (i = 0; i < element_count; i++) {
11562 if (c[i] == 0) {
11563 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11564 cadence_is_ok = 0;
11565 break;
11566 } else if (c[i] < 0) {
11567 if (i % 2 == 1) {
11568
11569 if (cid_location == -1) {
11570 cid_location = i;
11571 c[i] *= -1;
11572 } else {
11573 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11574 cadence_is_ok = 0;
11575 break;
11576 }
11577 } else {
11578 if (firstcadencepos == 0) {
11579 firstcadencepos = i;
11580
11581 } else {
11582 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11583 cadence_is_ok = 0;
11584 break;
11585 }
11586 }
11587 }
11588 }
11589
11590
11591 for (i = 0; i < 16; i++) {
11592 new_cadence.ringcadence[i] = c[i];
11593 }
11594
11595 if (cadence_is_ok) {
11596
11597 if (element_count < 2) {
11598 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11599 } else {
11600 if (cid_location == -1) {
11601
11602 cid_location = 1;
11603 } else {
11604
11605 cid_location = (cid_location + 1) / 2;
11606 }
11607
11608 if (!user_has_defined_cadences++)
11609
11610 num_cadence = 0;
11611 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11612 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11613 else {
11614 cadences[num_cadence] = new_cadence;
11615 cidrings[num_cadence++] = cid_location;
11616 if (option_verbose > 2)
11617 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11618 }
11619 }
11620 }
11621 } else if (!strcasecmp(v->name, "ringtimeout")) {
11622 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11623 } else if (!strcasecmp(v->name, "prewink")) {
11624 confp->timing.prewinktime = atoi(v->value);
11625 } else if (!strcasecmp(v->name, "preflash")) {
11626 confp->timing.preflashtime = atoi(v->value);
11627 } else if (!strcasecmp(v->name, "wink")) {
11628 confp->timing.winktime = atoi(v->value);
11629 } else if (!strcasecmp(v->name, "flash")) {
11630 confp->timing.flashtime = atoi(v->value);
11631 } else if (!strcasecmp(v->name, "start")) {
11632 confp->timing.starttime = atoi(v->value);
11633 } else if (!strcasecmp(v->name, "rxwink")) {
11634 confp->timing.rxwinktime = atoi(v->value);
11635 } else if (!strcasecmp(v->name, "rxflash")) {
11636 confp->timing.rxflashtime = atoi(v->value);
11637 } else if (!strcasecmp(v->name, "debounce")) {
11638 confp->timing.debouncetime = atoi(v->value);
11639 } else if (!strcasecmp(v->name, "toneduration")) {
11640 int toneduration;
11641 int ctlfd;
11642 int res;
11643 struct dahdi_dialparams dps;
11644
11645 ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
11646
11647 if (ctlfd == -1) {
11648 ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
11649 return -1;
11650 }
11651
11652 toneduration = atoi(v->value);
11653 if (toneduration > -1) {
11654 memset(&dps, 0, sizeof(dps));
11655
11656 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11657 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11658 if (res < 0) {
11659 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11660 return -1;
11661 }
11662 }
11663 close(ctlfd);
11664 } else if (!strcasecmp(v->name, "defaultcic")) {
11665 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11666 } else if (!strcasecmp(v->name, "defaultozz")) {
11667 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11668 }
11669 } else if (!skipchannels)
11670 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11671 }
11672 if (dahdichan[0]) {
11673
11674
11675 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11676 return -1;
11677 }
11678 }
11679
11680
11681 if (!found_pseudo && reload == 0) {
11682
11683
11684
11685
11686 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11687
11688 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
11689
11690 if (tmp) {
11691 if (option_verbose > 2)
11692 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11693 } else {
11694 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11695 }
11696 }
11697 return 0;
11698 }
11699
11700 static int setup_dahdi(int reload)
11701 {
11702 struct ast_config *cfg;
11703 struct ast_variable *v;
11704 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11705 int res;
11706
11707 #ifdef HAVE_PRI
11708 char *c;
11709 int spanno;
11710 int i, x;
11711 int logicalspan;
11712 int trunkgroup;
11713 int dchannels[NUM_DCHANS];
11714 #endif
11715
11716 #ifdef HAVE_ZAPTEL
11717 int load_from_zapata_conf = 1;
11718 #else
11719 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11720 #endif
11721
11722 if (load_from_zapata_conf) {
11723 if (!(cfg = ast_config_load("zapata.conf"))) {
11724 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11725 return 0;
11726 }
11727 } else {
11728 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11729 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11730 return 0;
11731 }
11732 }
11733
11734
11735 ast_mutex_lock(&iflock);
11736 #ifdef HAVE_PRI
11737 if (reload != 1) {
11738
11739 v = ast_variable_browse(cfg, "trunkgroups");
11740 while (v) {
11741 if (!strcasecmp(v->name, "trunkgroup")) {
11742 trunkgroup = atoi(v->value);
11743 if (trunkgroup > 0) {
11744 if ((c = strchr(v->value, ','))) {
11745 i = 0;
11746 memset(dchannels, 0, sizeof(dchannels));
11747 while (c && (i < NUM_DCHANS)) {
11748 dchannels[i] = atoi(c + 1);
11749 if (dchannels[i] < 0) {
11750 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);
11751 } else
11752 i++;
11753 c = strchr(c + 1, ',');
11754 }
11755 if (i) {
11756 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11757 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);
11758 } else if (option_verbose > 1)
11759 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11760 } else
11761 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11762 } else
11763 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11764 } else
11765 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11766 } else if (!strcasecmp(v->name, "spanmap")) {
11767 spanno = atoi(v->value);
11768 if (spanno > 0) {
11769 if ((c = strchr(v->value, ','))) {
11770 trunkgroup = atoi(c + 1);
11771 if (trunkgroup > 0) {
11772 if ((c = strchr(c + 1, ',')))
11773 logicalspan = atoi(c + 1);
11774 else
11775 logicalspan = 0;
11776 if (logicalspan >= 0) {
11777 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11778 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11779 } else if (option_verbose > 1)
11780 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11781 } else
11782 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);
11783 } else
11784 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11785 } else
11786 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11787 } else
11788 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11789 } else {
11790 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11791 }
11792 v = v->next;
11793 }
11794 }
11795 #endif
11796
11797
11798 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11799
11800 v = ast_variable_browse(cfg, "channels");
11801 res = process_dahdi(&conf, "", v, reload, 0);
11802 ast_mutex_unlock(&iflock);
11803 ast_config_destroy(cfg);
11804 if (res)
11805 return res;
11806 cfg = ast_config_load("users.conf");
11807 if (cfg) {
11808 char *cat;
11809 const char *chans;
11810 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11811 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11812 if (!strcasecmp(cat, "general"))
11813 continue;
11814 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11815 if (!ast_strlen_zero(chans)) {
11816 struct dahdi_chan_conf sect_conf;
11817 memcpy(§_conf, &conf, sizeof(sect_conf));
11818
11819 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11820 }
11821 }
11822 ast_config_destroy(cfg);
11823 }
11824 #ifdef HAVE_PRI
11825 if (reload != 1) {
11826 for (x = 0; x < NUM_SPANS; x++) {
11827 if (pris[x].pvts[0]) {
11828 if (start_pri(pris + x)) {
11829 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11830 return -1;
11831 } else if (option_verbose > 1)
11832 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11833 }
11834 }
11835 }
11836 #endif
11837
11838 restart_monitor();
11839 return 0;
11840 }
11841
11842 #define local_astman_register(a, b, c, d) do { \
11843 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11844 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11845 } \
11846 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11847 } while (0)
11848
11849 static int load_module(void)
11850 {
11851 int res;
11852
11853 #ifdef HAVE_PRI
11854 int y,i;
11855 memset(pris, 0, sizeof(pris));
11856 for (y = 0; y < NUM_SPANS; y++) {
11857 ast_mutex_init(&pris[y].lock);
11858 pris[y].offset = -1;
11859 pris[y].master = AST_PTHREADT_NULL;
11860 for (i = 0; i < NUM_DCHANS; i++)
11861 pris[y].fds[i] = -1;
11862 }
11863 pri_set_error(dahdi_pri_error);
11864 pri_set_message(dahdi_pri_message);
11865 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11866 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11867 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11868 }
11869 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11870 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11871 #endif
11872 if ((res = setup_dahdi(0))) {
11873 return AST_MODULE_LOAD_DECLINE;
11874 }
11875 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11876 chan_tech = &dahdi_tech;
11877 } else {
11878 chan_tech = &zap_tech;
11879 }
11880 if (ast_channel_register(chan_tech)) {
11881 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11882 __unload_module();
11883 return -1;
11884 }
11885 #ifdef HAVE_PRI
11886 ast_string_field_init(&inuse, 16);
11887 ast_string_field_set(&inuse, name, "GR-303InUse");
11888 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11889 #endif
11890 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11891
11892 memset(round_robin, 0, sizeof(round_robin));
11893 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11894 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11895 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11896 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11897 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11898 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11899 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11900
11901 ast_cond_init(&ss_thread_complete, NULL);
11902
11903 return res;
11904 }
11905
11906 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11907 {
11908 #define END_SILENCE_LEN 400
11909 #define HEADER_MS 50
11910 #define TRAILER_MS 5
11911 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11912 #define ASCII_BYTES_PER_CHAR 80
11913
11914 unsigned char *buf,*mybuf;
11915 struct dahdi_pvt *p = c->tech_pvt;
11916 struct pollfd fds[1];
11917 int size,res,fd,len,x;
11918 int bytes=0;
11919
11920 float cr = 1.0;
11921 float ci = 0.0;
11922 float scont = 0.0;
11923 int index;
11924
11925 index = dahdi_get_index(c, p, 0);
11926 if (index < 0) {
11927 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11928 return -1;
11929 }
11930 if (!text[0]) return(0);
11931 if ((!p->tdd) && (!p->mate)) return(0);
11932 if (p->mate)
11933 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11934 else
11935 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11936 if (!buf)
11937 return -1;
11938 mybuf = buf;
11939 if (p->mate) {
11940 int codec = AST_LAW(p);
11941 for (x = 0; x < HEADER_MS; x++) {
11942 PUT_CLID_MARKMS;
11943 }
11944
11945 for (x = 0; text[x]; x++) {
11946 PUT_CLID(text[x]);
11947 }
11948 for (x = 0; x < TRAILER_MS; x++) {
11949 PUT_CLID_MARKMS;
11950 }
11951 len = bytes;
11952 buf = mybuf;
11953 } else {
11954 len = tdd_generate(p->tdd, buf, text);
11955 if (len < 1) {
11956 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11957 free(mybuf);
11958 return -1;
11959 }
11960 }
11961 memset(buf + len, 0x7f, END_SILENCE_LEN);
11962 len += END_SILENCE_LEN;
11963 fd = p->subs[index].dfd;
11964 while (len) {
11965 if (ast_check_hangup(c)) {
11966 free(mybuf);
11967 return -1;
11968 }
11969 size = len;
11970 if (size > READ_SIZE)
11971 size = READ_SIZE;
11972 fds[0].fd = fd;
11973 fds[0].events = POLLOUT | POLLPRI;
11974 fds[0].revents = 0;
11975 res = poll(fds, 1, -1);
11976 if (!res) {
11977 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11978 continue;
11979 }
11980
11981 if (fds[0].revents & POLLPRI) {
11982 ast_free(mybuf);
11983 return -1;
11984 }
11985 if (!(fds[0].revents & POLLOUT)) {
11986 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11987 continue;
11988 }
11989 res = write(fd, buf, size);
11990 if (res != size) {
11991 if (res == -1) {
11992 free(mybuf);
11993 return -1;
11994 }
11995 if (option_debug)
11996 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11997 break;
11998 }
11999 len -= size;
12000 buf += size;
12001 }
12002 free(mybuf);
12003 return(0);
12004 }
12005
12006
12007 static int reload(void)
12008 {
12009 int res = 0;
12010
12011 res = setup_dahdi(1);
12012 if (res) {
12013 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12014 return -1;
12015 }
12016 return 0;
12017 }
12018
12019
12020
12021
12022
12023 #ifdef HAVE_PRI
12024 #define tdesc "DAHDI Telephony w/PRI"
12025 #else
12026 #define tdesc "DAHDI Telephony"
12027 #endif
12028
12029 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12030 .load = load_module,
12031 .unload = unload_module,
12032 .reload = reload,
12033 );
12034
12035