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: 140115 $")
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 #ifdef HAVE_ZAPTEL
00927 fn = "/dev/zap/channel";
00928 #else
00929 fn = "/dev/dahdi/channel";
00930 #endif
00931 }
00932 fd = open(fn, O_RDWR | O_NONBLOCK);
00933 if (fd < 0) {
00934 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00935 return -1;
00936 }
00937 if (chan) {
00938 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
00939 x = errno;
00940 close(fd);
00941 errno = x;
00942 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00943 return -1;
00944 }
00945 }
00946 bs = READ_SIZE;
00947 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
00948 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
00949 x = errno;
00950 close(fd);
00951 errno = x;
00952 return -1;
00953 }
00954 return fd;
00955 }
00956
00957 static void dahdi_close(int fd)
00958 {
00959 if (fd > 0)
00960 close(fd);
00961 }
00962
00963 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
00964 {
00965 dahdi_close(chan_pvt->subs[sub_num].dfd);
00966 chan_pvt->subs[sub_num].dfd = -1;
00967 }
00968
00969 #ifdef HAVE_PRI
00970 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
00971 {
00972 dahdi_close(pri->fds[fd_num]);
00973 pri->fds[fd_num] = -1;
00974 }
00975 #endif
00976
00977 static int dahdi_setlinear(int dfd, int linear)
00978 {
00979 int res;
00980 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
00981 if (res)
00982 return res;
00983 return 0;
00984 }
00985
00986
00987 static int alloc_sub(struct dahdi_pvt *p, int x)
00988 {
00989 struct dahdi_bufferinfo bi;
00990 int res;
00991 if (p->subs[x].dfd < 0) {
00992 #ifdef HAVE_ZAPTEL
00993 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
00994 #else
00995 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
00996 #endif
00997 if (p->subs[x].dfd > -1) {
00998 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
00999 if (!res) {
01000 bi.txbufpolicy = p->buf_policy;
01001 bi.rxbufpolicy = p->buf_policy;
01002 bi.numbufs = p->buf_no;
01003 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01004 if (res < 0) {
01005 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01006 }
01007 } else
01008 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01009 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01010 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01011 dahdi_close_sub(p, x);
01012 return -1;
01013 }
01014 if (option_debug)
01015 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01016 return 0;
01017 } else
01018 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01019 return -1;
01020 }
01021 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01022 return -1;
01023 }
01024
01025 static int unalloc_sub(struct dahdi_pvt *p, int x)
01026 {
01027 if (!x) {
01028 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01029 return -1;
01030 }
01031 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01032 dahdi_close_sub(p, x);
01033 p->subs[x].linear = 0;
01034 p->subs[x].chan = 0;
01035 p->subs[x].owner = NULL;
01036 p->subs[x].inthreeway = 0;
01037 p->polarity = POLARITY_IDLE;
01038 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01039 return 0;
01040 }
01041
01042 static int digit_to_dtmfindex(char digit)
01043 {
01044 if (isdigit(digit))
01045 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01046 else if (digit >= 'A' && digit <= 'D')
01047 return DAHDI_TONE_DTMF_A + (digit - 'A');
01048 else if (digit >= 'a' && digit <= 'd')
01049 return DAHDI_TONE_DTMF_A + (digit - 'a');
01050 else if (digit == '*')
01051 return DAHDI_TONE_DTMF_s;
01052 else if (digit == '#')
01053 return DAHDI_TONE_DTMF_p;
01054 else
01055 return -1;
01056 }
01057
01058 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01059 {
01060 struct dahdi_pvt *pvt;
01061 int index;
01062 int dtmf = -1;
01063
01064 pvt = chan->tech_pvt;
01065
01066 ast_mutex_lock(&pvt->lock);
01067
01068 index = dahdi_get_index(chan, pvt, 0);
01069
01070 if ((index != SUB_REAL) || !pvt->owner)
01071 goto out;
01072
01073 #ifdef HAVE_PRI
01074 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01075 if (pvt->setup_ack) {
01076 if (!pri_grab(pvt, pvt->pri)) {
01077 pri_information(pvt->pri->pri, pvt->call, digit);
01078 pri_rel(pvt->pri);
01079 } else
01080 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01081 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01082 int res;
01083 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01084 res = strlen(pvt->dialdest);
01085 pvt->dialdest[res++] = digit;
01086 pvt->dialdest[res] = '\0';
01087 }
01088 goto out;
01089 }
01090 #endif
01091 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01092 goto out;
01093
01094 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01095 int res;
01096 struct dahdi_dialoperation zo = {
01097 .op = DAHDI_DIAL_OP_APPEND,
01098 .dialstr[0] = 'T',
01099 .dialstr[1] = digit,
01100 .dialstr[2] = 0,
01101 };
01102 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01103 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01104 else
01105 pvt->dialing = 1;
01106 } else {
01107 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01108 pvt->dialing = 1;
01109 pvt->begindigit = digit;
01110 }
01111
01112 out:
01113 ast_mutex_unlock(&pvt->lock);
01114
01115 return 0;
01116 }
01117
01118 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01119 {
01120 struct dahdi_pvt *pvt;
01121 int res = 0;
01122 int index;
01123 int x;
01124
01125 pvt = chan->tech_pvt;
01126
01127 ast_mutex_lock(&pvt->lock);
01128
01129 index = dahdi_get_index(chan, pvt, 0);
01130
01131 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01132 goto out;
01133
01134 #ifdef HAVE_PRI
01135
01136 if (pvt->sig == SIG_PRI && !pvt->begindigit)
01137 goto out;
01138 #endif
01139
01140 if (pvt->begindigit) {
01141 x = -1;
01142 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01143 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01144 pvt->dialing = 0;
01145 pvt->begindigit = 0;
01146 }
01147
01148 out:
01149 ast_mutex_unlock(&pvt->lock);
01150
01151 return res;
01152 }
01153
01154 static char *events[] = {
01155 "No event",
01156 "On hook",
01157 "Ring/Answered",
01158 "Wink/Flash",
01159 "Alarm",
01160 "No more alarm",
01161 "HDLC Abort",
01162 "HDLC Overrun",
01163 "HDLC Bad FCS",
01164 "Dial Complete",
01165 "Ringer On",
01166 "Ringer Off",
01167 "Hook Transition Complete",
01168 "Bits Changed",
01169 "Pulse Start",
01170 "Timer Expired",
01171 "Timer Ping",
01172 "Polarity Reversal",
01173 "Ring Begin",
01174 };
01175
01176 static struct {
01177 int alarm;
01178 char *name;
01179 } alarms[] = {
01180 { DAHDI_ALARM_RED, "Red Alarm" },
01181 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01182 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01183 { DAHDI_ALARM_RECOVER, "Recovering" },
01184 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01185 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01186 { DAHDI_ALARM_NONE, "None" },
01187 };
01188
01189 static char *alarm2str(int alarm)
01190 {
01191 int x;
01192 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01193 if (alarms[x].alarm & alarm)
01194 return alarms[x].name;
01195 }
01196 return alarm ? "Unknown Alarm" : "No Alarm";
01197 }
01198
01199 static char *event2str(int event)
01200 {
01201 static char buf[256];
01202 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01203 return events[event];
01204 sprintf(buf, "Event %d", event);
01205 return buf;
01206 }
01207
01208 #ifdef HAVE_PRI
01209 static char *dialplan2str(int dialplan)
01210 {
01211 if (dialplan == -1) {
01212 return("Dynamically set dialplan in ISDN");
01213 }
01214 return (pri_plan2str(dialplan));
01215 }
01216 #endif
01217
01218 static char *dahdi_sig2str(int sig)
01219 {
01220 static char buf[256];
01221 switch (sig) {
01222 case SIG_EM:
01223 return "E & M Immediate";
01224 case SIG_EMWINK:
01225 return "E & M Wink";
01226 case SIG_EM_E1:
01227 return "E & M E1";
01228 case SIG_FEATD:
01229 return "Feature Group D (DTMF)";
01230 case SIG_FEATDMF:
01231 return "Feature Group D (MF)";
01232 case SIG_FEATDMF_TA:
01233 return "Feature Groud D (MF) Tandem Access";
01234 case SIG_FEATB:
01235 return "Feature Group B (MF)";
01236 case SIG_E911:
01237 return "E911 (MF)";
01238 case SIG_FGC_CAMA:
01239 return "FGC/CAMA (Dialpulse)";
01240 case SIG_FGC_CAMAMF:
01241 return "FGC/CAMA (MF)";
01242 case SIG_FXSLS:
01243 return "FXS Loopstart";
01244 case SIG_FXSGS:
01245 return "FXS Groundstart";
01246 case SIG_FXSKS:
01247 return "FXS Kewlstart";
01248 case SIG_FXOLS:
01249 return "FXO Loopstart";
01250 case SIG_FXOGS:
01251 return "FXO Groundstart";
01252 case SIG_FXOKS:
01253 return "FXO Kewlstart";
01254 case SIG_PRI:
01255 return "ISDN PRI";
01256 case SIG_SF:
01257 return "SF (Tone) Immediate";
01258 case SIG_SFWINK:
01259 return "SF (Tone) Wink";
01260 case SIG_SF_FEATD:
01261 return "SF (Tone) with Feature Group D (DTMF)";
01262 case SIG_SF_FEATDMF:
01263 return "SF (Tone) with Feature Group D (MF)";
01264 case SIG_SF_FEATB:
01265 return "SF (Tone) with Feature Group B (MF)";
01266 case SIG_GR303FXOKS:
01267 return "GR-303 with FXOKS";
01268 case SIG_GR303FXSKS:
01269 return "GR-303 with FXSKS";
01270 case 0:
01271 return "Pseudo";
01272 default:
01273 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01274 return buf;
01275 }
01276 }
01277
01278 #define sig2str dahdi_sig2str
01279
01280 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01281 {
01282
01283
01284 struct dahdi_confinfo zi;
01285
01286 memset(&zi, 0, sizeof(zi));
01287 zi.chan = 0;
01288
01289 if (slavechannel > 0) {
01290
01291 zi.confmode = DAHDI_CONF_DIGITALMON;
01292 zi.confno = slavechannel;
01293 } else {
01294 if (!index) {
01295
01296 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01297 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01298 } else
01299 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01300 zi.confno = p->confno;
01301 }
01302 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01303 return 0;
01304 if (c->dfd < 0)
01305 return 0;
01306 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01307 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01308 return -1;
01309 }
01310 if (slavechannel < 1) {
01311 p->confno = zi.confno;
01312 }
01313 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01314 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01315 return 0;
01316 }
01317
01318 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01319 {
01320
01321 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01322 return 1;
01323
01324 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01325 return 1;
01326 return 0;
01327 }
01328
01329 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01330 {
01331 struct dahdi_confinfo zi;
01332 if (
01333 (c->dfd < 0) ||
01334
01335 !isourconf(p, c)
01336
01337 ) return 0;
01338 memset(&zi, 0, sizeof(zi));
01339 zi.chan = 0;
01340 zi.confno = 0;
01341 zi.confmode = 0;
01342 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01343 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01344 return -1;
01345 }
01346 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01347 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01348 return 0;
01349 }
01350
01351 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01352 {
01353 int x;
01354 int useslavenative;
01355 struct dahdi_pvt *slave = NULL;
01356
01357 useslavenative = 1;
01358
01359 for (x = 0; x < 3; x++) {
01360
01361
01362 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01363 useslavenative = 0;
01364 }
01365
01366
01367 if (useslavenative) {
01368 for (x = 0; x < MAX_SLAVES; x++) {
01369 if (p->slaves[x]) {
01370 if (slave) {
01371
01372
01373 slave = NULL;
01374 useslavenative = 0;
01375 break;
01376 } else {
01377
01378 slave = p->slaves[x];
01379 }
01380 }
01381 }
01382 }
01383
01384 if (!slave)
01385 useslavenative = 0;
01386 else if (slave->law != p->law) {
01387 useslavenative = 0;
01388 slave = NULL;
01389 }
01390 if (out)
01391 *out = slave;
01392 return useslavenative;
01393 }
01394
01395 static int reset_conf(struct dahdi_pvt *p)
01396 {
01397 struct dahdi_confinfo zi;
01398 memset(&zi, 0, sizeof(zi));
01399 p->confno = -1;
01400 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01401 if (p->subs[SUB_REAL].dfd > -1) {
01402 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01403 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01404 }
01405 return 0;
01406 }
01407
01408 static int update_conf(struct dahdi_pvt *p)
01409 {
01410 int needconf = 0;
01411 int x;
01412 int useslavenative;
01413 struct dahdi_pvt *slave = NULL;
01414
01415 useslavenative = isslavenative(p, &slave);
01416
01417 for (x = 0; x < 3; x++) {
01418
01419 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01420 conf_add(p, &p->subs[x], x, 0);
01421 needconf++;
01422 } else {
01423 conf_del(p, &p->subs[x], x);
01424 }
01425 }
01426
01427
01428 for (x = 0; x < MAX_SLAVES; x++) {
01429 if (p->slaves[x]) {
01430 if (useslavenative)
01431 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01432 else {
01433 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01434 needconf++;
01435 }
01436 }
01437 }
01438
01439 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01440 if (useslavenative)
01441 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01442 else {
01443 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01444 needconf++;
01445 }
01446 }
01447
01448 if (p->master) {
01449 if (isslavenative(p->master, NULL)) {
01450 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01451 } else {
01452 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01453 }
01454 }
01455 if (!needconf) {
01456
01457
01458 p->confno = -1;
01459 }
01460 if (option_debug)
01461 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01462 return 0;
01463 }
01464
01465 static void dahdi_enable_ec(struct dahdi_pvt *p)
01466 {
01467 int x;
01468 int res;
01469 if (!p)
01470 return;
01471 if (p->echocanon) {
01472 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01473 return;
01474 }
01475 if (p->digital) {
01476 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01477 return;
01478 }
01479 if (p->echocancel) {
01480 if (p->sig == SIG_PRI) {
01481 x = 1;
01482 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01483 if (res)
01484 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01485 }
01486 x = p->echocancel;
01487 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01488 if (res)
01489 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01490 else {
01491 p->echocanon = 1;
01492 if (option_debug)
01493 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01494 }
01495 } else if (option_debug)
01496 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01497 }
01498
01499 static void dahdi_train_ec(struct dahdi_pvt *p)
01500 {
01501 int x;
01502 int res;
01503 if (p && p->echocancel && p->echotraining) {
01504 x = p->echotraining;
01505 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01506 if (res)
01507 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01508 else {
01509 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01510 }
01511 } else
01512 ast_log(LOG_DEBUG, "No echo training requested\n");
01513 }
01514
01515 static void dahdi_disable_ec(struct dahdi_pvt *p)
01516 {
01517 int x;
01518 int res;
01519 if (p->echocancel) {
01520 x = 0;
01521 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01522 if (res)
01523 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01524 else if (option_debug)
01525 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01526 }
01527 p->echocanon = 0;
01528 }
01529
01530 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01531 {
01532 int j;
01533 int k;
01534 float linear_gain = pow(10.0, gain / 20.0);
01535
01536 switch (law) {
01537 case DAHDI_LAW_ALAW:
01538 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01539 if (gain) {
01540 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01541 if (k > 32767) k = 32767;
01542 if (k < -32767) k = -32767;
01543 g->txgain[j] = AST_LIN2A(k);
01544 } else {
01545 g->txgain[j] = j;
01546 }
01547 }
01548 break;
01549 case DAHDI_LAW_MULAW:
01550 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01551 if (gain) {
01552 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01553 if (k > 32767) k = 32767;
01554 if (k < -32767) k = -32767;
01555 g->txgain[j] = AST_LIN2MU(k);
01556 } else {
01557 g->txgain[j] = j;
01558 }
01559 }
01560 break;
01561 }
01562 }
01563
01564 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01565 {
01566 int j;
01567 int k;
01568 float linear_gain = pow(10.0, gain / 20.0);
01569
01570 switch (law) {
01571 case DAHDI_LAW_ALAW:
01572 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01573 if (gain) {
01574 k = (int) (((float) AST_ALAW(j)) * linear_gain);
01575 if (k > 32767) k = 32767;
01576 if (k < -32767) k = -32767;
01577 g->rxgain[j] = AST_LIN2A(k);
01578 } else {
01579 g->rxgain[j] = j;
01580 }
01581 }
01582 break;
01583 case DAHDI_LAW_MULAW:
01584 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01585 if (gain) {
01586 k = (int) (((float) AST_MULAW(j)) * linear_gain);
01587 if (k > 32767) k = 32767;
01588 if (k < -32767) k = -32767;
01589 g->rxgain[j] = AST_LIN2MU(k);
01590 } else {
01591 g->rxgain[j] = j;
01592 }
01593 }
01594 break;
01595 }
01596 }
01597
01598 static int set_actual_txgain(int fd, int chan, float gain, int law)
01599 {
01600 struct dahdi_gains g;
01601 int res;
01602
01603 memset(&g, 0, sizeof(g));
01604 g.chan = chan;
01605 res = ioctl(fd, DAHDI_GETGAINS, &g);
01606 if (res) {
01607 if (option_debug)
01608 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01609 return res;
01610 }
01611
01612 fill_txgain(&g, gain, law);
01613
01614 return ioctl(fd, DAHDI_SETGAINS, &g);
01615 }
01616
01617 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01618 {
01619 struct dahdi_gains g;
01620 int res;
01621
01622 memset(&g, 0, sizeof(g));
01623 g.chan = chan;
01624 res = ioctl(fd, DAHDI_GETGAINS, &g);
01625 if (res) {
01626 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01627 return res;
01628 }
01629
01630 fill_rxgain(&g, gain, law);
01631
01632 return ioctl(fd, DAHDI_SETGAINS, &g);
01633 }
01634
01635 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01636 {
01637 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01638 }
01639
01640 static int bump_gains(struct dahdi_pvt *p)
01641 {
01642 int res;
01643
01644
01645 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01646 if (res) {
01647 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01648 return -1;
01649 }
01650
01651 return 0;
01652 }
01653
01654 static int restore_gains(struct dahdi_pvt *p)
01655 {
01656 int res;
01657
01658 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01659 if (res) {
01660 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01661 return -1;
01662 }
01663
01664 return 0;
01665 }
01666
01667 static inline int dahdi_set_hook(int fd, int hs)
01668 {
01669 int x, res;
01670
01671 x = hs;
01672 res = ioctl(fd, DAHDI_HOOK, &x);
01673
01674 if (res < 0) {
01675 if (errno == EINPROGRESS)
01676 return 0;
01677 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01678
01679 }
01680
01681 return res;
01682 }
01683
01684 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01685 {
01686 int x, y, res;
01687 x = muted;
01688 if (p->sig == SIG_PRI) {
01689 y = 1;
01690 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01691 if (res)
01692 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01693 }
01694 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
01695 if (res < 0)
01696 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01697 return res;
01698 }
01699
01700 static int save_conference(struct dahdi_pvt *p)
01701 {
01702 struct dahdi_confinfo c;
01703 int res;
01704 if (p->saveconf.confmode) {
01705 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01706 return -1;
01707 }
01708 p->saveconf.chan = 0;
01709 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
01710 if (res) {
01711 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01712 p->saveconf.confmode = 0;
01713 return -1;
01714 }
01715 c.chan = 0;
01716 c.confno = 0;
01717 c.confmode = DAHDI_CONF_NORMAL;
01718 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
01719 if (res) {
01720 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01721 return -1;
01722 }
01723 if (option_debug)
01724 ast_log(LOG_DEBUG, "Disabled conferencing\n");
01725 return 0;
01726 }
01727
01728 static int restore_conference(struct dahdi_pvt *p)
01729 {
01730 int res;
01731 if (p->saveconf.confmode) {
01732 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
01733 p->saveconf.confmode = 0;
01734 if (res) {
01735 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01736 return -1;
01737 }
01738 }
01739 if (option_debug)
01740 ast_log(LOG_DEBUG, "Restored conferencing\n");
01741 return 0;
01742 }
01743
01744 static int send_callerid(struct dahdi_pvt *p);
01745
01746 static int send_cwcidspill(struct dahdi_pvt *p)
01747 {
01748 p->callwaitcas = 0;
01749 p->cidcwexpire = 0;
01750 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01751 return -1;
01752 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01753
01754 p->cidlen += READ_SIZE * 4;
01755 p->cidpos = 0;
01756 send_callerid(p);
01757 if (option_verbose > 2)
01758 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01759 return 0;
01760 }
01761
01762 static int has_voicemail(struct dahdi_pvt *p)
01763 {
01764
01765 return ast_app_has_voicemail(p->mailbox, NULL);
01766 }
01767
01768 static int send_callerid(struct dahdi_pvt *p)
01769 {
01770
01771 int res;
01772
01773 if (p->subs[SUB_REAL].linear) {
01774 p->subs[SUB_REAL].linear = 0;
01775 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
01776 }
01777 while (p->cidpos < p->cidlen) {
01778 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01779 if (res < 0) {
01780 if (errno == EAGAIN)
01781 return 0;
01782 else {
01783 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01784 return -1;
01785 }
01786 }
01787 if (!res)
01788 return 0;
01789 p->cidpos += res;
01790 }
01791 free(p->cidspill);
01792 p->cidspill = NULL;
01793 if (p->callwaitcas) {
01794
01795 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01796 } else
01797 restore_conference(p);
01798 return 0;
01799 }
01800
01801 static int dahdi_callwait(struct ast_channel *ast)
01802 {
01803 struct dahdi_pvt *p = ast->tech_pvt;
01804 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01805 if (p->cidspill) {
01806 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01807 free(p->cidspill);
01808 }
01809 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01810 return -1;
01811 save_conference(p);
01812
01813 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01814 if (!p->callwaitrings && p->callwaitingcallerid) {
01815 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01816 p->callwaitcas = 1;
01817 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01818 } else {
01819 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01820 p->callwaitcas = 0;
01821 p->cidlen = 2400 + READ_SIZE * 4;
01822 }
01823 p->cidpos = 0;
01824 send_callerid(p);
01825
01826 return 0;
01827 }
01828
01829 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
01830 {
01831 struct dahdi_pvt *p = ast->tech_pvt;
01832 int x, res, index,mysig;
01833 char *c, *n, *l;
01834 #ifdef HAVE_PRI
01835 char *s = NULL;
01836 #endif
01837 char dest[256];
01838 ast_mutex_lock(&p->lock);
01839 ast_copy_string(dest, rdest, sizeof(dest));
01840 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01841 if ((ast->_state == AST_STATE_BUSY)) {
01842 p->subs[SUB_REAL].needbusy = 1;
01843 ast_mutex_unlock(&p->lock);
01844 return 0;
01845 }
01846 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01847 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
01848 ast_mutex_unlock(&p->lock);
01849 return -1;
01850 }
01851 p->dialednone = 0;
01852 if ((p->radio || (p->oprmode < 0)))
01853 {
01854
01855 ast_setstate(ast, AST_STATE_UP);
01856 ast_mutex_unlock(&p->lock);
01857 return 0;
01858 }
01859 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
01860 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
01861 if (res)
01862 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
01863 p->outgoing = 1;
01864
01865 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01866
01867 mysig = p->sig;
01868 if (p->outsigmod > -1)
01869 mysig = p->outsigmod;
01870
01871 switch (mysig) {
01872 case SIG_FXOLS:
01873 case SIG_FXOGS:
01874 case SIG_FXOKS:
01875 if (p->owner == ast) {
01876
01877
01878
01879 p->dialing = 1;
01880 if (p->use_callerid) {
01881
01882 if (p->cidspill) {
01883 ast_log(LOG_WARNING, "cidspill already exists??\n");
01884 free(p->cidspill);
01885 }
01886 p->callwaitcas = 0;
01887 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01888 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01889 p->cidpos = 0;
01890 send_callerid(p);
01891 }
01892 }
01893
01894 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01895 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01896 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
01897 p->cidrings = cidrings[p->distinctivering - 1];
01898 } else {
01899 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01900 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
01901 p->cidrings = p->sendcalleridafter;
01902 }
01903
01904
01905 c = strchr(dest, '/');
01906 if (c)
01907 c++;
01908 if (c && (strlen(c) < p->stripmsd)) {
01909 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01910 c = NULL;
01911 }
01912 if (c) {
01913 p->dop.op = DAHDI_DIAL_OP_REPLACE;
01914 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01915 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01916 } else {
01917 p->dop.dialstr[0] = '\0';
01918 }
01919 x = DAHDI_RING;
01920 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
01921 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01922 ast_mutex_unlock(&p->lock);
01923 return -1;
01924 }
01925 p->dialing = 1;
01926 } else {
01927
01928 p->callwaitrings = 0;
01929 if (ast->cid.cid_num)
01930 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01931 else
01932 p->callwait_num[0] = '\0';
01933 if (ast->cid.cid_name)
01934 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01935 else
01936 p->callwait_name[0] = '\0';
01937
01938 if (dahdi_callwait(ast)) {
01939 ast_mutex_unlock(&p->lock);
01940 return -1;
01941 }
01942
01943 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
01944 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01945
01946 }
01947 n = ast->cid.cid_name;
01948 l = ast->cid.cid_num;
01949 if (l)
01950 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01951 else
01952 p->lastcid_num[0] = '\0';
01953 if (n)
01954 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01955 else
01956 p->lastcid_name[0] = '\0';
01957 ast_setstate(ast, AST_STATE_RINGING);
01958 index = dahdi_get_index(ast, p, 0);
01959 if (index > -1) {
01960 p->subs[index].needringing = 1;
01961 }
01962 break;
01963 case SIG_FXSLS:
01964 case SIG_FXSGS:
01965 case SIG_FXSKS:
01966 case SIG_EMWINK:
01967 case SIG_EM:
01968 case SIG_EM_E1:
01969 case SIG_FEATD:
01970 case SIG_FEATDMF:
01971 case SIG_E911:
01972 case SIG_FGC_CAMA:
01973 case SIG_FGC_CAMAMF:
01974 case SIG_FEATB:
01975 case SIG_SFWINK:
01976 case SIG_SF:
01977 case SIG_SF_FEATD:
01978 case SIG_SF_FEATDMF:
01979 case SIG_FEATDMF_TA:
01980 case SIG_SF_FEATB:
01981 c = strchr(dest, '/');
01982 if (c)
01983 c++;
01984 else
01985 c = "";
01986 if (strlen(c) < p->stripmsd) {
01987 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01988 ast_mutex_unlock(&p->lock);
01989 return -1;
01990 }
01991 #ifdef HAVE_PRI
01992
01993 if (!p->pri) {
01994 #endif
01995 x = DAHDI_START;
01996 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
01997 if (res < 0) {
01998 if (errno != EINPROGRESS) {
01999 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02000 ast_mutex_unlock(&p->lock);
02001 return -1;
02002 }
02003 }
02004 #ifdef HAVE_PRI
02005 }
02006 #endif
02007 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02008 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02009
02010 c += p->stripmsd;
02011
02012 switch (mysig) {
02013 case SIG_FEATD:
02014 l = ast->cid.cid_num;
02015 if (l)
02016 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02017 else
02018 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02019 break;
02020 case SIG_FEATDMF:
02021 l = ast->cid.cid_num;
02022 if (l)
02023 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02024 else
02025 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02026 break;
02027 case SIG_FEATDMF_TA:
02028 {
02029 const char *cic, *ozz;
02030
02031
02032 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02033 if (!ozz)
02034 ozz = defaultozz;
02035 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02036 if (!cic)
02037 cic = defaultcic;
02038 if (!ozz || !cic) {
02039 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02040 ast_mutex_unlock(&p->lock);
02041 return -1;
02042 }
02043 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02044 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02045 p->whichwink = 0;
02046 }
02047 break;
02048 case SIG_E911:
02049 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02050 break;
02051 case SIG_FGC_CAMA:
02052 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02053 break;
02054 case SIG_FGC_CAMAMF:
02055 case SIG_FEATB:
02056 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02057 break;
02058 default:
02059 if (p->pulse)
02060 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02061 else
02062 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02063 break;
02064 }
02065
02066 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02067 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02068 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02069 p->echorest[sizeof(p->echorest) - 1] = '\0';
02070 p->echobreak = 1;
02071 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02072 } else
02073 p->echobreak = 0;
02074 if (!res) {
02075 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02076 int saveerr = errno;
02077
02078 x = DAHDI_ONHOOK;
02079 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02080 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02081 ast_mutex_unlock(&p->lock);
02082 return -1;
02083 }
02084 } else
02085 ast_log(LOG_DEBUG, "Deferring dialing...\n");
02086 p->dialing = 1;
02087 if (ast_strlen_zero(c))
02088 p->dialednone = 1;
02089 ast_setstate(ast, AST_STATE_DIALING);
02090 break;
02091 case 0:
02092
02093 ast_setstate(ast, AST_STATE_UP);
02094 break;
02095 case SIG_PRI:
02096
02097 p->dialdest[0] = '\0';
02098 break;
02099 default:
02100 ast_log(LOG_DEBUG, "not yet implemented\n");
02101 ast_mutex_unlock(&p->lock);
02102 return -1;
02103 }
02104 #ifdef HAVE_PRI
02105 if (p->pri) {
02106 struct pri_sr *sr;
02107 #ifdef SUPPORT_USERUSER
02108 const char *useruser;
02109 #endif
02110 int pridialplan;
02111 int dp_strip;
02112 int prilocaldialplan;
02113 int ldp_strip;
02114 int exclusive;
02115 const char *rr_str;
02116 int redirect_reason;
02117
02118 c = strchr(dest, '/');
02119 if (c)
02120 c++;
02121 else
02122 c = dest;
02123
02124 l = NULL;
02125 n = NULL;
02126
02127 if (!p->hidecallerid) {
02128 l = ast->cid.cid_num;
02129 if (!p->hidecalleridname) {
02130 n = ast->cid.cid_name;
02131 }
02132 }
02133
02134
02135 if (strlen(c) < p->stripmsd) {
02136 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02137 ast_mutex_unlock(&p->lock);
02138 return -1;
02139 }
02140 if (mysig != SIG_FXSKS) {
02141 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02142 s = strchr(c + p->stripmsd, 'w');
02143 if (s) {
02144 if (strlen(s) > 1)
02145 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02146 else
02147 p->dop.dialstr[0] = '\0';
02148 *s = '\0';
02149 } else {
02150 p->dop.dialstr[0] = '\0';
02151 }
02152 }
02153 if (pri_grab(p, p->pri)) {
02154 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02155 ast_mutex_unlock(&p->lock);
02156 return -1;
02157 }
02158 if (!(p->call = pri_new_call(p->pri->pri))) {
02159 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02160 pri_rel(p->pri);
02161 ast_mutex_unlock(&p->lock);
02162 return -1;
02163 }
02164 if (!(sr = pri_sr_new())) {
02165 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02166 pri_destroycall(p->pri->pri, p->call);
02167 p->call = NULL;
02168 pri_rel(p->pri);
02169 ast_mutex_unlock(&p->lock);
02170 return -1;
02171 }
02172 if (p->bearer || (mysig == SIG_FXSKS)) {
02173 if (p->bearer) {
02174 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);
02175 p->bearer->call = p->call;
02176 } else
02177 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02178 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02179 }
02180 p->digital = IS_DIGITAL(ast->transfercapability);
02181
02182 if (p->priexclusive)
02183 exclusive = 1;
02184 else {
02185
02186 if (p->pri->nodetype == PRI_NETWORK)
02187 exclusive = 0;
02188 else
02189 exclusive = 1;
02190 }
02191
02192 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02193 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02194 (p->digital ? -1 :
02195 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02196 if (p->pri->facilityenable)
02197 pri_facility_enable(p->pri->pri);
02198
02199 if (option_verbose > 2)
02200 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02201 dp_strip = 0;
02202 pridialplan = p->pri->dialplan - 1;
02203 if (pridialplan == -2) {
02204 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02205 dp_strip = strlen(p->pri->internationalprefix);
02206 pridialplan = PRI_INTERNATIONAL_ISDN;
02207 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02208 dp_strip = strlen(p->pri->nationalprefix);
02209 pridialplan = PRI_NATIONAL_ISDN;
02210 } else {
02211 pridialplan = PRI_LOCAL_ISDN;
02212 }
02213 }
02214 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02215
02216 ldp_strip = 0;
02217 prilocaldialplan = p->pri->localdialplan - 1;
02218 if ((l != NULL) && (prilocaldialplan == -2)) {
02219 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02220 ldp_strip = strlen(p->pri->internationalprefix);
02221 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02222 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02223 ldp_strip = strlen(p->pri->nationalprefix);
02224 prilocaldialplan = PRI_NATIONAL_ISDN;
02225 } else {
02226 prilocaldialplan = PRI_LOCAL_ISDN;
02227 }
02228 }
02229 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02230 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02231 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02232 if (!strcasecmp(rr_str, "UNKNOWN"))
02233 redirect_reason = 0;
02234 else if (!strcasecmp(rr_str, "BUSY"))
02235 redirect_reason = 1;
02236 else if (!strcasecmp(rr_str, "NO_REPLY"))
02237 redirect_reason = 2;
02238 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02239 redirect_reason = 15;
02240 else
02241 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02242 } else
02243 redirect_reason = PRI_REDIR_UNCONDITIONAL;
02244 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02245
02246 #ifdef SUPPORT_USERUSER
02247
02248 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02249
02250 if (useruser)
02251 pri_sr_set_useruser(sr, useruser);
02252 #endif
02253
02254 if (pri_setup(p->pri->pri, p->call, sr)) {
02255 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
02256 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02257 pri_rel(p->pri);
02258 ast_mutex_unlock(&p->lock);
02259 pri_sr_free(sr);
02260 return -1;
02261 }
02262 pri_sr_free(sr);
02263 ast_setstate(ast, AST_STATE_DIALING);
02264 pri_rel(p->pri);
02265 }
02266 #endif
02267 ast_mutex_unlock(&p->lock);
02268 return 0;
02269 }
02270
02271 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02272 {
02273 struct dahdi_pvt *p = *pvt;
02274
02275 if (p->prev)
02276 p->prev->next = p->next;
02277 if (p->next)
02278 p->next->prev = p->prev;
02279 if (p->use_smdi)
02280 ast_smdi_interface_unref(p->smdi_iface);
02281 ast_mutex_destroy(&p->lock);
02282 dahdi_close_sub(p, SUB_REAL);
02283 if (p->owner)
02284 p->owner->tech_pvt = NULL;
02285 free(p);
02286 *pvt = NULL;
02287 }
02288
02289 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02290 {
02291 int owned = 0;
02292 int i = 0;
02293
02294 if (!now) {
02295 if (cur->owner) {
02296 owned = 1;
02297 }
02298
02299 for (i = 0; i < 3; i++) {
02300 if (cur->subs[i].owner) {
02301 owned = 1;
02302 }
02303 }
02304 if (!owned) {
02305 if (prev) {
02306 prev->next = cur->next;
02307 if (prev->next)
02308 prev->next->prev = prev;
02309 else
02310 ifend = prev;
02311 } else {
02312 iflist = cur->next;
02313 if (iflist)
02314 iflist->prev = NULL;
02315 else
02316 ifend = NULL;
02317 }
02318 destroy_dahdi_pvt(&cur);
02319 }
02320 } else {
02321 if (prev) {
02322 prev->next = cur->next;
02323 if (prev->next)
02324 prev->next->prev = prev;
02325 else
02326 ifend = prev;
02327 } else {
02328 iflist = cur->next;
02329 if (iflist)
02330 iflist->prev = NULL;
02331 else
02332 ifend = NULL;
02333 }
02334 destroy_dahdi_pvt(&cur);
02335 }
02336 return 0;
02337 }
02338
02339 static void destroy_all_channels(void)
02340 {
02341 int x;
02342 struct dahdi_pvt *p, *pl;
02343
02344 while (num_restart_pending) {
02345 usleep(1);
02346 }
02347
02348 ast_mutex_lock(&iflock);
02349
02350 p = iflist;
02351 while (p) {
02352
02353 if (p->cidspill)
02354 ast_free(p->cidspill);
02355 pl = p;
02356 p = p->next;
02357 x = pl->channel;
02358
02359 if (pl)
02360 destroy_dahdi_pvt(&pl);
02361 if (option_verbose > 2)
02362 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02363 }
02364 iflist = NULL;
02365 ifcount = 0;
02366 ast_mutex_unlock(&iflock);
02367 }
02368
02369 #ifdef HAVE_PRI
02370 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02371 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02372
02373 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02374 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02375
02376 static char *dahdi_send_keypad_facility_descrip =
02377 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02378 " IE over the current channel.\n";
02379 static char *zap_send_keypad_facility_descrip =
02380 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02381 " IE over the current channel.\n";
02382
02383 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02384 {
02385
02386 struct dahdi_pvt *p;
02387 char *digits = (char *) data;
02388
02389 if (ast_strlen_zero(digits)) {
02390 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02391 return -1;
02392 }
02393
02394 p = (struct dahdi_pvt *)chan->tech_pvt;
02395
02396 if (!p) {
02397 ast_log(LOG_DEBUG, "Unable to find technology private\n");
02398 return -1;
02399 }
02400
02401 ast_mutex_lock(&p->lock);
02402
02403 if (!p->pri || !p->call) {
02404 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02405 ast_mutex_unlock(&p->lock);
02406 return -1;
02407 }
02408
02409 if (!pri_grab(p, p->pri)) {
02410 pri_keypad_facility(p->pri->pri, p->call, digits);
02411 pri_rel(p->pri);
02412 } else {
02413 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02414 ast_mutex_unlock(&p->lock);
02415 return -1;
02416 }
02417
02418 ast_mutex_unlock(&p->lock);
02419
02420 return 0;
02421 }
02422
02423 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02424 {
02425 return send_keypad_facility_exec(chan, data);
02426 }
02427
02428 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02429 {
02430 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);
02431 return send_keypad_facility_exec(chan, data);
02432 }
02433
02434 static int pri_is_up(struct dahdi_pri *pri)
02435 {
02436 int x;
02437 for (x = 0; x < NUM_DCHANS; x++) {
02438 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02439 return 1;
02440 }
02441 return 0;
02442 }
02443
02444 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02445 {
02446 bearer->owner = &inuse;
02447 bearer->realcall = crv;
02448 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02449 if (crv->subs[SUB_REAL].owner)
02450 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02451 crv->bearer = bearer;
02452 crv->call = bearer->call;
02453 crv->pri = pri;
02454 return 0;
02455 }
02456
02457 static char *pri_order(int level)
02458 {
02459 switch (level) {
02460 case 0:
02461 return "Primary";
02462 case 1:
02463 return "Secondary";
02464 case 2:
02465 return "Tertiary";
02466 case 3:
02467 return "Quaternary";
02468 default:
02469 return "<Unknown>";
02470 }
02471 }
02472
02473
02474 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02475 {
02476 int x = -1;
02477
02478 for (x = 0; x < NUM_DCHANS; x++) {
02479 if ((pri->dchans[x] == pri->pri))
02480 break;
02481 }
02482
02483 return pri->fds[x];
02484 }
02485
02486 static int pri_find_dchan(struct dahdi_pri *pri)
02487 {
02488 int oldslot = -1;
02489 struct pri *old;
02490 int newslot = -1;
02491 int x;
02492 old = pri->pri;
02493 for (x = 0; x < NUM_DCHANS; x++) {
02494 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02495 newslot = x;
02496 if (pri->dchans[x] == old) {
02497 oldslot = x;
02498 }
02499 }
02500 if (newslot < 0) {
02501 newslot = 0;
02502 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
02503 pri->dchannels[newslot]);
02504 }
02505 if (old && (oldslot != newslot))
02506 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02507 pri->dchannels[oldslot], pri->dchannels[newslot]);
02508 pri->pri = pri->dchans[newslot];
02509 return 0;
02510 }
02511 #endif
02512
02513 static int dahdi_hangup(struct ast_channel *ast)
02514 {
02515 int res;
02516 int index,x, law;
02517
02518 struct dahdi_pvt *p = ast->tech_pvt;
02519 struct dahdi_pvt *tmp = NULL;
02520 struct dahdi_pvt *prev = NULL;
02521 struct dahdi_params par;
02522
02523 if (option_debug)
02524 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02525 if (!ast->tech_pvt) {
02526 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02527 return 0;
02528 }
02529
02530 ast_mutex_lock(&p->lock);
02531
02532 index = dahdi_get_index(ast, p, 1);
02533
02534 if (p->sig == SIG_PRI) {
02535 x = 1;
02536 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02537 }
02538
02539 x = 0;
02540 dahdi_confmute(p, 0);
02541 restore_gains(p);
02542 if (p->origcid_num) {
02543 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02544 free(p->origcid_num);
02545 p->origcid_num = NULL;
02546 }
02547 if (p->origcid_name) {
02548 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02549 free(p->origcid_name);
02550 p->origcid_name = NULL;
02551 }
02552 if (p->dsp)
02553 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02554 if (p->exten)
02555 p->exten[0] = '\0';
02556
02557 if (option_debug)
02558 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02559 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02560 p->ignoredtmf = 0;
02561
02562 if (index > -1) {
02563
02564 p->subs[index].owner = NULL;
02565 p->subs[index].needanswer = 0;
02566 p->subs[index].needflash = 0;
02567 p->subs[index].needringing = 0;
02568 p->subs[index].needbusy = 0;
02569 p->subs[index].needcongestion = 0;
02570 p->subs[index].linear = 0;
02571 p->subs[index].needcallerid = 0;
02572 p->polarity = POLARITY_IDLE;
02573 dahdi_setlinear(p->subs[index].dfd, 0);
02574 if (index == SUB_REAL) {
02575 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02576 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02577 if (p->subs[SUB_CALLWAIT].inthreeway) {
02578
02579 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02580
02581 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02582 unalloc_sub(p, SUB_CALLWAIT);
02583 p->owner = NULL;
02584 } else {
02585
02586 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
02587 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02588 unalloc_sub(p, SUB_THREEWAY);
02589 if (p->subs[SUB_REAL].inthreeway) {
02590
02591
02592 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02593 p->owner = p->subs[SUB_REAL].owner;
02594 } else {
02595
02596 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02597 p->owner = NULL;
02598 }
02599 p->subs[SUB_REAL].inthreeway = 0;
02600 }
02601 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02602
02603 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02604 unalloc_sub(p, SUB_CALLWAIT);
02605 p->owner = p->subs[SUB_REAL].owner;
02606 if (p->owner->_state != AST_STATE_UP)
02607 p->subs[SUB_REAL].needanswer = 1;
02608 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02609 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02610 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02611 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02612 unalloc_sub(p, SUB_THREEWAY);
02613 if (p->subs[SUB_REAL].inthreeway) {
02614
02615
02616 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02617 p->owner = p->subs[SUB_REAL].owner;
02618 } else {
02619
02620 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02621 p->owner = NULL;
02622 }
02623 p->subs[SUB_REAL].inthreeway = 0;
02624 }
02625 } else if (index == SUB_CALLWAIT) {
02626
02627 if (p->subs[SUB_CALLWAIT].inthreeway) {
02628
02629
02630 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02631 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
02632 S_OR(p->mohsuggest, NULL),
02633 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02634 }
02635 p->subs[SUB_THREEWAY].inthreeway = 0;
02636
02637 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02638 unalloc_sub(p, SUB_THREEWAY);
02639 } else
02640 unalloc_sub(p, SUB_CALLWAIT);
02641 } else if (index == SUB_THREEWAY) {
02642 if (p->subs[SUB_CALLWAIT].inthreeway) {
02643
02644
02645 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02646 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
02647 S_OR(p->mohsuggest, NULL),
02648 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02649 }
02650 p->subs[SUB_CALLWAIT].inthreeway = 0;
02651 }
02652 p->subs[SUB_REAL].inthreeway = 0;
02653
02654
02655 unalloc_sub(p, SUB_THREEWAY);
02656 } else {
02657
02658 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02659 }
02660 }
02661
02662 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02663 p->owner = NULL;
02664 p->ringt = 0;
02665 p->distinctivering = 0;
02666 p->confirmanswer = 0;
02667 p->cidrings = 1;
02668 p->outgoing = 0;
02669 p->digital = 0;
02670 p->faxhandled = 0;
02671 p->pulsedial = 0;
02672 p->onhooktime = time(NULL);
02673 #ifdef HAVE_PRI
02674 p->proceeding = 0;
02675 p->progress = 0;
02676 p->alerting = 0;
02677 p->setup_ack = 0;
02678 #endif
02679 if (p->dsp) {
02680 ast_dsp_free(p->dsp);
02681 p->dsp = NULL;
02682 }
02683
02684 law = DAHDI_LAW_DEFAULT;
02685 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02686 if (res < 0)
02687 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02688
02689 #ifdef HAVE_PRI
02690 if (p->pri) {
02691 #ifdef SUPPORT_USERUSER
02692 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02693 #endif
02694
02695
02696 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02697 if (!pri_grab(p, p->pri)) {
02698 if (p->alreadyhungup) {
02699 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
02700
02701 #ifdef SUPPORT_USERUSER
02702 pri_call_set_useruser(p->call, useruser);
02703 #endif
02704
02705 pri_hangup(p->pri->pri, p->call, -1);
02706 p->call = NULL;
02707 if (p->bearer)
02708 p->bearer->call = NULL;
02709 } else {
02710 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02711 int icause = ast->hangupcause ? ast->hangupcause : -1;
02712 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
02713
02714 #ifdef SUPPORT_USERUSER
02715 pri_call_set_useruser(p->call, useruser);
02716 #endif
02717
02718 p->alreadyhungup = 1;
02719 if (p->bearer)
02720 p->bearer->alreadyhungup = 1;
02721 if (cause) {
02722 if (atoi(cause))
02723 icause = atoi(cause);
02724 }
02725 pri_hangup(p->pri->pri, p->call, icause);
02726 }
02727 if (res < 0)
02728 ast_log(LOG_WARNING, "pri_disconnect failed\n");
02729 pri_rel(p->pri);
02730 } else {
02731 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02732 res = -1;
02733 }
02734 } else {
02735 if (p->bearer)
02736 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02737 p->call = NULL;
02738 res = 0;
02739 }
02740 }
02741 #endif
02742 if (p->sig && (p->sig != SIG_PRI))
02743 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
02744 if (res < 0) {
02745 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02746 }
02747 switch (p->sig) {
02748 case SIG_FXOGS:
02749 case SIG_FXOLS:
02750 case SIG_FXOKS:
02751 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02752 if (!res) {
02753 #if 0
02754 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02755 #endif
02756
02757 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02758 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
02759 else
02760 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02761 }
02762 break;
02763 case SIG_FXSGS:
02764 case SIG_FXSLS:
02765 case SIG_FXSKS:
02766
02767
02768 if (ast->_state != AST_STATE_RESERVED) {
02769 time(&p->guardtime);
02770 p->guardtime += 2;
02771 }
02772 break;
02773 default:
02774 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02775 }
02776 if (p->cidspill)
02777 free(p->cidspill);
02778 if (p->sig)
02779 dahdi_disable_ec(p);
02780 x = 0;
02781 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02782 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02783 p->didtdd = 0;
02784 p->cidspill = NULL;
02785 p->callwaitcas = 0;
02786 p->callwaiting = p->permcallwaiting;
02787 p->hidecallerid = p->permhidecallerid;
02788 p->dialing = 0;
02789 p->rdnis[0] = '\0';
02790 update_conf(p);
02791 reset_conf(p);
02792
02793 if (p->sig == SIG_PRI) {
02794 x = 0;
02795 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02796 }
02797 #ifdef HAVE_PRI
02798 if (p->bearer) {
02799 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02800
02801
02802 update_conf(p->bearer);
02803 reset_conf(p->bearer);
02804 p->bearer->owner = NULL;
02805 p->bearer->realcall = NULL;
02806 p->bearer = NULL;
02807 p->subs[SUB_REAL].dfd = -1;
02808 p->pri = NULL;
02809 }
02810 #endif
02811 if (num_restart_pending == 0)
02812 restart_monitor();
02813 }
02814
02815 p->callwaitingrepeat = 0;
02816 p->cidcwexpire = 0;
02817 p->oprmode = 0;
02818 ast->tech_pvt = NULL;
02819 ast_mutex_unlock(&p->lock);
02820 ast_module_unref(ast_module_info->self);
02821 if (option_verbose > 2)
02822 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02823
02824 ast_mutex_lock(&iflock);
02825
02826 if (p->restartpending) {
02827 num_restart_pending--;
02828 }
02829
02830 tmp = iflist;
02831 prev = NULL;
02832 if (p->destroy) {
02833 while (tmp) {
02834 if (tmp == p) {
02835 destroy_channel(prev, tmp, 0);
02836 break;
02837 } else {
02838 prev = tmp;
02839 tmp = tmp->next;
02840 }
02841 }
02842 }
02843 ast_mutex_unlock(&iflock);
02844 return 0;
02845 }
02846
02847 static int dahdi_answer(struct ast_channel *ast)
02848 {
02849 struct dahdi_pvt *p = ast->tech_pvt;
02850 int res = 0;
02851 int index;
02852 int oldstate = ast->_state;
02853 ast_setstate(ast, AST_STATE_UP);
02854 ast_mutex_lock(&p->lock);
02855 index = dahdi_get_index(ast, p, 0);
02856 if (index < 0)
02857 index = SUB_REAL;
02858
02859 if ((p->radio || (p->oprmode < 0))) {
02860 ast_mutex_unlock(&p->lock);
02861 return 0;
02862 }
02863 switch (p->sig) {
02864 case SIG_FXSLS:
02865 case SIG_FXSGS:
02866 case SIG_FXSKS:
02867 p->ringt = 0;
02868
02869 case SIG_EM:
02870 case SIG_EM_E1:
02871 case SIG_EMWINK:
02872 case SIG_FEATD:
02873 case SIG_FEATDMF:
02874 case SIG_FEATDMF_TA:
02875 case SIG_E911:
02876 case SIG_FGC_CAMA:
02877 case SIG_FGC_CAMAMF:
02878 case SIG_FEATB:
02879 case SIG_SF:
02880 case SIG_SFWINK:
02881 case SIG_SF_FEATD:
02882 case SIG_SF_FEATDMF:
02883 case SIG_SF_FEATB:
02884 case SIG_FXOLS:
02885 case SIG_FXOGS:
02886 case SIG_FXOKS:
02887
02888 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02889 if (p->hanguponpolarityswitch) {
02890 gettimeofday(&p->polaritydelaytv, NULL);
02891 }
02892 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02893 tone_zone_play_tone(p->subs[index].dfd, -1);
02894 p->dialing = 0;
02895 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02896 if (oldstate == AST_STATE_RINGING) {
02897 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02898 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
02899 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02900 p->owner = p->subs[SUB_REAL].owner;
02901 }
02902 }
02903 if (p->sig & __DAHDI_SIG_FXS) {
02904 dahdi_enable_ec(p);
02905 dahdi_train_ec(p);
02906 }
02907 break;
02908 #ifdef HAVE_PRI
02909 case SIG_PRI:
02910
02911 if (!pri_grab(p, p->pri)) {
02912 p->proceeding = 1;
02913 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02914 pri_rel(p->pri);
02915 } else {
02916 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02917 res = -1;
02918 }
02919 break;
02920 #endif
02921 case 0:
02922 ast_mutex_unlock(&p->lock);
02923 return 0;
02924 default:
02925 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02926 res = -1;
02927 }
02928 ast_mutex_unlock(&p->lock);
02929 return res;
02930 }
02931
02932 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
02933 {
02934 char *cp;
02935 signed char *scp;
02936 int x;
02937 int index;
02938 struct dahdi_pvt *p = chan->tech_pvt, *pp;
02939 struct oprmode *oprmode;
02940
02941
02942
02943 if (!data || (datalen < 1)) {
02944 errno = EINVAL;
02945 return -1;
02946 }
02947
02948 switch (option) {
02949 case AST_OPTION_TXGAIN:
02950 scp = (signed char *) data;
02951 index = dahdi_get_index(chan, p, 0);
02952 if (index < 0) {
02953 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02954 return -1;
02955 }
02956 if (option_debug)
02957 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02958 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
02959 case AST_OPTION_RXGAIN:
02960 scp = (signed char *) data;
02961 index = dahdi_get_index(chan, p, 0);
02962 if (index < 0) {
02963 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02964 return -1;
02965 }
02966 if (option_debug)
02967 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02968 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
02969 case AST_OPTION_TONE_VERIFY:
02970 if (!p->dsp)
02971 break;
02972 cp = (char *) data;
02973 switch (*cp) {
02974 case 1:
02975 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02976 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
02977 break;
02978 case 2:
02979 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02980 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
02981 break;
02982 default:
02983 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02984 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02985 break;
02986 }
02987 break;
02988 case AST_OPTION_TDD:
02989
02990 cp = (char *) data;
02991 p->mate = 0;
02992 if (!*cp) {
02993 if (option_debug)
02994 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02995 if (p->tdd)
02996 tdd_free(p->tdd);
02997 p->tdd = 0;
02998 break;
02999 }
03000 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03001 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03002 dahdi_disable_ec(p);
03003
03004 if (!p->didtdd) {
03005 unsigned char mybuf[41000], *buf;
03006 int size, res, fd, len;
03007 struct pollfd fds[1];
03008
03009 buf = mybuf;
03010 memset(buf, 0x7f, sizeof(mybuf));
03011 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03012 len = 40000;
03013 index = dahdi_get_index(chan, p, 0);
03014 if (index < 0) {
03015 ast_log(LOG_WARNING, "No index in TDD?\n");
03016 return -1;
03017 }
03018 fd = p->subs[index].dfd;
03019 while (len) {
03020 if (ast_check_hangup(chan))
03021 return -1;
03022 size = len;
03023 if (size > READ_SIZE)
03024 size = READ_SIZE;
03025 fds[0].fd = fd;
03026 fds[0].events = POLLPRI | POLLOUT;
03027 fds[0].revents = 0;
03028 res = poll(fds, 1, -1);
03029 if (!res) {
03030 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03031 continue;
03032 }
03033
03034 if (fds[0].revents & POLLPRI)
03035 return -1;
03036 if (!(fds[0].revents & POLLOUT)) {
03037 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03038 continue;
03039 }
03040 res = write(fd, buf, size);
03041 if (res != size) {
03042 if (res == -1) return -1;
03043 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03044 break;
03045 }
03046 len -= size;
03047 buf += size;
03048 }
03049 p->didtdd = 1;
03050 }
03051 if (*cp == 2) {
03052 if (p->tdd)
03053 tdd_free(p->tdd);
03054 p->tdd = 0;
03055 p->mate = 1;
03056 break;
03057 }
03058 if (!p->tdd) {
03059 p->tdd = tdd_new();
03060 }
03061 break;
03062 case AST_OPTION_RELAXDTMF:
03063 if (!p->dsp)
03064 break;
03065 cp = (char *) data;
03066 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03067 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03068 p->dtmfrelax = 0;
03069 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03070 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03071 break;
03072 case AST_OPTION_AUDIO_MODE:
03073 cp = (char *) data;
03074 if (!*cp) {
03075 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03076 x = 0;
03077 dahdi_disable_ec(p);
03078 } else {
03079 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03080 x = 1;
03081 }
03082 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03083 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03084 break;
03085 case AST_OPTION_OPRMODE:
03086 oprmode = (struct oprmode *) data;
03087 pp = oprmode->peer->tech_pvt;
03088 p->oprmode = pp->oprmode = 0;
03089
03090 p->oprpeer = pp;
03091 pp->oprpeer = p;
03092
03093 if (oprmode->mode)
03094 {
03095 pp->oprmode = oprmode->mode;
03096 p->oprmode = -oprmode->mode;
03097 }
03098 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03099 oprmode->mode, chan->name,oprmode->peer->name);;
03100 break;
03101 case AST_OPTION_ECHOCAN:
03102 cp = (char *) data;
03103 if (*cp) {
03104 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03105 dahdi_enable_ec(p);
03106 } else {
03107 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03108 dahdi_disable_ec(p);
03109 }
03110 break;
03111 }
03112 errno = 0;
03113
03114 return 0;
03115 }
03116
03117 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03118 {
03119 struct dahdi_pvt *p = chan->tech_pvt;
03120
03121 if (!strcasecmp(data, "rxgain")) {
03122 ast_mutex_lock(&p->lock);
03123 snprintf(buf, len, "%f", p->rxgain);
03124 ast_mutex_unlock(&p->lock);
03125 } else if (!strcasecmp(data, "txgain")) {
03126 ast_mutex_lock(&p->lock);
03127 snprintf(buf, len, "%f", p->txgain);
03128 ast_mutex_unlock(&p->lock);
03129 } else {
03130 ast_copy_string(buf, "", len);
03131 }
03132 return 0;
03133 }
03134
03135
03136 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03137 {
03138
03139 int x;
03140 int hasslaves;
03141 if (!master)
03142 return;
03143 if (needlock) {
03144 ast_mutex_lock(&master->lock);
03145 if (slave) {
03146 while (ast_mutex_trylock(&slave->lock)) {
03147 DEADLOCK_AVOIDANCE(&master->lock);
03148 }
03149 }
03150 }
03151 hasslaves = 0;
03152 for (x = 0; x < MAX_SLAVES; x++) {
03153 if (master->slaves[x]) {
03154 if (!slave || (master->slaves[x] == slave)) {
03155
03156 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03157 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03158 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03159 master->slaves[x]->master = NULL;
03160 master->slaves[x] = NULL;
03161 } else
03162 hasslaves = 1;
03163 }
03164 if (!hasslaves)
03165 master->inconference = 0;
03166 }
03167 if (!slave) {
03168 if (master->master) {
03169
03170 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03171 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03172 hasslaves = 0;
03173 for (x = 0; x < MAX_SLAVES; x++) {
03174 if (master->master->slaves[x] == master)
03175 master->master->slaves[x] = NULL;
03176 else if (master->master->slaves[x])
03177 hasslaves = 1;
03178 }
03179 if (!hasslaves)
03180 master->master->inconference = 0;
03181 }
03182 master->master = NULL;
03183 }
03184 update_conf(master);
03185 if (needlock) {
03186 if (slave)
03187 ast_mutex_unlock(&slave->lock);
03188 ast_mutex_unlock(&master->lock);
03189 }
03190 }
03191
03192 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03193 int x;
03194 if (!slave || !master) {
03195 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03196 return;
03197 }
03198 for (x = 0; x < MAX_SLAVES; x++) {
03199 if (!master->slaves[x]) {
03200 master->slaves[x] = slave;
03201 break;
03202 }
03203 }
03204 if (x >= MAX_SLAVES) {
03205 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03206 master->slaves[MAX_SLAVES - 1] = slave;
03207 }
03208 if (slave->master)
03209 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03210 slave->master = master;
03211
03212 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03213 }
03214
03215 static void disable_dtmf_detect(struct dahdi_pvt *p)
03216 {
03217 #ifdef DAHDI_TONEDETECT
03218 int val;
03219 #endif
03220
03221 p->ignoredtmf = 1;
03222
03223 #ifdef DAHDI_TONEDETECT
03224 val = 0;
03225 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03226 #endif
03227 if (!p->hardwaredtmf && p->dsp) {
03228 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03229 ast_dsp_set_features(p->dsp, p->dsp_features);
03230 }
03231 }
03232
03233 static void enable_dtmf_detect(struct dahdi_pvt *p)
03234 {
03235 #ifdef DAHDI_TONEDETECT
03236 int val;
03237 #endif
03238
03239 if (p->channel == CHAN_PSEUDO)
03240 return;
03241
03242 p->ignoredtmf = 0;
03243
03244 #ifdef DAHDI_TONEDETECT
03245 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03246 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03247 #endif
03248 if (!p->hardwaredtmf && p->dsp) {
03249 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03250 ast_dsp_set_features(p->dsp, p->dsp_features);
03251 }
03252 }
03253
03254 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)
03255 {
03256 struct ast_channel *who;
03257 struct dahdi_pvt *p0, *p1, *op0, *op1;
03258 struct dahdi_pvt *master = NULL, *slave = NULL;
03259 struct ast_frame *f;
03260 int inconf = 0;
03261 int nothingok = 1;
03262 int ofd0, ofd1;
03263 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03264 int os0 = -1, os1 = -1;
03265 int priority = 0;
03266 struct ast_channel *oc0, *oc1;
03267 enum ast_bridge_result res;
03268
03269 #ifdef PRI_2BCT
03270 int triedtopribridge = 0;
03271 q931_call *q931c0 = NULL, *q931c1 = NULL;
03272 #endif
03273
03274
03275
03276
03277
03278
03279 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03280 return AST_BRIDGE_FAILED_NOWARN;
03281
03282 ast_mutex_lock(&c0->lock);
03283 while (ast_mutex_trylock(&c1->lock)) {
03284 DEADLOCK_AVOIDANCE(&c0->lock);
03285 }
03286
03287 p0 = c0->tech_pvt;
03288 p1 = c1->tech_pvt;
03289
03290 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03291 ast_mutex_unlock(&c0->lock);
03292 ast_mutex_unlock(&c1->lock);
03293 return AST_BRIDGE_FAILED_NOWARN;
03294 }
03295
03296 oi0 = dahdi_get_index(c0, p0, 0);
03297 oi1 = dahdi_get_index(c1, p1, 0);
03298 if ((oi0 < 0) || (oi1 < 0)) {
03299 ast_mutex_unlock(&c0->lock);
03300 ast_mutex_unlock(&c1->lock);
03301 return AST_BRIDGE_FAILED;
03302 }
03303
03304 op0 = p0 = c0->tech_pvt;
03305 op1 = p1 = c1->tech_pvt;
03306 ofd0 = c0->fds[0];
03307 ofd1 = c1->fds[0];
03308 oc0 = p0->owner;
03309 oc1 = p1->owner;
03310
03311 if (ast_mutex_trylock(&p0->lock)) {
03312
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 if (ast_mutex_trylock(&p1->lock)) {
03319
03320 ast_mutex_unlock(&p0->lock);
03321 ast_mutex_unlock(&c0->lock);
03322 ast_mutex_unlock(&c1->lock);
03323 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03324 return AST_BRIDGE_RETRY;
03325 }
03326
03327 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03328 if (p0->owner && p1->owner) {
03329
03330 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03331 master = p0;
03332 slave = p1;
03333 inconf = 1;
03334 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03335 master = p1;
03336 slave = p0;
03337 inconf = 1;
03338 } else {
03339 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
03340 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03341 p0->channel,
03342 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03343 p0->subs[SUB_REAL].inthreeway, p0->channel,
03344 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03345 p1->subs[SUB_REAL].inthreeway);
03346 }
03347 nothingok = 0;
03348 }
03349 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03350 if (p1->subs[SUB_THREEWAY].inthreeway) {
03351 master = p1;
03352 slave = p0;
03353 nothingok = 0;
03354 }
03355 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03356 if (p0->subs[SUB_THREEWAY].inthreeway) {
03357 master = p0;
03358 slave = p1;
03359 nothingok = 0;
03360 }
03361 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03362
03363
03364 if (p1->subs[SUB_CALLWAIT].inthreeway) {
03365 master = p1;
03366 slave = p0;
03367 nothingok = 0;
03368 }
03369 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03370
03371 if (p0->subs[SUB_CALLWAIT].inthreeway) {
03372 master = p0;
03373 slave = p1;
03374 nothingok = 0;
03375 }
03376 }
03377 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03378 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03379 if (master && slave) {
03380
03381
03382
03383 if ((oi1 == SUB_THREEWAY) &&
03384 p1->subs[SUB_THREEWAY].inthreeway &&
03385 p1->subs[SUB_REAL].owner &&
03386 p1->subs[SUB_REAL].inthreeway &&
03387 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03388 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03389 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03390 os1 = p1->subs[SUB_REAL].owner->_state;
03391 } else {
03392 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03393 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03394 }
03395 if ((oi0 == SUB_THREEWAY) &&
03396 p0->subs[SUB_THREEWAY].inthreeway &&
03397 p0->subs[SUB_REAL].owner &&
03398 p0->subs[SUB_REAL].inthreeway &&
03399 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03400 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03401 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03402 os0 = p0->subs[SUB_REAL].owner->_state;
03403 } else {
03404 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03405 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03406 }
03407 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03408 if (!p0->echocanbridged || !p1->echocanbridged) {
03409
03410 dahdi_disable_ec(p0);
03411 dahdi_disable_ec(p1);
03412 }
03413 }
03414 dahdi_link(slave, master);
03415 master->inconference = inconf;
03416 } else if (!nothingok)
03417 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03418
03419 update_conf(p0);
03420 update_conf(p1);
03421 t0 = p0->subs[SUB_REAL].inthreeway;
03422 t1 = p1->subs[SUB_REAL].inthreeway;
03423
03424 ast_mutex_unlock(&p0->lock);
03425 ast_mutex_unlock(&p1->lock);
03426
03427 ast_mutex_unlock(&c0->lock);
03428 ast_mutex_unlock(&c1->lock);
03429
03430
03431 if ((!master || !slave) && !nothingok) {
03432 dahdi_enable_ec(p0);
03433 dahdi_enable_ec(p1);
03434 return AST_BRIDGE_FAILED;
03435 }
03436
03437 if (option_verbose > 2)
03438 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03439
03440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03441 disable_dtmf_detect(op0);
03442
03443 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03444 disable_dtmf_detect(op1);
03445
03446 for (;;) {
03447 struct ast_channel *c0_priority[2] = {c0, c1};
03448 struct ast_channel *c1_priority[2] = {c1, c0};
03449
03450
03451
03452 ast_mutex_lock(&c0->lock);
03453 while (ast_mutex_trylock(&c1->lock)) {
03454 DEADLOCK_AVOIDANCE(&c0->lock);
03455 }
03456
03457 p0 = c0->tech_pvt;
03458 p1 = c1->tech_pvt;
03459
03460 if (op0 == p0)
03461 i0 = dahdi_get_index(c0, p0, 1);
03462 if (op1 == p1)
03463 i1 = dahdi_get_index(c1, p1, 1);
03464 ast_mutex_unlock(&c0->lock);
03465 ast_mutex_unlock(&c1->lock);
03466
03467 if (!timeoutms ||
03468 (op0 != p0) ||
03469 (op1 != p1) ||
03470 (ofd0 != c0->fds[0]) ||
03471 (ofd1 != c1->fds[0]) ||
03472 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
03473 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
03474 (oc0 != p0->owner) ||
03475 (oc1 != p1->owner) ||
03476 (t0 != p0->subs[SUB_REAL].inthreeway) ||
03477 (t1 != p1->subs[SUB_REAL].inthreeway) ||
03478 (oi0 != i0) ||
03479 (oi1 != i1)) {
03480 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03481 op0->channel, oi0, op1->channel, oi1);
03482 res = AST_BRIDGE_RETRY;
03483 goto return_from_bridge;
03484 }
03485
03486 #ifdef PRI_2BCT
03487 q931c0 = p0->call;
03488 q931c1 = p1->call;
03489 if (p0->transfer && p1->transfer
03490 && q931c0 && q931c1
03491 && !triedtopribridge) {
03492 pri_channel_bridge(q931c0, q931c1);
03493 triedtopribridge = 1;
03494 }
03495 #endif
03496
03497 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03498 if (!who) {
03499 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03500 continue;
03501 }
03502 f = ast_read(who);
03503 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03504 *fo = f;
03505 *rc = who;
03506 res = AST_BRIDGE_COMPLETE;
03507 goto return_from_bridge;
03508 }
03509 if (f->frametype == AST_FRAME_DTMF) {
03510 if ((who == c0) && p0->pulsedial) {
03511 ast_write(c1, f);
03512 } else if ((who == c1) && p1->pulsedial) {
03513 ast_write(c0, f);
03514 } else {
03515 *fo = f;
03516 *rc = who;
03517 res = AST_BRIDGE_COMPLETE;
03518 goto return_from_bridge;
03519 }
03520 }
03521 ast_frfree(f);
03522
03523
03524 priority = !priority;
03525 }
03526
03527 return_from_bridge:
03528 if (op0 == p0)
03529 dahdi_enable_ec(p0);
03530
03531 if (op1 == p1)
03532 dahdi_enable_ec(p1);
03533
03534 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03535 enable_dtmf_detect(op0);
03536
03537 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03538 enable_dtmf_detect(op1);
03539
03540 dahdi_unlink(slave, master, 1);
03541
03542 return res;
03543 }
03544
03545 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03546 {
03547 struct dahdi_pvt *p = newchan->tech_pvt;
03548 int x;
03549 ast_mutex_lock(&p->lock);
03550 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03551 if (p->owner == oldchan) {
03552 p->owner = newchan;
03553 }
03554 for (x = 0; x < 3; x++)
03555 if (p->subs[x].owner == oldchan) {
03556 if (!x)
03557 dahdi_unlink(NULL, p, 0);
03558 p->subs[x].owner = newchan;
03559 }
03560 if (newchan->_state == AST_STATE_RINGING)
03561 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03562 update_conf(p);
03563 ast_mutex_unlock(&p->lock);
03564 return 0;
03565 }
03566
03567 static int dahdi_ring_phone(struct dahdi_pvt *p)
03568 {
03569 int x;
03570 int res;
03571
03572 x = 0;
03573 x = DAHDI_ONHOOK;
03574 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03575 do {
03576 x = DAHDI_RING;
03577 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03578 if (res) {
03579 switch (errno) {
03580 case EBUSY:
03581 case EINTR:
03582
03583 usleep(10000);
03584 continue;
03585 case EINPROGRESS:
03586 res = 0;
03587 break;
03588 default:
03589 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03590 res = 0;
03591 }
03592 }
03593 } while (res);
03594 return res;
03595 }
03596
03597 static void *ss_thread(void *data);
03598
03599 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03600
03601 static int attempt_transfer(struct dahdi_pvt *p)
03602 {
03603
03604
03605
03606 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03607
03608
03609 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03610 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03611 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03612 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03613 }
03614 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03615 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03616 }
03617 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03618 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03619 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03620 return -1;
03621 }
03622
03623 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03624 unalloc_sub(p, SUB_THREEWAY);
03625 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03626 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03627 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03628 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03629 }
03630 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03631 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03632 }
03633 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03634 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03635 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03636 return -1;
03637 }
03638
03639 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03640 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03641 unalloc_sub(p, SUB_THREEWAY);
03642
03643 return 1;
03644 } else {
03645 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03646 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03647 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03648 return -1;
03649 }
03650 return 0;
03651 }
03652
03653 static int check_for_conference(struct dahdi_pvt *p)
03654 {
03655 struct dahdi_confinfo ci;
03656
03657 if (p->master || (p->confno > -1))
03658 return 0;
03659 memset(&ci, 0, sizeof(ci));
03660 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03661 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03662 return 0;
03663 }
03664
03665
03666
03667 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03668 if (option_verbose > 2)
03669 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03670 return 1;
03671 }
03672 return 0;
03673 }
03674
03675 static int get_alarms(struct dahdi_pvt *p)
03676 {
03677 int res;
03678 struct dahdi_spaninfo zi;
03679 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03680
03681
03682
03683
03684
03685 struct dahdi_params params;
03686 #endif
03687
03688 memset(&zi, 0, sizeof(zi));
03689 zi.spanno = p->span;
03690
03691
03692 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03693 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03694 return 0;
03695 }
03696 if (zi.alarms != DAHDI_ALARM_NONE)
03697 return zi.alarms;
03698 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03699
03700 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
03701 return params.chan_alarms;
03702
03703 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03704 #endif
03705 return DAHDI_ALARM_NONE;
03706 }
03707
03708 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
03709 {
03710 struct dahdi_pvt *p = ast->tech_pvt;
03711 struct ast_frame *f = *dest;
03712
03713 if (option_debug)
03714 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03715
03716 if (p->confirmanswer) {
03717 if (option_debug)
03718 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03719
03720
03721 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03722 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03723 *dest = &p->subs[index].f;
03724
03725 p->confirmanswer = 0;
03726 } else if (p->callwaitcas) {
03727 if ((f->subclass == 'A') || (f->subclass == 'D')) {
03728 if (option_debug)
03729 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03730 if (p->cidspill)
03731 free(p->cidspill);
03732 send_cwcidspill(p);
03733 }
03734 if ((f->subclass != 'm') && (f->subclass != 'u'))
03735 p->callwaitcas = 0;
03736 p->subs[index].f.frametype = AST_FRAME_NULL;
03737 p->subs[index].f.subclass = 0;
03738 *dest = &p->subs[index].f;
03739 } else if (f->subclass == 'f') {
03740
03741 if ((p->callprogress & 0x6) && !p->faxhandled) {
03742 p->faxhandled++;
03743 if (strcmp(ast->exten, "fax")) {
03744 const char *target_context = S_OR(ast->macrocontext, ast->context);
03745
03746 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
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_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03755 } else if (option_debug)
03756 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03757 } else if (option_debug)
03758 ast_log(LOG_DEBUG, "Fax already handled\n");
03759 dahdi_confmute(p, 0);
03760 p->subs[index].f.frametype = AST_FRAME_NULL;
03761 p->subs[index].f.subclass = 0;
03762 *dest = &p->subs[index].f;
03763 } else if (f->subclass == 'm') {
03764
03765 dahdi_confmute(p, 1);
03766 p->subs[index].f.frametype = AST_FRAME_NULL;
03767 p->subs[index].f.subclass = 0;
03768 *dest = &p->subs[index].f;
03769 } else if (f->subclass == 'u') {
03770
03771 dahdi_confmute(p, 0);
03772 p->subs[index].f.frametype = AST_FRAME_NULL;
03773 p->subs[index].f.subclass = 0;
03774 *dest = &p->subs[index].f;
03775 } else
03776 dahdi_confmute(p, 0);
03777 }
03778
03779 static void handle_alarms(struct dahdi_pvt *p, int alarms)
03780 {
03781 const char *alarm_str = alarm2str(alarms);
03782
03783
03784
03785 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
03786 p->unknown_alarm = 1;
03787 return;
03788 } else {
03789 p->unknown_alarm = 0;
03790 }
03791
03792 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
03793 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03794 "Alarm: %s\r\n"
03795 "Channel: %d\r\n",
03796 alarm_str, p->channel);
03797 }
03798
03799 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
03800 {
03801 int res, x;
03802 int index, mysig;
03803 char *c;
03804 struct dahdi_pvt *p = ast->tech_pvt;
03805 pthread_t threadid;
03806 pthread_attr_t attr;
03807 struct ast_channel *chan;
03808 struct ast_frame *f;
03809
03810 index = dahdi_get_index(ast, p, 0);
03811 mysig = p->sig;
03812 if (p->outsigmod > -1)
03813 mysig = p->outsigmod;
03814 p->subs[index].f.frametype = AST_FRAME_NULL;
03815 p->subs[index].f.subclass = 0;
03816 p->subs[index].f.datalen = 0;
03817 p->subs[index].f.samples = 0;
03818 p->subs[index].f.mallocd = 0;
03819 p->subs[index].f.offset = 0;
03820 p->subs[index].f.src = "dahdi_handle_event";
03821 p->subs[index].f.data = NULL;
03822 f = &p->subs[index].f;
03823
03824 if (index < 0)
03825 return &p->subs[index].f;
03826 if (p->fake_event) {
03827 res = p->fake_event;
03828 p->fake_event = 0;
03829 } else
03830 res = dahdi_get_event(p->subs[index].dfd);
03831
03832 if (option_debug)
03833 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03834
03835 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
03836 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
03837
03838 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03839 #ifdef HAVE_PRI
03840 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03841
03842 } else {
03843 #endif
03844 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03845 p->subs[index].f.subclass = res & 0xff;
03846 #ifdef HAVE_PRI
03847 }
03848 #endif
03849 dahdi_handle_dtmfup(ast, index, &f);
03850 return f;
03851 }
03852
03853 if (res & DAHDI_EVENT_DTMFDOWN) {
03854 if (option_debug)
03855 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03856
03857 dahdi_confmute(p, 1);
03858 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03859 p->subs[index].f.subclass = res & 0xff;
03860 return &p->subs[index].f;
03861 }
03862
03863 switch (res) {
03864 #ifdef DAHDI_EVENT_EC_DISABLED
03865 case DAHDI_EVENT_EC_DISABLED:
03866 if (option_verbose > 2)
03867 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03868 p->echocanon = 0;
03869 break;
03870 #endif
03871 case DAHDI_EVENT_BITSCHANGED:
03872 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03873 case DAHDI_EVENT_PULSE_START:
03874
03875 if (!ast->pbx)
03876 tone_zone_play_tone(p->subs[index].dfd, -1);
03877 break;
03878 case DAHDI_EVENT_DIALCOMPLETE:
03879 if (p->inalarm) break;
03880 if ((p->radio || (p->oprmode < 0))) break;
03881 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
03882 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
03883 return NULL;
03884 }
03885 if (!x) {
03886 dahdi_enable_ec(p);
03887 if (p->echobreak) {
03888 dahdi_train_ec(p);
03889 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03890 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03891 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
03892 p->echobreak = 0;
03893 } else {
03894 p->dialing = 0;
03895 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03896
03897 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03898 ast_setstate(ast, AST_STATE_UP);
03899 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03900 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03901 break;
03902 } else {
03903
03904 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03905 }
03906 }
03907 if (ast->_state == AST_STATE_DIALING) {
03908 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03909 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03910 } 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)))) {
03911 ast_setstate(ast, AST_STATE_RINGING);
03912 } else if (!p->answeronpolarityswitch) {
03913 ast_setstate(ast, AST_STATE_UP);
03914 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03915 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03916
03917 p->polarity = POLARITY_REV;
03918 } else {
03919
03920 p->polarity = POLARITY_IDLE;
03921 }
03922 }
03923 }
03924 }
03925 break;
03926 case DAHDI_EVENT_ALARM:
03927 #ifdef HAVE_PRI
03928 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03929
03930 if (p->call) {
03931 if (p->pri && p->pri->pri) {
03932 if (!pri_grab(p, p->pri)) {
03933 pri_hangup(p->pri->pri, p->call, -1);
03934 pri_destroycall(p->pri->pri, p->call);
03935 p->call = NULL;
03936 pri_rel(p->pri);
03937 } else
03938 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03939 } else
03940 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03941 }
03942 if (p->owner)
03943 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03944 }
03945 if (p->bearer)
03946 p->bearer->inalarm = 1;
03947 else
03948 #endif
03949 p->inalarm = 1;
03950 res = get_alarms(p);
03951 handle_alarms(p, res);
03952 #ifdef HAVE_LIBPRI
03953 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03954
03955 } else {
03956 break;
03957 }
03958 #endif
03959 case DAHDI_EVENT_ONHOOK:
03960 if (p->radio) {
03961 p->subs[index].f.frametype = AST_FRAME_CONTROL;
03962 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03963 break;
03964 }
03965 if (p->oprmode < 0)
03966 {
03967 if (p->oprmode != -1) break;
03968 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03969 {
03970
03971 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
03972 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
03973 save_conference(p->oprpeer);
03974 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03975 }
03976 break;
03977 }
03978 switch (p->sig) {
03979 case SIG_FXOLS:
03980 case SIG_FXOGS:
03981 case SIG_FXOKS:
03982 p->onhooktime = time(NULL);
03983 p->msgstate = -1;
03984
03985 if (index == SUB_REAL) {
03986
03987 if (p->subs[SUB_CALLWAIT].owner) {
03988
03989 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03990 if (option_verbose > 2)
03991 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03992 unalloc_sub(p, SUB_CALLWAIT);
03993 #if 0
03994 p->subs[index].needanswer = 0;
03995 p->subs[index].needringing = 0;
03996 #endif
03997 p->callwaitingrepeat = 0;
03998 p->cidcwexpire = 0;
03999 p->owner = NULL;
04000
04001 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04002 p->dialing = 1;
04003 dahdi_ring_phone(p);
04004 } else if (p->subs[SUB_THREEWAY].owner) {
04005 unsigned int mssinceflash;
04006
04007
04008 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04009
04010 ast_mutex_unlock(&p->lock);
04011 DEADLOCK_AVOIDANCE(&ast->lock);
04012
04013
04014
04015 ast_mutex_lock(&p->lock);
04016 if (p->owner != ast) {
04017 ast_log(LOG_WARNING, "This isn't good...\n");
04018 return NULL;
04019 }
04020 }
04021 if (!p->subs[SUB_THREEWAY].owner) {
04022 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04023 return NULL;
04024 }
04025 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04026 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04027 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04028
04029
04030 if (p->subs[SUB_THREEWAY].owner)
04031 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04032 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04033 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04034 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04035 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04036 if (p->transfer) {
04037
04038 p->subs[SUB_REAL].inthreeway = 0;
04039 p->subs[SUB_THREEWAY].inthreeway = 0;
04040
04041 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04042 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04043
04044 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04045 p->owner = NULL;
04046
04047 dahdi_ring_phone(p);
04048 } else {
04049 if ((res = attempt_transfer(p)) < 0) {
04050 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04051 if (p->subs[SUB_THREEWAY].owner)
04052 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04053 } else if (res) {
04054
04055 if (p->subs[SUB_THREEWAY].owner)
04056 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04057 break;
04058 }
04059 }
04060 } else {
04061 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04062 if (p->subs[SUB_THREEWAY].owner)
04063 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04064 }
04065 } else {
04066 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04067
04068 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04069 p->owner = NULL;
04070
04071 dahdi_ring_phone(p);
04072 }
04073 }
04074 } else {
04075 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04076 }
04077
04078 default:
04079 dahdi_disable_ec(p);
04080 return NULL;
04081 }
04082 break;
04083 case DAHDI_EVENT_RINGOFFHOOK:
04084 if (p->inalarm) break;
04085 if (p->oprmode < 0)
04086 {
04087 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04088 {
04089
04090 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04091 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04092 restore_conference(p->oprpeer);
04093 }
04094 break;
04095 }
04096 if (p->radio)
04097 {
04098 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04099 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04100 break;
04101 }
04102
04103
04104 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04105 c = strchr(p->dialdest, '/');
04106 if (c)
04107 c++;
04108 else
04109 c = p->dialdest;
04110 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04111 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04112 if (strlen(p->dop.dialstr) > 4) {
04113 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04114 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04115 p->echorest[sizeof(p->echorest) - 1] = '\0';
04116 p->echobreak = 1;
04117 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04118 } else
04119 p->echobreak = 0;
04120 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04121 int saveerr = errno;
04122
04123 x = DAHDI_ONHOOK;
04124 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04125 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04126 return NULL;
04127 }
04128 p->dialing = 1;
04129 return &p->subs[index].f;
04130 }
04131 switch (p->sig) {
04132 case SIG_FXOLS:
04133 case SIG_FXOGS:
04134 case SIG_FXOKS:
04135 switch (ast->_state) {
04136 case AST_STATE_RINGING:
04137 dahdi_enable_ec(p);
04138 dahdi_train_ec(p);
04139 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04140 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04141
04142 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04143 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04144 if (p->cidspill) {
04145
04146 free(p->cidspill);
04147 p->cidspill = NULL;
04148 }
04149 p->dialing = 0;
04150 p->callwaitcas = 0;
04151 if (p->confirmanswer) {
04152
04153 p->subs[index].f.frametype = AST_FRAME_NULL;
04154 p->subs[index].f.subclass = 0;
04155 } else if (!ast_strlen_zero(p->dop.dialstr)) {
04156
04157 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04158 if (res < 0) {
04159 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04160 p->dop.dialstr[0] = '\0';
04161 return NULL;
04162 } else {
04163 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04164 p->subs[index].f.frametype = AST_FRAME_NULL;
04165 p->subs[index].f.subclass = 0;
04166 p->dialing = 1;
04167 }
04168 p->dop.dialstr[0] = '\0';
04169 ast_setstate(ast, AST_STATE_DIALING);
04170 } else
04171 ast_setstate(ast, AST_STATE_UP);
04172 return &p->subs[index].f;
04173 case AST_STATE_DOWN:
04174 ast_setstate(ast, AST_STATE_RING);
04175 ast->rings = 1;
04176 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04177 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04178 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04179 return &p->subs[index].f;
04180 case AST_STATE_UP:
04181
04182 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04183
04184 if (ast_bridged_channel(p->owner))
04185 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04186 p->subs[index].needunhold = 1;
04187 break;
04188 case AST_STATE_RESERVED:
04189
04190 if (has_voicemail(p))
04191 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04192 else
04193 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04194 break;
04195 default:
04196 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04197 }
04198 break;
04199 case SIG_FXSLS:
04200 case SIG_FXSGS:
04201 case SIG_FXSKS:
04202 if (ast->_state == AST_STATE_RING) {
04203 p->ringt = p->ringt_base;
04204 }
04205
04206
04207 case SIG_EM:
04208 case SIG_EM_E1:
04209 case SIG_EMWINK:
04210 case SIG_FEATD:
04211 case SIG_FEATDMF:
04212 case SIG_FEATDMF_TA:
04213 case SIG_E911:
04214 case SIG_FGC_CAMA:
04215 case SIG_FGC_CAMAMF:
04216 case SIG_FEATB:
04217 case SIG_SF:
04218 case SIG_SFWINK:
04219 case SIG_SF_FEATD:
04220 case SIG_SF_FEATDMF:
04221 case SIG_SF_FEATB:
04222 if (ast->_state == AST_STATE_PRERING)
04223 ast_setstate(ast, AST_STATE_RING);
04224 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04225 if (option_debug)
04226 ast_log(LOG_DEBUG, "Ring detected\n");
04227 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04228 p->subs[index].f.subclass = AST_CONTROL_RING;
04229 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04230 if (option_debug)
04231 ast_log(LOG_DEBUG, "Line answered\n");
04232 if (p->confirmanswer) {
04233 p->subs[index].f.frametype = AST_FRAME_NULL;
04234 p->subs[index].f.subclass = 0;
04235 } else {
04236 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04237 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04238 ast_setstate(ast, AST_STATE_UP);
04239 }
04240 } else if (ast->_state != AST_STATE_RING)
04241 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04242 break;
04243 default:
04244 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04245 }
04246 break;
04247 #ifdef DAHDI_EVENT_RINGBEGIN
04248 case DAHDI_EVENT_RINGBEGIN:
04249 switch (p->sig) {
04250 case SIG_FXSLS:
04251 case SIG_FXSGS:
04252 case SIG_FXSKS:
04253 if (ast->_state == AST_STATE_RING) {
04254 p->ringt = p->ringt_base;
04255 }
04256 break;
04257 }
04258 break;
04259 #endif
04260 case DAHDI_EVENT_RINGEROFF:
04261 if (p->inalarm) break;
04262 if ((p->radio || (p->oprmode < 0))) break;
04263 ast->rings++;
04264 if ((ast->rings > p->cidrings) && (p->cidspill)) {
04265 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
04266 free(p->cidspill);
04267 p->cidspill = NULL;
04268 p->callwaitcas = 0;
04269 }
04270 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04271 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04272 break;
04273 case DAHDI_EVENT_RINGERON:
04274 break;
04275 case DAHDI_EVENT_NOALARM:
04276 p->inalarm = 0;
04277 #ifdef HAVE_PRI
04278
04279 if (p->bearer)
04280 p->bearer->inalarm = 0;
04281 #endif
04282 if (!p->unknown_alarm) {
04283 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04284 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04285 "Channel: %d\r\n", p->channel);
04286 } else {
04287 p->unknown_alarm = 0;
04288 }
04289 break;
04290 case DAHDI_EVENT_WINKFLASH:
04291 if (p->inalarm) break;
04292 if (p->radio) break;
04293 if (p->oprmode < 0) break;
04294 if (p->oprmode > 1)
04295 {
04296 struct dahdi_params par;
04297
04298 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04299 {
04300 if (!par.rxisoffhook)
04301 {
04302
04303 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04304 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04305 save_conference(p);
04306 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04307 }
04308 }
04309 break;
04310 }
04311
04312 gettimeofday(&p->flashtime, NULL);
04313 switch (mysig) {
04314 case SIG_FXOLS:
04315 case SIG_FXOGS:
04316 case SIG_FXOKS:
04317 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04318 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04319 p->callwaitcas = 0;
04320
04321 if (index != SUB_REAL) {
04322 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04323 goto winkflashdone;
04324 }
04325
04326 if (p->subs[SUB_CALLWAIT].owner) {
04327
04328 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04329 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04330 p->owner = p->subs[SUB_REAL].owner;
04331 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04332 if (p->owner->_state == AST_STATE_RINGING) {
04333 ast_setstate(p->owner, AST_STATE_UP);
04334 p->subs[SUB_REAL].needanswer = 1;
04335 }
04336 p->callwaitingrepeat = 0;
04337 p->cidcwexpire = 0;
04338
04339 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04340 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04341 S_OR(p->mohsuggest, NULL),
04342 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04343 }
04344 p->subs[SUB_CALLWAIT].needhold = 1;
04345 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04346 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04347 S_OR(p->mohsuggest, NULL),
04348 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04349 }
04350 p->subs[SUB_REAL].needunhold = 1;
04351 } else if (!p->subs[SUB_THREEWAY].owner) {
04352 char cid_num[256];
04353 char cid_name[256];
04354
04355 if (!p->threewaycalling) {
04356
04357 p->subs[SUB_REAL].needflash = 1;
04358 goto winkflashdone;
04359 } else if (!check_for_conference(p)) {
04360 if (p->dahditrcallerid && p->owner) {
04361 if (p->owner->cid.cid_num)
04362 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04363 if (p->owner->cid.cid_name)
04364 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04365 }
04366
04367
04368 if (!((ast->pbx) ||
04369 (ast->_state == AST_STATE_UP) ||
04370 (ast->_state == AST_STATE_RING))) {
04371 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04372 goto winkflashdone;
04373 }
04374 if (alloc_sub(p, SUB_THREEWAY)) {
04375 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04376 goto winkflashdone;
04377 }
04378
04379 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04380 if (p->dahditrcallerid) {
04381 if (!p->origcid_num)
04382 p->origcid_num = ast_strdup(p->cid_num);
04383 if (!p->origcid_name)
04384 p->origcid_name = ast_strdup(p->cid_name);
04385 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04386 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04387 }
04388
04389 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04390
04391 dahdi_disable_ec(p);
04392 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04393 if (res)
04394 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04395 p->owner = chan;
04396 pthread_attr_init(&attr);
04397 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04398 if (!chan) {
04399 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04400 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04401 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04402 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04403 dahdi_enable_ec(p);
04404 ast_hangup(chan);
04405 } else {
04406 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04407 int way3bridge = 0, cdr3way = 0;
04408
04409 if (!other) {
04410 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04411 } else
04412 way3bridge = 1;
04413
04414 if (p->subs[SUB_THREEWAY].owner->cdr)
04415 cdr3way = 1;
04416
04417 if (option_verbose > 2)
04418 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04419
04420 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04421 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04422 S_OR(p->mohsuggest, NULL),
04423 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04424 }
04425 p->subs[SUB_THREEWAY].needhold = 1;
04426 }
04427 pthread_attr_destroy(&attr);
04428 }
04429 } else {
04430
04431 if (p->subs[SUB_THREEWAY].inthreeway) {
04432
04433 if (option_debug)
04434 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04435
04436 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04437
04438 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04439 p->owner = p->subs[SUB_REAL].owner;
04440 }
04441
04442 if (option_verbose > 2)
04443 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04444 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04445 p->subs[SUB_REAL].inthreeway = 0;
04446 p->subs[SUB_THREEWAY].inthreeway = 0;
04447 } else {
04448
04449 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
04450 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04451 int otherindex = SUB_THREEWAY;
04452 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04453 int way3bridge = 0, cdr3way = 0;
04454
04455 if (!other) {
04456 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04457 } else
04458 way3bridge = 1;
04459
04460 if (p->subs[SUB_THREEWAY].owner->cdr)
04461 cdr3way = 1;
04462
04463 if (option_verbose > 2)
04464 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);
04465
04466 p->subs[SUB_THREEWAY].inthreeway = 1;
04467 p->subs[SUB_REAL].inthreeway = 1;
04468 if (ast->_state == AST_STATE_UP) {
04469 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04470 otherindex = SUB_REAL;
04471 }
04472 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04473 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04474 p->subs[otherindex].needunhold = 1;
04475 p->owner = p->subs[SUB_REAL].owner;
04476 if (ast->_state == AST_STATE_RINGING) {
04477 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04478 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04479 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04480 }
04481 } else {
04482 if (option_verbose > 2)
04483 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04484 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04485 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04486 p->owner = p->subs[SUB_REAL].owner;
04487 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04488 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04489 p->subs[SUB_REAL].needunhold = 1;
04490 dahdi_enable_ec(p);
04491 }
04492
04493 }
04494 }
04495 winkflashdone:
04496 update_conf(p);
04497 break;
04498 case SIG_EM:
04499 case SIG_EM_E1:
04500 case SIG_EMWINK:
04501 case SIG_FEATD:
04502 case SIG_SF:
04503 case SIG_SFWINK:
04504 case SIG_SF_FEATD:
04505 case SIG_FXSLS:
04506 case SIG_FXSGS:
04507 if (p->dialing)
04508 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04509 else
04510 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04511 break;
04512 case SIG_FEATDMF_TA:
04513 switch (p->whichwink) {
04514 case 0:
04515 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04516 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04517 break;
04518 case 1:
04519 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04520 break;
04521 case 2:
04522 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04523 return NULL;
04524 }
04525 p->whichwink++;
04526
04527 case SIG_FEATDMF:
04528 case SIG_E911:
04529 case SIG_FGC_CAMAMF:
04530 case SIG_FGC_CAMA:
04531 case SIG_FEATB:
04532 case SIG_SF_FEATDMF:
04533 case SIG_SF_FEATB:
04534
04535 if (!ast_strlen_zero(p->dop.dialstr)) {
04536 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04537 if (res < 0) {
04538 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04539 p->dop.dialstr[0] = '\0';
04540 return NULL;
04541 } else
04542 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04543 }
04544 p->dop.dialstr[0] = '\0';
04545 break;
04546 default:
04547 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04548 }
04549 break;
04550 case DAHDI_EVENT_HOOKCOMPLETE:
04551 if (p->inalarm) break;
04552 if ((p->radio || (p->oprmode < 0))) break;
04553 switch (mysig) {
04554 case SIG_FXSLS:
04555 case SIG_FXSGS:
04556 case SIG_FXSKS:
04557 case SIG_EM:
04558 case SIG_EM_E1:
04559 case SIG_EMWINK:
04560 case SIG_FEATD:
04561 case SIG_SF:
04562 case SIG_SFWINK:
04563 case SIG_SF_FEATD:
04564 if (!ast_strlen_zero(p->dop.dialstr)) {
04565 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04566 if (res < 0) {
04567 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04568 p->dop.dialstr[0] = '\0';
04569 return NULL;
04570 } else
04571 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04572 }
04573 p->dop.dialstr[0] = '\0';
04574 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04575 break;
04576 case SIG_FEATDMF:
04577 case SIG_FEATDMF_TA:
04578 case SIG_E911:
04579 case SIG_FGC_CAMA:
04580 case SIG_FGC_CAMAMF:
04581 case SIG_FEATB:
04582 case SIG_SF_FEATDMF:
04583 case SIG_SF_FEATB:
04584 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04585 break;
04586 default:
04587 break;
04588 }
04589 break;
04590 case DAHDI_EVENT_POLARITY:
04591
04592
04593
04594
04595
04596
04597 if (p->polarity == POLARITY_IDLE) {
04598 p->polarity = POLARITY_REV;
04599 if (p->answeronpolarityswitch &&
04600 ((ast->_state == AST_STATE_DIALING) ||
04601 (ast->_state == AST_STATE_RINGING))) {
04602 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04603 ast_setstate(p->owner, AST_STATE_UP);
04604 if (p->hanguponpolarityswitch) {
04605 gettimeofday(&p->polaritydelaytv, NULL);
04606 }
04607 } else
04608 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04609 }
04610
04611
04612 if (p->hanguponpolarityswitch &&
04613 (p->polarityonanswerdelay > 0) &&
04614 (p->polarity == POLARITY_REV) &&
04615 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04616
04617 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) );
04618
04619 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04620 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04621 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04622 p->polarity = POLARITY_IDLE;
04623 } else {
04624 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);
04625 }
04626 } else {
04627 p->polarity = POLARITY_IDLE;
04628 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04629 }
04630
04631 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) );
04632 break;
04633 default:
04634 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04635 }
04636 return &p->subs[index].f;
04637 }
04638
04639 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04640 {
04641 struct dahdi_pvt *p = ast->tech_pvt;
04642 int res;
04643 int usedindex=-1;
04644 int index;
04645 struct ast_frame *f;
04646
04647
04648 index = dahdi_get_index(ast, p, 1);
04649
04650 p->subs[index].f.frametype = AST_FRAME_NULL;
04651 p->subs[index].f.datalen = 0;
04652 p->subs[index].f.samples = 0;
04653 p->subs[index].f.mallocd = 0;
04654 p->subs[index].f.offset = 0;
04655 p->subs[index].f.subclass = 0;
04656 p->subs[index].f.delivery = ast_tv(0,0);
04657 p->subs[index].f.src = "dahdi_exception";
04658 p->subs[index].f.data = NULL;
04659
04660
04661 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04662
04663
04664
04665
04666
04667 if (p->fake_event) {
04668 res = p->fake_event;
04669 p->fake_event = 0;
04670 } else
04671 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04672
04673 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04674 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04675 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04676 p->owner = p->subs[SUB_REAL].owner;
04677 if (p->owner && ast_bridged_channel(p->owner))
04678 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04679 p->subs[SUB_REAL].needunhold = 1;
04680 }
04681 switch (res) {
04682 case DAHDI_EVENT_ONHOOK:
04683 dahdi_disable_ec(p);
04684 if (p->owner) {
04685 if (option_verbose > 2)
04686 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04687 dahdi_ring_phone(p);
04688 p->callwaitingrepeat = 0;
04689 p->cidcwexpire = 0;
04690 } else
04691 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04692 update_conf(p);
04693 break;
04694 case DAHDI_EVENT_RINGOFFHOOK:
04695 dahdi_enable_ec(p);
04696 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04697 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04698 p->subs[SUB_REAL].needanswer = 1;
04699 p->dialing = 0;
04700 }
04701 break;
04702 case DAHDI_EVENT_HOOKCOMPLETE:
04703 case DAHDI_EVENT_RINGERON:
04704 case DAHDI_EVENT_RINGEROFF:
04705
04706 break;
04707 case DAHDI_EVENT_WINKFLASH:
04708 gettimeofday(&p->flashtime, NULL);
04709 if (p->owner) {
04710 if (option_verbose > 2)
04711 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04712 if (p->owner->_state != AST_STATE_UP) {
04713
04714 usedindex = dahdi_get_index(p->owner, p, 0);
04715 if (usedindex > -1) {
04716 p->subs[usedindex].needanswer = 1;
04717 }
04718 ast_setstate(p->owner, AST_STATE_UP);
04719 }
04720 p->callwaitingrepeat = 0;
04721 p->cidcwexpire = 0;
04722 if (ast_bridged_channel(p->owner))
04723 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04724 p->subs[SUB_REAL].needunhold = 1;
04725 } else
04726 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04727 update_conf(p);
04728 break;
04729 default:
04730 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04731 }
04732 f = &p->subs[index].f;
04733 return f;
04734 }
04735 if (!(p->radio || (p->oprmode < 0)) && option_debug)
04736 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04737
04738 if (ast != p->owner) {
04739 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04740 f = &p->subs[index].f;
04741 return f;
04742 }
04743 f = dahdi_handle_event(ast);
04744 return f;
04745 }
04746
04747 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
04748 {
04749 struct dahdi_pvt *p = ast->tech_pvt;
04750 struct ast_frame *f;
04751 ast_mutex_lock(&p->lock);
04752 f = __dahdi_exception(ast);
04753 ast_mutex_unlock(&p->lock);
04754 return f;
04755 }
04756
04757 static struct ast_frame *dahdi_read(struct ast_channel *ast)
04758 {
04759 struct dahdi_pvt *p = ast->tech_pvt;
04760 int res;
04761 int index;
04762 void *readbuf;
04763 struct ast_frame *f;
04764
04765 while (ast_mutex_trylock(&p->lock)) {
04766 DEADLOCK_AVOIDANCE(&ast->lock);
04767 }
04768
04769 index = dahdi_get_index(ast, p, 0);
04770
04771
04772 if (index < 0) {
04773 ast_log(LOG_WARNING, "We dont exist?\n");
04774 ast_mutex_unlock(&p->lock);
04775 return NULL;
04776 }
04777
04778 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04779
04780 p->subs[index].f.frametype = AST_FRAME_NULL;
04781 p->subs[index].f.datalen = 0;
04782 p->subs[index].f.samples = 0;
04783 p->subs[index].f.mallocd = 0;
04784 p->subs[index].f.offset = 0;
04785 p->subs[index].f.subclass = 0;
04786 p->subs[index].f.delivery = ast_tv(0,0);
04787 p->subs[index].f.src = "dahdi_read";
04788 p->subs[index].f.data = NULL;
04789
04790
04791 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04792 {
04793 struct dahdi_params ps;
04794
04795 ps.channo = p->channel;
04796 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
04797 ast_mutex_unlock(&p->lock);
04798 return NULL;
04799 }
04800 p->firstradio = 1;
04801 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04802 if (ps.rxisoffhook)
04803 {
04804 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04805 }
04806 else
04807 {
04808 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04809 }
04810 ast_mutex_unlock(&p->lock);
04811 return &p->subs[index].f;
04812 }
04813 if (p->ringt == 1) {
04814 ast_mutex_unlock(&p->lock);
04815 return NULL;
04816 }
04817 else if (p->ringt > 0)
04818 p->ringt--;
04819
04820 if (p->subs[index].needringing) {
04821
04822 p->subs[index].needringing = 0;
04823 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04824 p->subs[index].f.subclass = AST_CONTROL_RINGING;
04825 ast_setstate(ast, AST_STATE_RINGING);
04826 ast_mutex_unlock(&p->lock);
04827 return &p->subs[index].f;
04828 }
04829
04830 if (p->subs[index].needbusy) {
04831
04832 p->subs[index].needbusy = 0;
04833 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04834 p->subs[index].f.subclass = AST_CONTROL_BUSY;
04835 ast_mutex_unlock(&p->lock);
04836 return &p->subs[index].f;
04837 }
04838
04839 if (p->subs[index].needcongestion) {
04840
04841 p->subs[index].needcongestion = 0;
04842 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04843 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04844 ast_mutex_unlock(&p->lock);
04845 return &p->subs[index].f;
04846 }
04847
04848 if (p->subs[index].needcallerid) {
04849 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04850 S_OR(p->lastcid_name, NULL),
04851 S_OR(p->lastcid_num, NULL)
04852 );
04853 p->subs[index].needcallerid = 0;
04854 }
04855
04856 if (p->subs[index].needanswer) {
04857
04858 p->subs[index].needanswer = 0;
04859 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04860 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04861 ast_mutex_unlock(&p->lock);
04862 return &p->subs[index].f;
04863 }
04864
04865 if (p->subs[index].needflash) {
04866
04867 p->subs[index].needflash = 0;
04868 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04869 p->subs[index].f.subclass = AST_CONTROL_FLASH;
04870 ast_mutex_unlock(&p->lock);
04871 return &p->subs[index].f;
04872 }
04873
04874 if (p->subs[index].needhold) {
04875
04876 p->subs[index].needhold = 0;
04877 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04878 p->subs[index].f.subclass = AST_CONTROL_HOLD;
04879 ast_mutex_unlock(&p->lock);
04880 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04881 return &p->subs[index].f;
04882 }
04883
04884 if (p->subs[index].needunhold) {
04885
04886 p->subs[index].needunhold = 0;
04887 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04888 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04889 ast_mutex_unlock(&p->lock);
04890 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04891 return &p->subs[index].f;
04892 }
04893
04894 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04895 if (!p->subs[index].linear) {
04896 p->subs[index].linear = 1;
04897 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04898 if (res)
04899 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04900 }
04901 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04902 (ast->rawreadformat == AST_FORMAT_ALAW)) {
04903 if (p->subs[index].linear) {
04904 p->subs[index].linear = 0;
04905 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04906 if (res)
04907 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04908 }
04909 } else {
04910 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04911 ast_mutex_unlock(&p->lock);
04912 return NULL;
04913 }
04914 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04915 CHECK_BLOCKING(ast);
04916 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04917 ast_clear_flag(ast, AST_FLAG_BLOCKING);
04918
04919 if (res < 0) {
04920 f = NULL;
04921 if (res == -1) {
04922 if (errno == EAGAIN) {
04923
04924 ast_mutex_unlock(&p->lock);
04925 return &p->subs[index].f;
04926 } else if (errno == ELAST) {
04927 f = __dahdi_exception(ast);
04928 } else
04929 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
04930 }
04931 ast_mutex_unlock(&p->lock);
04932 return f;
04933 }
04934 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04935 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04936 f = __dahdi_exception(ast);
04937 ast_mutex_unlock(&p->lock);
04938 return f;
04939 }
04940 if (p->tdd) {
04941 int c;
04942
04943 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04944 if (c < 0) {
04945 ast_log(LOG_DEBUG,"tdd_feed failed\n");
04946 ast_mutex_unlock(&p->lock);
04947 return NULL;
04948 }
04949 if (c) {
04950 p->subs[index].f.subclass = 0;
04951 p->subs[index].f.frametype = AST_FRAME_TEXT;
04952 p->subs[index].f.mallocd = 0;
04953 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04954 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04955 p->subs[index].f.datalen = 1;
04956 *((char *) p->subs[index].f.data) = c;
04957 ast_mutex_unlock(&p->lock);
04958 return &p->subs[index].f;
04959 }
04960 }
04961
04962 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
04963 p->callwaitingrepeat--;
04964 }
04965 if (p->cidcwexpire)
04966 p->cidcwexpire--;
04967
04968 if (p->callwaitingrepeat == 1) {
04969 p->callwaitrings++;
04970 dahdi_callwait(ast);
04971 }
04972
04973 if (p->cidcwexpire == 1) {
04974 if (option_verbose > 2)
04975 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04976 restore_conference(p);
04977 }
04978 if (p->subs[index].linear) {
04979 p->subs[index].f.datalen = READ_SIZE * 2;
04980 } else
04981 p->subs[index].f.datalen = READ_SIZE;
04982
04983
04984 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04985 send_callerid(p);
04986 }
04987
04988 p->subs[index].f.frametype = AST_FRAME_VOICE;
04989 p->subs[index].f.subclass = ast->rawreadformat;
04990 p->subs[index].f.samples = READ_SIZE;
04991 p->subs[index].f.mallocd = 0;
04992 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04993 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04994 #if 0
04995 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04996 #endif
04997 if (p->dialing ||
04998 (index && (ast->_state != AST_STATE_UP)) ||
04999 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05000 ) {
05001
05002
05003 p->subs[index].f.frametype = AST_FRAME_NULL;
05004 p->subs[index].f.subclass = 0;
05005 p->subs[index].f.samples = 0;
05006 p->subs[index].f.mallocd = 0;
05007 p->subs[index].f.offset = 0;
05008 p->subs[index].f.data = NULL;
05009 p->subs[index].f.datalen= 0;
05010 }
05011 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05012
05013 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05014 if (f) {
05015 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05016 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05017
05018
05019 f = NULL;
05020 }
05021 } else if (f->frametype == AST_FRAME_DTMF) {
05022 #ifdef HAVE_PRI
05023 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05024
05025 f->frametype = AST_FRAME_NULL;
05026 f->subclass = 0;
05027 }
05028 #endif
05029
05030 p->pulsedial = 0;
05031 }
05032 }
05033 } else
05034 f = &p->subs[index].f;
05035
05036 if (f && (f->frametype == AST_FRAME_DTMF))
05037 dahdi_handle_dtmfup(ast, index, &f);
05038
05039
05040 if (p->fake_event)
05041 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05042
05043 ast_mutex_unlock(&p->lock);
05044 return f;
05045 }
05046
05047 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05048 {
05049 int sent=0;
05050 int size;
05051 int res;
05052 int fd;
05053 fd = p->subs[index].dfd;
05054 while (len) {
05055 size = len;
05056 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05057 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05058 res = write(fd, buf, size);
05059 if (res != size) {
05060 if (option_debug)
05061 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05062 return sent;
05063 }
05064 len -= size;
05065 buf += size;
05066 }
05067 return sent;
05068 }
05069
05070 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05071 {
05072 struct dahdi_pvt *p = ast->tech_pvt;
05073 int res;
05074 int index;
05075 index = dahdi_get_index(ast, p, 0);
05076 if (index < 0) {
05077 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05078 return -1;
05079 }
05080
05081 #if 0
05082 #ifdef HAVE_PRI
05083 ast_mutex_lock(&p->lock);
05084 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05085 if (p->pri->pri) {
05086 if (!pri_grab(p, p->pri)) {
05087 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05088 pri_rel(p->pri);
05089 } else
05090 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05091 }
05092 p->proceeding=1;
05093 }
05094 ast_mutex_unlock(&p->lock);
05095 #endif
05096 #endif
05097
05098 if (frame->frametype != AST_FRAME_VOICE) {
05099 if (frame->frametype != AST_FRAME_IMAGE)
05100 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05101 return 0;
05102 }
05103 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
05104 (frame->subclass != AST_FORMAT_ULAW) &&
05105 (frame->subclass != AST_FORMAT_ALAW)) {
05106 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05107 return -1;
05108 }
05109 if (p->dialing) {
05110 if (option_debug)
05111 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05112 return 0;
05113 }
05114 if (!p->owner) {
05115 if (option_debug)
05116 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05117 return 0;
05118 }
05119 if (p->cidspill) {
05120 if (option_debug)
05121 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05122 return 0;
05123 }
05124
05125 if (!frame->data || !frame->datalen)
05126 return 0;
05127
05128 if (frame->subclass == AST_FORMAT_SLINEAR) {
05129 if (!p->subs[index].linear) {
05130 p->subs[index].linear = 1;
05131 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05132 if (res)
05133 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05134 }
05135 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05136 } else {
05137
05138 if (p->subs[index].linear) {
05139 p->subs[index].linear = 0;
05140 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05141 if (res)
05142 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05143 }
05144 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05145 }
05146 if (res < 0) {
05147 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05148 return -1;
05149 }
05150 return 0;
05151 }
05152
05153 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05154 {
05155 struct dahdi_pvt *p = chan->tech_pvt;
05156 int res=-1;
05157 int index;
05158 int func = DAHDI_FLASH;
05159 ast_mutex_lock(&p->lock);
05160 index = dahdi_get_index(chan, p, 0);
05161 if (option_debug)
05162 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05163 if (index == SUB_REAL) {
05164 switch (condition) {
05165 case AST_CONTROL_BUSY:
05166 #ifdef HAVE_PRI
05167 if (p->priindication_oob && p->sig == SIG_PRI) {
05168 chan->hangupcause = AST_CAUSE_USER_BUSY;
05169 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05170 res = 0;
05171 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05172 if (p->pri->pri) {
05173 if (!pri_grab(p, p->pri)) {
05174 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05175 pri_rel(p->pri);
05176 }
05177 else
05178 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05179 }
05180 p->progress = 1;
05181 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05182 } else
05183 #endif
05184 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05185 break;
05186 case AST_CONTROL_RINGING:
05187 #ifdef HAVE_PRI
05188 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05189 if (p->pri->pri) {
05190 if (!pri_grab(p, p->pri)) {
05191 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05192 pri_rel(p->pri);
05193 }
05194 else
05195 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05196 }
05197 p->alerting = 1;
05198 }
05199 #endif
05200 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05201 if (chan->_state != AST_STATE_UP) {
05202 if ((chan->_state != AST_STATE_RING) ||
05203 ((p->sig != SIG_FXSKS) &&
05204 (p->sig != SIG_FXSLS) &&
05205 (p->sig != SIG_FXSGS)))
05206 ast_setstate(chan, AST_STATE_RINGING);
05207 }
05208 break;
05209 case AST_CONTROL_PROCEEDING:
05210 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05211 #ifdef HAVE_PRI
05212 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05213 if (p->pri->pri) {
05214 if (!pri_grab(p, p->pri)) {
05215 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05216 pri_rel(p->pri);
05217 }
05218 else
05219 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05220 }
05221 p->proceeding = 1;
05222 }
05223 #endif
05224
05225 res = 0;
05226 break;
05227 case AST_CONTROL_PROGRESS:
05228 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05229 #ifdef HAVE_PRI
05230 p->digital = 0;
05231 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05232 if (p->pri->pri) {
05233 if (!pri_grab(p, p->pri)) {
05234 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05235 pri_rel(p->pri);
05236 }
05237 else
05238 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05239 }
05240 p->progress = 1;
05241 }
05242 #endif
05243
05244 res = 0;
05245 break;
05246 case AST_CONTROL_CONGESTION:
05247 chan->hangupcause = AST_CAUSE_CONGESTION;
05248 #ifdef HAVE_PRI
05249 if (p->priindication_oob && p->sig == SIG_PRI) {
05250 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05251 chan->_softhangup |= AST_SOFTHANGUP_DEV;
05252 res = 0;
05253 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05254 if (p->pri) {
05255 if (!pri_grab(p, p->pri)) {
05256 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05257 pri_rel(p->pri);
05258 } else
05259 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05260 }
05261 p->progress = 1;
05262 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05263 } else
05264 #endif
05265 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05266 break;
05267 case AST_CONTROL_HOLD:
05268 #ifdef HAVE_PRI
05269 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05270 if (!pri_grab(p, p->pri)) {
05271 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05272 pri_rel(p->pri);
05273 } else
05274 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05275 } else
05276 #endif
05277 ast_moh_start(chan, data, p->mohinterpret);
05278 break;
05279 case AST_CONTROL_UNHOLD:
05280 #ifdef HAVE_PRI
05281 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05282 if (!pri_grab(p, p->pri)) {
05283 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05284 pri_rel(p->pri);
05285 } else
05286 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05287 } else
05288 #endif
05289 ast_moh_stop(chan);
05290 break;
05291 case AST_CONTROL_RADIO_KEY:
05292 if (p->radio)
05293 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05294 res = 0;
05295 break;
05296 case AST_CONTROL_RADIO_UNKEY:
05297 if (p->radio)
05298 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05299 res = 0;
05300 break;
05301 case AST_CONTROL_FLASH:
05302
05303 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05304
05305 p->dop.dialstr[0] = '\0';
05306 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05307 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
05308 chan->name, strerror(errno));
05309 } else
05310 res = 0;
05311 } else
05312 res = 0;
05313 break;
05314 case AST_CONTROL_SRCUPDATE:
05315 res = 0;
05316 break;
05317 case -1:
05318 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05319 break;
05320 }
05321 } else
05322 res = 0;
05323 ast_mutex_unlock(&p->lock);
05324 return res;
05325 }
05326
05327 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05328 {
05329 struct ast_channel *tmp;
05330 int deflaw;
05331 int res;
05332 int x,y;
05333 int features;
05334 char *b2 = NULL;
05335 struct dahdi_params ps;
05336 char chanprefix[*dahdi_chan_name_len + 4];
05337
05338 if (i->subs[index].owner) {
05339 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05340 return NULL;
05341 }
05342 y = 1;
05343 do {
05344 if (b2)
05345 free(b2);
05346 #ifdef HAVE_PRI
05347 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05348 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05349 else
05350 #endif
05351 if (i->channel == CHAN_PSEUDO)
05352 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05353 else
05354 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05355 for (x = 0; x < 3; x++) {
05356 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05357 break;
05358 }
05359 y++;
05360 } while (x < 3);
05361 strcpy(chanprefix, dahdi_chan_name);
05362 strcat(chanprefix, "/%s");
05363 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05364 if (b2)
05365 free(b2);
05366 if (!tmp)
05367 return NULL;
05368 tmp->tech = chan_tech;
05369 ps.channo = i->channel;
05370 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05371 if (res) {
05372 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05373 ps.curlaw = DAHDI_LAW_MULAW;
05374 }
05375 if (ps.curlaw == DAHDI_LAW_ALAW)
05376 deflaw = AST_FORMAT_ALAW;
05377 else
05378 deflaw = AST_FORMAT_ULAW;
05379 if (law) {
05380 if (law == DAHDI_LAW_ALAW)
05381 deflaw = AST_FORMAT_ALAW;
05382 else
05383 deflaw = AST_FORMAT_ULAW;
05384 }
05385 tmp->fds[0] = i->subs[index].dfd;
05386 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05387
05388 tmp->rawreadformat = deflaw;
05389 tmp->readformat = deflaw;
05390 tmp->rawwriteformat = deflaw;
05391 tmp->writeformat = deflaw;
05392 i->subs[index].linear = 0;
05393 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05394 features = 0;
05395 if (index == SUB_REAL) {
05396 if (i->busydetect && CANBUSYDETECT(i))
05397 features |= DSP_FEATURE_BUSY_DETECT;
05398 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05399 features |= DSP_FEATURE_CALL_PROGRESS;
05400 if ((!i->outgoing && (i->callprogress & 4)) ||
05401 (i->outgoing && (i->callprogress & 2))) {
05402 features |= DSP_FEATURE_FAX_DETECT;
05403 }
05404 #ifdef DAHDI_TONEDETECT
05405 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05406 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05407 #endif
05408 i->hardwaredtmf = 0;
05409 features |= DSP_FEATURE_DTMF_DETECT;
05410 #ifdef DAHDI_TONEDETECT
05411 } else if (NEED_MFDETECT(i)) {
05412 i->hardwaredtmf = 1;
05413 features |= DSP_FEATURE_DTMF_DETECT;
05414 }
05415 #endif
05416 }
05417 if (features) {
05418 if (i->dsp) {
05419 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05420 } else {
05421 if (i->channel != CHAN_PSEUDO)
05422 i->dsp = ast_dsp_new();
05423 else
05424 i->dsp = NULL;
05425 if (i->dsp) {
05426 i->dsp_features = features;
05427 #ifdef HAVE_PRI
05428
05429 if (i->outgoing && (i->sig == SIG_PRI)) {
05430
05431
05432 i->dsp_features = features & ~DSP_PROGRESS_TALK;
05433 features = 0;
05434 }
05435 #endif
05436 ast_dsp_set_features(i->dsp, features);
05437 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05438 if (!ast_strlen_zero(progzone))
05439 ast_dsp_set_call_progress_zone(i->dsp, progzone);
05440 if (i->busydetect && CANBUSYDETECT(i)) {
05441 if(i->silencethreshold > 0)
05442 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05443 ast_dsp_set_busy_count(i->dsp, i->busycount);
05444 if(i->busytonelength > 0)
05445 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05446 if((i->busytonelength == i->busyquietlength) && i->busycompare)
05447 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05448 }
05449 }
05450 }
05451 }
05452
05453 if (state == AST_STATE_RING)
05454 tmp->rings = 1;
05455 tmp->tech_pvt = i;
05456 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05457
05458 tmp->callgroup = i->callgroup;
05459 tmp->pickupgroup = i->pickupgroup;
05460 }
05461 if (!ast_strlen_zero(i->language))
05462 ast_string_field_set(tmp, language, i->language);
05463 if (!i->owner)
05464 i->owner = tmp;
05465 if (!ast_strlen_zero(i->accountcode))
05466 ast_string_field_set(tmp, accountcode, i->accountcode);
05467 if (i->amaflags)
05468 tmp->amaflags = i->amaflags;
05469 i->subs[index].owner = tmp;
05470 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05471 ast_string_field_set(tmp, call_forward, i->call_forward);
05472
05473 if (!i->adsi)
05474 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05475 if (!ast_strlen_zero(i->exten))
05476 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05477 if (!ast_strlen_zero(i->rdnis))
05478 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05479 if (!ast_strlen_zero(i->dnid))
05480 tmp->cid.cid_dnid = ast_strdup(i->dnid);
05481
05482
05483
05484 #ifdef PRI_ANI
05485 if (!ast_strlen_zero(i->cid_ani))
05486 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05487 else
05488 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05489 #else
05490 tmp->cid.cid_ani = ast_strdup(i->cid_num);
05491 #endif
05492 tmp->cid.cid_pres = i->callingpres;
05493 tmp->cid.cid_ton = i->cid_ton;
05494 #ifdef HAVE_PRI
05495 tmp->transfercapability = transfercapability;
05496 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05497 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05498 i->digital = 1;
05499
05500 i->isidlecall = 0;
05501 i->alreadyhungup = 0;
05502 #endif
05503
05504 i->fake_event = 0;
05505
05506 dahdi_confmute(i, 0);
05507
05508 ast_jb_configure(tmp, &global_jbconf);
05509 if (startpbx) {
05510 if (ast_pbx_start(tmp)) {
05511 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05512 ast_hangup(tmp);
05513 i->owner = NULL;
05514 return NULL;
05515 }
05516 }
05517
05518 ast_module_ref(ast_module_info->self);
05519
05520 return tmp;
05521 }
05522
05523
05524 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05525 {
05526 char c;
05527
05528 *str = 0;
05529 for (;;)
05530 {
05531
05532 c = ast_waitfordigit(chan, ms);
05533
05534 if (c < 1)
05535 return c;
05536 *str++ = c;
05537 *str = 0;
05538 if (strchr(term, c))
05539 return 1;
05540 }
05541 }
05542
05543 static int dahdi_wink(struct dahdi_pvt *p, int index)
05544 {
05545 int j;
05546 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05547 for (;;)
05548 {
05549
05550 j = DAHDI_IOMUX_SIGEVENT;
05551
05552 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05553
05554 if (j & DAHDI_IOMUX_SIGEVENT) break;
05555 }
05556
05557 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05558 return 0;
05559 }
05560
05561 static void *ss_thread(void *data)
05562 {
05563 struct ast_channel *chan = data;
05564 struct dahdi_pvt *p = chan->tech_pvt;
05565 char exten[AST_MAX_EXTENSION] = "";
05566 char exten2[AST_MAX_EXTENSION] = "";
05567 unsigned char buf[256];
05568 char dtmfcid[300];
05569 char dtmfbuf[300];
05570 struct callerid_state *cs = NULL;
05571 char *name = NULL, *number = NULL;
05572 int distMatches;
05573 int curRingData[3];
05574 int receivedRingT;
05575 int counter1;
05576 int counter;
05577 int samples = 0;
05578 struct ast_smdi_md_message *smdi_msg = NULL;
05579 int flags;
05580 int i;
05581 int timeout;
05582 int getforward = 0;
05583 char *s1, *s2;
05584 int len = 0;
05585 int res;
05586 int index;
05587
05588 ast_mutex_lock(&ss_thread_lock);
05589 ss_thread_count++;
05590 ast_mutex_unlock(&ss_thread_lock);
05591
05592
05593
05594 if (!p) {
05595 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05596 ast_hangup(chan);
05597 goto quit;
05598 }
05599 if (option_verbose > 2)
05600 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05601 index = dahdi_get_index(chan, p, 1);
05602 if (index < 0) {
05603 ast_log(LOG_WARNING, "Huh?\n");
05604 ast_hangup(chan);
05605 goto quit;
05606 }
05607 if (p->dsp)
05608 ast_dsp_digitreset(p->dsp);
05609 switch (p->sig) {
05610 #ifdef HAVE_PRI
05611 case SIG_PRI:
05612
05613 ast_copy_string(exten, p->exten, sizeof(exten));
05614 len = strlen(exten);
05615 res = 0;
05616 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05617 if (len && !ast_ignore_pattern(chan->context, exten))
05618 tone_zone_play_tone(p->subs[index].dfd, -1);
05619 else
05620 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05621 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05622 timeout = matchdigittimeout;
05623 else
05624 timeout = gendigittimeout;
05625 res = ast_waitfordigit(chan, timeout);
05626 if (res < 0) {
05627 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05628 ast_hangup(chan);
05629 goto quit;
05630 } else if (res) {
05631 exten[len++] = res;
05632 exten[len] = '\0';
05633 } else
05634 break;
05635 }
05636
05637 if (ast_strlen_zero(exten)) {
05638 if (option_verbose > 2)
05639 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05640 exten[0] = 's';
05641 exten[1] = '\0';
05642 }
05643 tone_zone_play_tone(p->subs[index].dfd, -1);
05644 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05645
05646 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05647 if (p->dsp) ast_dsp_digitreset(p->dsp);
05648 dahdi_enable_ec(p);
05649 ast_setstate(chan, AST_STATE_RING);
05650 res = ast_pbx_run(chan);
05651 if (res) {
05652 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05653 }
05654 } else {
05655 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05656 chan->hangupcause = AST_CAUSE_UNALLOCATED;
05657 ast_hangup(chan);
05658 p->exten[0] = '\0';
05659
05660 p->call = NULL;
05661 }
05662 goto quit;
05663 break;
05664 #endif
05665 case SIG_FEATD:
05666 case SIG_FEATDMF:
05667 case SIG_FEATDMF_TA:
05668 case SIG_E911:
05669 case SIG_FGC_CAMAMF:
05670 case SIG_FEATB:
05671 case SIG_EMWINK:
05672 case SIG_SF_FEATD:
05673 case SIG_SF_FEATDMF:
05674 case SIG_SF_FEATB:
05675 case SIG_SFWINK:
05676 if (dahdi_wink(p, index))
05677 goto quit;
05678
05679 case SIG_EM:
05680 case SIG_EM_E1:
05681 case SIG_SF:
05682 case SIG_FGC_CAMA:
05683 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05684 if (p->dsp)
05685 ast_dsp_digitreset(p->dsp);
05686
05687 if (p->dsp) {
05688 if (NEED_MFDETECT(p))
05689 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05690 else
05691 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05692 }
05693 memset(dtmfbuf, 0, sizeof(dtmfbuf));
05694
05695 if (!p->immediate)
05696
05697 res = ast_waitfordigit(chan, 5000);
05698 else
05699 res = 0;
05700 if (res > 0) {
05701
05702 dtmfbuf[0] = res;
05703 switch (p->sig) {
05704 case SIG_FEATD:
05705 case SIG_SF_FEATD:
05706 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05707 if (res > 0)
05708 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05709 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05710 break;
05711 case SIG_FEATDMF_TA:
05712 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05713 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05714 if (dahdi_wink(p, index)) goto quit;
05715 dtmfbuf[0] = 0;
05716
05717 res = ast_waitfordigit(chan, 5000);
05718 if (res <= 0) break;
05719 dtmfbuf[0] = res;
05720
05721 case SIG_FEATDMF:
05722 case SIG_E911:
05723 case SIG_FGC_CAMAMF:
05724 case SIG_SF_FEATDMF:
05725 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05726
05727 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05728 {
05729 if (dahdi_wink(p, index)) goto quit;
05730 dtmfbuf[0] = 0;
05731
05732 res = ast_waitfordigit(chan, 5000);
05733 if (res <= 0) break;
05734 dtmfbuf[0] = res;
05735 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05736 }
05737 if (res > 0) {
05738
05739 if (p->sig == SIG_E911)
05740 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05741 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05742 }
05743 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05744 break;
05745 case SIG_FEATB:
05746 case SIG_SF_FEATB:
05747 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05748 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05749 break;
05750 case SIG_EMWINK:
05751
05752
05753
05754
05755 if (res == '*') {
05756 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05757 if (res > 0)
05758 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05759 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05760 break;
05761 }
05762 default:
05763
05764 len = 1;
05765 dtmfbuf[len] = '\0';
05766 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05767 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05768 timeout = matchdigittimeout;
05769 } else {
05770 timeout = gendigittimeout;
05771 }
05772 res = ast_waitfordigit(chan, timeout);
05773 if (res < 0) {
05774 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05775 ast_hangup(chan);
05776 goto quit;
05777 } else if (res) {
05778 dtmfbuf[len++] = res;
05779 dtmfbuf[len] = '\0';
05780 } else {
05781 break;
05782 }
05783 }
05784 break;
05785 }
05786 }
05787 if (res == -1) {
05788 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05789 ast_hangup(chan);
05790 goto quit;
05791 } else if (res < 0) {
05792 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05793 ast_hangup(chan);
05794 goto quit;
05795 }
05796
05797 if (p->sig == SIG_FGC_CAMA) {
05798 char anibuf[100];
05799
05800 if (ast_safe_sleep(chan,1000) == -1) {
05801 ast_hangup(chan);
05802 goto quit;
05803 }
05804 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05805 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05806 res = my_getsigstr(chan, anibuf, "#", 10000);
05807 if ((res > 0) && (strlen(anibuf) > 2)) {
05808 if (anibuf[strlen(anibuf) - 1] == '#')
05809 anibuf[strlen(anibuf) - 1] = 0;
05810 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05811 }
05812 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05813 }
05814
05815 ast_copy_string(exten, dtmfbuf, sizeof(exten));
05816 if (ast_strlen_zero(exten))
05817 ast_copy_string(exten, "s", sizeof(exten));
05818 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05819
05820 if (exten[0] == '*') {
05821 char *stringp=NULL;
05822 ast_copy_string(exten2, exten, sizeof(exten2));
05823
05824 stringp=exten2 +1;
05825 s1 = strsep(&stringp, "*");
05826 s2 = strsep(&stringp, "*");
05827 if (s2) {
05828 if (!ast_strlen_zero(p->cid_num))
05829 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05830 else
05831 ast_set_callerid(chan, s1, NULL, s1);
05832 ast_copy_string(exten, s2, sizeof(exten));
05833 } else
05834 ast_copy_string(exten, s1, sizeof(exten));
05835 } else if (p->sig == SIG_FEATD)
05836 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
05837 }
05838 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05839 if (exten[0] == '*') {
05840 char *stringp=NULL;
05841 ast_copy_string(exten2, exten, sizeof(exten2));
05842
05843 stringp=exten2 +1;
05844 s1 = strsep(&stringp, "#");
05845 s2 = strsep(&stringp, "#");
05846 if (s2) {
05847 if (!ast_strlen_zero(p->cid_num))
05848 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05849 else
05850 if (*(s1 + 2))
05851 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05852 ast_copy_string(exten, s2 + 1, sizeof(exten));
05853 } else
05854 ast_copy_string(exten, s1 + 2, sizeof(exten));
05855 } else
05856 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
05857 }
05858 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05859 if (exten[0] == '*') {
05860 char *stringp=NULL;
05861 ast_copy_string(exten2, exten, sizeof(exten2));
05862
05863 stringp=exten2 +1;
05864 s1 = strsep(&stringp, "#");
05865 s2 = strsep(&stringp, "#");
05866 if (s2 && (*(s2 + 1) == '0')) {
05867 if (*(s2 + 2))
05868 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05869 }
05870 if (s1) ast_copy_string(exten, s1, sizeof(exten));
05871 else ast_copy_string(exten, "911", sizeof(exten));
05872 } else
05873 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
05874 }
05875 if (p->sig == SIG_FEATB) {
05876 if (exten[0] == '*') {
05877 char *stringp=NULL;
05878 ast_copy_string(exten2, exten, sizeof(exten2));
05879
05880 stringp=exten2 +1;
05881 s1 = strsep(&stringp, "#");
05882 ast_copy_string(exten, exten2 + 1, sizeof(exten));
05883 } else
05884 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
05885 }
05886 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05887 dahdi_wink(p, index);
05888
05889
05890
05891 if (ast_safe_sleep(chan,100)) goto quit;
05892 }
05893 dahdi_enable_ec(p);
05894 if (NEED_MFDETECT(p)) {
05895 if (p->dsp) {
05896 if (!p->hardwaredtmf)
05897 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05898 else {
05899 ast_dsp_free(p->dsp);
05900 p->dsp = NULL;
05901 }
05902 }
05903 }
05904
05905 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05906 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05907 if (p->dsp) ast_dsp_digitreset(p->dsp);
05908 res = ast_pbx_run(chan);
05909 if (res) {
05910 ast_log(LOG_WARNING, "PBX exited non-zero\n");
05911 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05912 }
05913 goto quit;
05914 } else {
05915 if (option_verbose > 2)
05916 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05917 sleep(2);
05918 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
05919 if (res < 0)
05920 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05921 else
05922 sleep(1);
05923 res = ast_streamfile(chan, "ss-noservice", chan->language);
05924 if (res >= 0)
05925 ast_waitstream(chan, "");
05926 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05927 ast_hangup(chan);
05928 goto quit;
05929 }
05930 break;
05931 case SIG_FXOLS:
05932 case SIG_FXOGS:
05933 case SIG_FXOKS:
05934
05935 timeout = firstdigittimeout;
05936
05937
05938 if (p->subs[SUB_THREEWAY].owner)
05939 timeout = 999999;
05940 while (len < AST_MAX_EXTENSION-1) {
05941
05942
05943 if (p->immediate)
05944 res = 's';
05945 else
05946 res = ast_waitfordigit(chan, timeout);
05947 timeout = 0;
05948 if (res < 0) {
05949 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05950 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05951 ast_hangup(chan);
05952 goto quit;
05953 } else if (res) {
05954 exten[len++]=res;
05955 exten[len] = '\0';
05956 }
05957 if (!ast_ignore_pattern(chan->context, exten))
05958 tone_zone_play_tone(p->subs[index].dfd, -1);
05959 else
05960 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05961 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05962 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05963 if (getforward) {
05964
05965 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
05966 if (option_verbose > 2)
05967 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05968 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
05969 if (res)
05970 break;
05971 usleep(500000);
05972 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05973 sleep(1);
05974 memset(exten, 0, sizeof(exten));
05975 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05976 len = 0;
05977 getforward = 0;
05978 } else {
05979 res = tone_zone_play_tone(p->subs[index].dfd, -1);
05980 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05981 if (!ast_strlen_zero(p->cid_num)) {
05982 if (!p->hidecallerid)
05983 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05984 else
05985 ast_set_callerid(chan, NULL, NULL, p->cid_num);
05986 }
05987 if (!ast_strlen_zero(p->cid_name)) {
05988 if (!p->hidecallerid)
05989 ast_set_callerid(chan, NULL, p->cid_name, NULL);
05990 }
05991 ast_setstate(chan, AST_STATE_RING);
05992 dahdi_enable_ec(p);
05993 res = ast_pbx_run(chan);
05994 if (res) {
05995 ast_log(LOG_WARNING, "PBX exited non-zero\n");
05996 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05997 }
05998 goto quit;
05999 }
06000 } else {
06001
06002
06003 timeout = matchdigittimeout;
06004 }
06005 } else if (res == 0) {
06006 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06007 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06008 dahdi_wait_event(p->subs[index].dfd);
06009 ast_hangup(chan);
06010 goto quit;
06011 } else if (p->callwaiting && !strcmp(exten, "*70")) {
06012 if (option_verbose > 2)
06013 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06014
06015 p->callwaiting = 0;
06016 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06017 if (res) {
06018 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06019 chan->name, strerror(errno));
06020 }
06021 len = 0;
06022 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06023 memset(exten, 0, sizeof(exten));
06024 timeout = firstdigittimeout;
06025
06026 } else if (!strcmp(exten,ast_pickup_ext())) {
06027
06028
06029
06030
06031 if (index == SUB_REAL) {
06032
06033 if (p->subs[SUB_THREEWAY].owner) {
06034
06035
06036 alloc_sub(p, SUB_CALLWAIT);
06037 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06038 unalloc_sub(p, SUB_THREEWAY);
06039 }
06040 dahdi_enable_ec(p);
06041 if (ast_pickup_call(chan)) {
06042 ast_log(LOG_DEBUG, "No call pickup possible...\n");
06043 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06044 dahdi_wait_event(p->subs[index].dfd);
06045 }
06046 ast_hangup(chan);
06047 goto quit;
06048 } else {
06049 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
06050 ast_hangup(chan);
06051 goto quit;
06052 }
06053
06054 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06055 if (option_verbose > 2)
06056 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06057
06058 p->hidecallerid = 1;
06059 if (chan->cid.cid_num)
06060 free(chan->cid.cid_num);
06061 chan->cid.cid_num = NULL;
06062 if (chan->cid.cid_name)
06063 free(chan->cid.cid_name);
06064 chan->cid.cid_name = NULL;
06065 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06066 if (res) {
06067 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06068 chan->name, strerror(errno));
06069 }
06070 len = 0;
06071 memset(exten, 0, sizeof(exten));
06072 timeout = firstdigittimeout;
06073 } else if (p->callreturn && !strcmp(exten, "*69")) {
06074 res = 0;
06075 if (!ast_strlen_zero(p->lastcid_num)) {
06076 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06077 }
06078 if (!res)
06079 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06080 break;
06081 } else if (!strcmp(exten, "*78")) {
06082
06083 if (option_verbose > 2)
06084 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06085 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06086 "Channel: %s/%d\r\n"
06087 "Status: enabled\r\n", dahdi_chan_name, p->channel);
06088 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06089 p->dnd = 1;
06090 getforward = 0;
06091 memset(exten, 0, sizeof(exten));
06092 len = 0;
06093 } else if (!strcmp(exten, "*79")) {
06094
06095 if (option_verbose > 2)
06096 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06097 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06098 "Channel: %s/%d\r\n"
06099 "Status: disabled\r\n", dahdi_chan_name, p->channel);
06100 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06101 p->dnd = 0;
06102 getforward = 0;
06103 memset(exten, 0, sizeof(exten));
06104 len = 0;
06105 } else if (p->cancallforward && !strcmp(exten, "*72")) {
06106 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06107 getforward = 1;
06108 memset(exten, 0, sizeof(exten));
06109 len = 0;
06110 } else if (p->cancallforward && !strcmp(exten, "*73")) {
06111 if (option_verbose > 2)
06112 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06113 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06114 memset(p->call_forward, 0, sizeof(p->call_forward));
06115 getforward = 0;
06116 memset(exten, 0, sizeof(exten));
06117 len = 0;
06118 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
06119 p->subs[SUB_THREEWAY].owner &&
06120 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06121
06122
06123 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06124 if (option_verbose > 2)
06125 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06126 break;
06127 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06128 if (option_verbose > 2)
06129 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06130 res = ast_db_put("blacklist", p->lastcid_num, "1");
06131 if (!res) {
06132 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06133 memset(exten, 0, sizeof(exten));
06134 len = 0;
06135 }
06136 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06137 if (option_verbose > 2)
06138 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06139
06140 p->hidecallerid = 0;
06141 if (chan->cid.cid_num)
06142 free(chan->cid.cid_num);
06143 chan->cid.cid_num = NULL;
06144 if (chan->cid.cid_name)
06145 free(chan->cid.cid_name);
06146 chan->cid.cid_name = NULL;
06147 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06148 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06149 if (res) {
06150 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
06151 chan->name, strerror(errno));
06152 }
06153 len = 0;
06154 memset(exten, 0, sizeof(exten));
06155 timeout = firstdigittimeout;
06156 } else if (!strcmp(exten, "*0")) {
06157 struct ast_channel *nbridge =
06158 p->subs[SUB_THREEWAY].owner;
06159 struct dahdi_pvt *pbridge = NULL;
06160
06161 if (nbridge && ast_bridged_channel(nbridge))
06162 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06163 if (nbridge && pbridge &&
06164 (nbridge->tech == chan_tech) &&
06165 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06166 ISTRUNK(pbridge)) {
06167 int func = DAHDI_FLASH;
06168
06169 p->dop.dialstr[0] = '\0';
06170
06171 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06172 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
06173 nbridge->name, strerror(errno));
06174 }
06175 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06176 unalloc_sub(p, SUB_THREEWAY);
06177 p->owner = p->subs[SUB_REAL].owner;
06178 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06179 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06180 ast_hangup(chan);
06181 goto quit;
06182 } else {
06183 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06184 dahdi_wait_event(p->subs[index].dfd);
06185 tone_zone_play_tone(p->subs[index].dfd, -1);
06186 swap_subs(p, SUB_REAL, SUB_THREEWAY);
06187 unalloc_sub(p, SUB_THREEWAY);
06188 p->owner = p->subs[SUB_REAL].owner;
06189 ast_hangup(chan);
06190 goto quit;
06191 }
06192 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06193 ((exten[0] != '*') || (strlen(exten) > 2))) {
06194 if (option_debug)
06195 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);
06196 break;
06197 }
06198 if (!timeout)
06199 timeout = gendigittimeout;
06200 if (len && !ast_ignore_pattern(chan->context, exten))
06201 tone_zone_play_tone(p->subs[index].dfd, -1);
06202 }
06203 break;
06204 case SIG_FXSLS:
06205 case SIG_FXSGS:
06206 case SIG_FXSKS:
06207 #ifdef HAVE_PRI
06208 if (p->pri) {
06209
06210 struct ast_frame *f;
06211 int res;
06212 time_t start;
06213
06214 time(&start);
06215 ast_setstate(chan, AST_STATE_RING);
06216 while (time(NULL) < start + 3) {
06217 res = ast_waitfor(chan, 1000);
06218 if (res) {
06219 f = ast_read(chan);
06220 if (!f) {
06221 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06222 ast_hangup(chan);
06223 goto quit;
06224 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06225 res = 1;
06226 } else
06227 res = 0;
06228 ast_frfree(f);
06229 if (res) {
06230 ast_log(LOG_DEBUG, "Got ring!\n");
06231 res = 0;
06232 break;
06233 }
06234 }
06235 }
06236 }
06237 #endif
06238
06239 if (p->use_smdi && p->smdi_iface) {
06240 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06241
06242 if (smdi_msg != NULL) {
06243 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06244
06245 if (smdi_msg->type == 'B')
06246 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06247 else if (smdi_msg->type == 'N')
06248 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06249
06250 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06251 } else {
06252 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06253 }
06254 }
06255
06256 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06257 number = smdi_msg->calling_st;
06258
06259
06260
06261
06262 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06263
06264 if (p->cid_signalling == CID_SIG_DTMF) {
06265 int i = 0;
06266 cs = NULL;
06267 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06268 "channel %s\n", chan->name);
06269 dahdi_setlinear(p->subs[index].dfd, 0);
06270 res = 2000;
06271 for (;;) {
06272 struct ast_frame *f;
06273 res = ast_waitfor(chan, res);
06274 if (res <= 0) {
06275 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06276 "Exiting simple switch\n");
06277 ast_hangup(chan);
06278 goto quit;
06279 }
06280 f = ast_read(chan);
06281 if (!f)
06282 break;
06283 if (f->frametype == AST_FRAME_DTMF) {
06284 dtmfbuf[i++] = f->subclass;
06285 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06286 res = 2000;
06287 }
06288 ast_frfree(f);
06289 if (chan->_state == AST_STATE_RING ||
06290 chan->_state == AST_STATE_RINGING)
06291 break;
06292 }
06293 dtmfbuf[i] = '\0';
06294 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06295
06296 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06297 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06298 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
06299 dtmfcid, flags);
06300
06301 if (!ast_strlen_zero(dtmfcid))
06302 number = dtmfcid;
06303 else
06304 number = NULL;
06305
06306 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06307 cs = callerid_new(p->cid_signalling);
06308 if (cs) {
06309 samples = 0;
06310 #if 1
06311 bump_gains(p);
06312 #endif
06313
06314 dahdi_setlinear(p->subs[index].dfd, 0);
06315
06316
06317 for (;;) {
06318 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06319 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06320 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06321 callerid_free(cs);
06322 ast_hangup(chan);
06323 goto quit;
06324 }
06325 if (i & DAHDI_IOMUX_SIGEVENT) {
06326 res = dahdi_get_event(p->subs[index].dfd);
06327 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06328
06329 if (p->cid_signalling == CID_SIG_V23_JP) {
06330 #ifdef DAHDI_EVENT_RINGBEGIN
06331 if (res == DAHDI_EVENT_RINGBEGIN) {
06332 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06333 usleep(1);
06334 }
06335 #endif
06336 } else {
06337 res = 0;
06338 break;
06339 }
06340 } else if (i & DAHDI_IOMUX_READ) {
06341 res = read(p->subs[index].dfd, buf, sizeof(buf));
06342 if (res < 0) {
06343 if (errno != ELAST) {
06344 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06345 callerid_free(cs);
06346 ast_hangup(chan);
06347 goto quit;
06348 }
06349 break;
06350 }
06351 samples += res;
06352
06353 if (p->cid_signalling == CID_SIG_V23_JP) {
06354 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06355 } else {
06356 res = callerid_feed(cs, buf, res, AST_LAW(p));
06357 }
06358
06359 if (res < 0) {
06360 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06361 break;
06362 } else if (res)
06363 break;
06364 else if (samples > (8000 * 10))
06365 break;
06366 }
06367 }
06368 if (res == 1) {
06369 callerid_get(cs, &name, &number, &flags);
06370 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06371 }
06372
06373 if (p->cid_signalling == CID_SIG_V23_JP) {
06374 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06375 usleep(1);
06376 res = 4000;
06377 } else {
06378
06379
06380 res = 2000;
06381 }
06382
06383 for (;;) {
06384 struct ast_frame *f;
06385 res = ast_waitfor(chan, res);
06386 if (res <= 0) {
06387 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06388 "Exiting simple switch\n");
06389 ast_hangup(chan);
06390 goto quit;
06391 }
06392 if (!(f = ast_read(chan))) {
06393 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06394 ast_hangup(chan);
06395 goto quit;
06396 }
06397 ast_frfree(f);
06398 if (chan->_state == AST_STATE_RING ||
06399 chan->_state == AST_STATE_RINGING)
06400 break;
06401 }
06402
06403
06404
06405 if (p->usedistinctiveringdetection == 1) {
06406 len = 0;
06407 distMatches = 0;
06408
06409 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06410 curRingData[receivedRingT] = 0;
06411 receivedRingT = 0;
06412 counter = 0;
06413 counter1 = 0;
06414
06415 if (strcmp(p->context,p->defcontext) != 0) {
06416 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06417 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06418 }
06419
06420 for (;;) {
06421 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06422 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06423 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06424 callerid_free(cs);
06425 ast_hangup(chan);
06426 goto quit;
06427 }
06428 if (i & DAHDI_IOMUX_SIGEVENT) {
06429 res = dahdi_get_event(p->subs[index].dfd);
06430 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06431 res = 0;
06432
06433
06434 curRingData[receivedRingT] = p->ringt;
06435
06436 if (p->ringt < p->ringt_base/2)
06437 break;
06438
06439
06440 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06441 break;
06442 } else if (i & DAHDI_IOMUX_READ) {
06443 res = read(p->subs[index].dfd, buf, sizeof(buf));
06444 if (res < 0) {
06445 if (errno != ELAST) {
06446 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06447 callerid_free(cs);
06448 ast_hangup(chan);
06449 goto quit;
06450 }
06451 break;
06452 }
06453 if (p->ringt)
06454 p->ringt--;
06455 if (p->ringt == 1) {
06456 res = -1;
06457 break;
06458 }
06459 }
06460 }
06461 if (option_verbose > 2)
06462
06463 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06464
06465 for (counter = 0; counter < 3; counter++) {
06466
06467
06468 distMatches = 0;
06469 for (counter1 = 0; counter1 < 3; counter1++) {
06470 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06471 (p->drings.ringnum[counter].ring[counter1]-10)) {
06472 distMatches++;
06473 }
06474 }
06475 if (distMatches == 3) {
06476
06477 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06478 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06479 if (option_verbose > 2)
06480 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06481 break;
06482 }
06483 }
06484 }
06485
06486 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06487 #if 1
06488 restore_gains(p);
06489 #endif
06490 } else
06491 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06492 } else {
06493 ast_log(LOG_WARNING, "Channel %s in prering "
06494 "state, but I have nothing to do. "
06495 "Terminating simple switch, should be "
06496 "restarted by the actual ring.\n",
06497 chan->name);
06498 ast_hangup(chan);
06499 goto quit;
06500 }
06501 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06502
06503 cs = callerid_new(p->cid_signalling);
06504 if (cs) {
06505 #if 1
06506 bump_gains(p);
06507 #endif
06508 samples = 0;
06509 len = 0;
06510 distMatches = 0;
06511
06512 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06513 curRingData[receivedRingT] = 0;
06514 receivedRingT = 0;
06515 counter = 0;
06516 counter1 = 0;
06517
06518 if (strcmp(p->context,p->defcontext) != 0) {
06519 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06520 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06521 }
06522
06523
06524 dahdi_setlinear(p->subs[index].dfd, 0);
06525 for (;;) {
06526 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06527 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06528 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06529 callerid_free(cs);
06530 ast_hangup(chan);
06531 goto quit;
06532 }
06533 if (i & DAHDI_IOMUX_SIGEVENT) {
06534 res = dahdi_get_event(p->subs[index].dfd);
06535 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06536
06537 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06538 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06539 p->polarity = POLARITY_IDLE;
06540 callerid_free(cs);
06541 ast_hangup(chan);
06542 goto quit;
06543 }
06544 res = 0;
06545
06546
06547 curRingData[receivedRingT] = p->ringt;
06548
06549 if (p->ringt < p->ringt_base/2)
06550 break;
06551
06552
06553 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06554 break;
06555 } else if (i & DAHDI_IOMUX_READ) {
06556 res = read(p->subs[index].dfd, buf, sizeof(buf));
06557 if (res < 0) {
06558 if (errno != ELAST) {
06559 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06560 callerid_free(cs);
06561 ast_hangup(chan);
06562 goto quit;
06563 }
06564 break;
06565 }
06566 if (p->ringt)
06567 p->ringt--;
06568 if (p->ringt == 1) {
06569 res = -1;
06570 break;
06571 }
06572 samples += res;
06573 res = callerid_feed(cs, buf, res, AST_LAW(p));
06574 if (res < 0) {
06575 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06576 break;
06577 } else if (res)
06578 break;
06579 else if (samples > (8000 * 10))
06580 break;
06581 }
06582 }
06583 if (res == 1) {
06584 callerid_get(cs, &name, &number, &flags);
06585 if (option_debug)
06586 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06587 }
06588 if (distinctiveringaftercid == 1) {
06589
06590 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06591 curRingData[receivedRingT] = 0;
06592 }
06593 receivedRingT = 0;
06594 if (option_verbose > 2)
06595 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06596 for (;;) {
06597 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06598 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
06599 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06600 callerid_free(cs);
06601 ast_hangup(chan);
06602 goto quit;
06603 }
06604 if (i & DAHDI_IOMUX_SIGEVENT) {
06605 res = dahdi_get_event(p->subs[index].dfd);
06606 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06607 res = 0;
06608
06609
06610 curRingData[receivedRingT] = p->ringt;
06611
06612 if (p->ringt < p->ringt_base/2)
06613 break;
06614
06615
06616 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06617 break;
06618 } else if (i & DAHDI_IOMUX_READ) {
06619 res = read(p->subs[index].dfd, buf, sizeof(buf));
06620 if (res < 0) {
06621 if (errno != ELAST) {
06622 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06623 callerid_free(cs);
06624 ast_hangup(chan);
06625 goto quit;
06626 }
06627 break;
06628 }
06629 if (p->ringt)
06630 p->ringt--;
06631 if (p->ringt == 1) {
06632 res = -1;
06633 break;
06634 }
06635 }
06636 }
06637 }
06638 if (p->usedistinctiveringdetection == 1) {
06639 if (option_verbose > 2)
06640
06641 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06642
06643 for (counter = 0; counter < 3; counter++) {
06644
06645
06646 if (option_verbose > 2)
06647
06648 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06649 p->drings.ringnum[counter].ring[0],
06650 p->drings.ringnum[counter].ring[1],
06651 p->drings.ringnum[counter].ring[2]);
06652 distMatches = 0;
06653 for (counter1 = 0; counter1 < 3; counter1++) {
06654 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06655 (p->drings.ringnum[counter].ring[counter1]-10)) {
06656 distMatches++;
06657 }
06658 }
06659 if (distMatches == 3) {
06660
06661 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06662 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06663 if (option_verbose > 2)
06664 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06665 break;
06666 }
06667 }
06668 }
06669
06670 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06671 #if 1
06672 restore_gains(p);
06673 #endif
06674 if (res < 0) {
06675 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06676 }
06677 } else
06678 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06679 }
06680 else
06681 cs = NULL;
06682
06683 if (number)
06684 ast_shrink_phone_number(number);
06685 ast_set_callerid(chan, number, name, number);
06686
06687 if (smdi_msg)
06688 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06689
06690 if (cs)
06691 callerid_free(cs);
06692
06693 ast_setstate(chan, AST_STATE_RING);
06694 chan->rings = 1;
06695 p->ringt = p->ringt_base;
06696 res = ast_pbx_run(chan);
06697 if (res) {
06698 ast_hangup(chan);
06699 ast_log(LOG_WARNING, "PBX exited non-zero\n");
06700 }
06701 goto quit;
06702 default:
06703 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06704 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06705 if (res < 0)
06706 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06707 }
06708 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06709 if (res < 0)
06710 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06711 ast_hangup(chan);
06712 quit:
06713 ast_mutex_lock(&ss_thread_lock);
06714 ss_thread_count--;
06715 ast_cond_signal(&ss_thread_complete);
06716 ast_mutex_unlock(&ss_thread_lock);
06717 return NULL;
06718 }
06719
06720
06721 static int dahdi_destroy_channel_bynum(int channel)
06722 {
06723 struct dahdi_pvt *tmp = NULL;
06724 struct dahdi_pvt *prev = NULL;
06725
06726 tmp = iflist;
06727 while (tmp) {
06728 if (tmp->channel == channel) {
06729 int x = DAHDI_FLASH;
06730 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06731 destroy_channel(prev, tmp, 1);
06732 ast_module_unref(ast_module_info->self);
06733 return RESULT_SUCCESS;
06734 }
06735 prev = tmp;
06736 tmp = tmp->next;
06737 }
06738 return RESULT_FAILURE;
06739 }
06740
06741 static int handle_init_event(struct dahdi_pvt *i, int event)
06742 {
06743 int res;
06744 pthread_t threadid;
06745 pthread_attr_t attr;
06746 struct ast_channel *chan;
06747 pthread_attr_init(&attr);
06748 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06749
06750 switch (event) {
06751 case DAHDI_EVENT_NONE:
06752 case DAHDI_EVENT_BITSCHANGED:
06753 break;
06754 case DAHDI_EVENT_WINKFLASH:
06755 case DAHDI_EVENT_RINGOFFHOOK:
06756 if (i->inalarm) break;
06757 if (i->radio) break;
06758
06759 switch (i->sig) {
06760 case SIG_FXOLS:
06761 case SIG_FXOGS:
06762 case SIG_FXOKS:
06763 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06764 if (res && (errno == EBUSY))
06765 break;
06766 if (i->cidspill) {
06767
06768 free(i->cidspill);
06769 i->cidspill = NULL;
06770 }
06771 if (i->immediate) {
06772 dahdi_enable_ec(i);
06773
06774 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06775 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06776 if (!chan) {
06777 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06778 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06779 if (res < 0)
06780 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06781 }
06782 } else {
06783
06784 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06785 if (chan) {
06786 if (has_voicemail(i))
06787 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06788 else
06789 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06790 if (res < 0)
06791 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06792 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06793 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06794 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06795 if (res < 0)
06796 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06797 ast_hangup(chan);
06798 }
06799 } else
06800 ast_log(LOG_WARNING, "Unable to create channel\n");
06801 }
06802 break;
06803 case SIG_FXSLS:
06804 case SIG_FXSGS:
06805 case SIG_FXSKS:
06806 i->ringt = i->ringt_base;
06807
06808 case SIG_EMWINK:
06809 case SIG_FEATD:
06810 case SIG_FEATDMF:
06811 case SIG_FEATDMF_TA:
06812 case SIG_E911:
06813 case SIG_FGC_CAMA:
06814 case SIG_FGC_CAMAMF:
06815 case SIG_FEATB:
06816 case SIG_EM:
06817 case SIG_EM_E1:
06818 case SIG_SFWINK:
06819 case SIG_SF_FEATD:
06820 case SIG_SF_FEATDMF:
06821 case SIG_SF_FEATB:
06822 case SIG_SF:
06823
06824 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06825 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06826 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06827 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06828 if (res < 0)
06829 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06830 ast_hangup(chan);
06831 } else if (!chan) {
06832 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06833 }
06834 break;
06835 default:
06836 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06837 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06838 if (res < 0)
06839 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06840 return -1;
06841 }
06842 break;
06843 case DAHDI_EVENT_NOALARM:
06844 i->inalarm = 0;
06845 if (!i->unknown_alarm) {
06846 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06847 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06848 "Channel: %d\r\n", i->channel);
06849 } else {
06850 i->unknown_alarm = 0;
06851 }
06852 break;
06853 case DAHDI_EVENT_ALARM:
06854 i->inalarm = 1;
06855 res = get_alarms(i);
06856 handle_alarms(i, res);
06857
06858 case DAHDI_EVENT_ONHOOK:
06859 if (i->radio)
06860 break;
06861
06862 switch (i->sig) {
06863 case SIG_FXOLS:
06864 case SIG_FXOGS:
06865 case SIG_FEATD:
06866 case SIG_FEATDMF:
06867 case SIG_FEATDMF_TA:
06868 case SIG_E911:
06869 case SIG_FGC_CAMA:
06870 case SIG_FGC_CAMAMF:
06871 case SIG_FEATB:
06872 case SIG_EM:
06873 case SIG_EM_E1:
06874 case SIG_EMWINK:
06875 case SIG_SF_FEATD:
06876 case SIG_SF_FEATDMF:
06877 case SIG_SF_FEATB:
06878 case SIG_SF:
06879 case SIG_SFWINK:
06880 case SIG_FXSLS:
06881 case SIG_FXSGS:
06882 case SIG_FXSKS:
06883 case SIG_GR303FXSKS:
06884 dahdi_disable_ec(i);
06885 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06886 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06887 break;
06888 case SIG_GR303FXOKS:
06889 case SIG_FXOKS:
06890 dahdi_disable_ec(i);
06891
06892 #ifdef ZHONE_HACK
06893 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06894 usleep(1);
06895 #endif
06896 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06897 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06898 break;
06899 case SIG_PRI:
06900 dahdi_disable_ec(i);
06901 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06902 break;
06903 default:
06904 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06905 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06906 return -1;
06907 }
06908 break;
06909 case DAHDI_EVENT_POLARITY:
06910 switch (i->sig) {
06911 case SIG_FXSLS:
06912 case SIG_FXSKS:
06913 case SIG_FXSGS:
06914
06915
06916
06917
06918 if (i->hanguponpolarityswitch)
06919 i->polarity = POLARITY_REV;
06920
06921 if (i->cid_start == CID_START_POLARITY) {
06922 i->polarity = POLARITY_REV;
06923 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06924 "CID detection on channel %d\n",
06925 i->channel);
06926 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06927 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06928 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06929 }
06930 }
06931 break;
06932 default:
06933 ast_log(LOG_WARNING, "handle_init_event detected "
06934 "polarity reversal on non-FXO (SIG_FXS) "
06935 "interface %d\n", i->channel);
06936 }
06937 break;
06938 case DAHDI_EVENT_REMOVED:
06939 ast_log(LOG_NOTICE,
06940 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
06941 i->channel);
06942 dahdi_destroy_channel_bynum(i->channel);
06943 break;
06944 }
06945 pthread_attr_destroy(&attr);
06946 return 0;
06947 }
06948
06949 static void *do_monitor(void *data)
06950 {
06951 int count, res, res2, spoint, pollres=0;
06952 struct dahdi_pvt *i;
06953 struct dahdi_pvt *last = NULL;
06954 time_t thispass = 0, lastpass = 0;
06955 int found;
06956 char buf[1024];
06957 struct pollfd *pfds=NULL;
06958 int lastalloc = -1;
06959
06960
06961
06962 #if 0
06963 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06964 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06965 return NULL;
06966 }
06967 ast_log(LOG_DEBUG, "Monitor starting...\n");
06968 #endif
06969 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
06970
06971 for (;;) {
06972
06973 ast_mutex_lock(&iflock);
06974 if (!pfds || (lastalloc != ifcount)) {
06975 if (pfds) {
06976 free(pfds);
06977 pfds = NULL;
06978 }
06979 if (ifcount) {
06980 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06981 ast_mutex_unlock(&iflock);
06982 return NULL;
06983 }
06984 }
06985 lastalloc = ifcount;
06986 }
06987
06988
06989 count = 0;
06990 i = iflist;
06991 while (i) {
06992 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
06993 if (!i->owner && !i->subs[SUB_REAL].owner) {
06994
06995 pfds[count].fd = i->subs[SUB_REAL].dfd;
06996 pfds[count].events = POLLPRI;
06997 pfds[count].revents = 0;
06998
06999 if (i->cidspill)
07000 pfds[count].events |= POLLIN;
07001 count++;
07002 }
07003 }
07004 i = i->next;
07005 }
07006
07007 ast_mutex_unlock(&iflock);
07008
07009 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07010 pthread_testcancel();
07011
07012 res = poll(pfds, count, 1000);
07013 pthread_testcancel();
07014 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07015
07016
07017 if (res < 0) {
07018 if ((errno != EAGAIN) && (errno != EINTR))
07019 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07020 continue;
07021 }
07022
07023
07024 ast_mutex_lock(&iflock);
07025 found = 0;
07026 spoint = 0;
07027 lastpass = thispass;
07028 thispass = time(NULL);
07029 i = iflist;
07030 while (i) {
07031 if (thispass != lastpass) {
07032 if (!found && ((i == last) || ((i == iflist) && !last))) {
07033 last = i;
07034 if (last) {
07035 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07036 (last->sig & __DAHDI_SIG_FXO)) {
07037 res = ast_app_has_voicemail(last->mailbox, NULL);
07038 if (last->msgstate != res) {
07039 int x;
07040 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07041 x = DAHDI_FLUSH_BOTH;
07042 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07043 if (res2)
07044 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07045 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07046
07047 x = 4000;
07048 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07049 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07050 last->cidpos = 0;
07051 last->msgstate = res;
07052 last->onhooktime = thispass;
07053 }
07054 found ++;
07055 }
07056 }
07057 last = last->next;
07058 }
07059 }
07060 }
07061 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07062 if (i->radio && !i->owner)
07063 {
07064 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07065 if (res)
07066 {
07067 if (option_debug)
07068 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07069
07070 ast_mutex_unlock(&iflock);
07071 handle_init_event(i, res);
07072 ast_mutex_lock(&iflock);
07073 }
07074 i = i->next;
07075 continue;
07076 }
07077 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07078 if (pollres & POLLIN) {
07079 if (i->owner || i->subs[SUB_REAL].owner) {
07080 #ifdef HAVE_PRI
07081 if (!i->pri)
07082 #endif
07083 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07084 i = i->next;
07085 continue;
07086 }
07087 if (!i->cidspill) {
07088 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07089 i = i->next;
07090 continue;
07091 }
07092 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07093 if (res > 0) {
07094
07095 if (res > i->cidlen - i->cidpos)
07096 res = i->cidlen - i->cidpos;
07097 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07098 if (res2 > 0) {
07099 i->cidpos += res2;
07100 if (i->cidpos >= i->cidlen) {
07101 free(i->cidspill);
07102 i->cidspill = 0;
07103 i->cidpos = 0;
07104 i->cidlen = 0;
07105 }
07106 } else {
07107 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07108 i->msgstate = -1;
07109 }
07110 } else {
07111 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07112 }
07113 }
07114 if (pollres & POLLPRI) {
07115 if (i->owner || i->subs[SUB_REAL].owner) {
07116 #ifdef HAVE_PRI
07117 if (!i->pri)
07118 #endif
07119 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07120 i = i->next;
07121 continue;
07122 }
07123 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07124 if (option_debug)
07125 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07126
07127 ast_mutex_unlock(&iflock);
07128 handle_init_event(i, res);
07129 ast_mutex_lock(&iflock);
07130 }
07131 }
07132 i=i->next;
07133 }
07134 ast_mutex_unlock(&iflock);
07135 }
07136
07137 return NULL;
07138
07139 }
07140
07141 static int restart_monitor(void)
07142 {
07143 pthread_attr_t attr;
07144 pthread_attr_init(&attr);
07145 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07146
07147 if (monitor_thread == AST_PTHREADT_STOP)
07148 return 0;
07149 ast_mutex_lock(&monlock);
07150 if (monitor_thread == pthread_self()) {
07151 ast_mutex_unlock(&monlock);
07152 ast_log(LOG_WARNING, "Cannot kill myself\n");
07153 return -1;
07154 }
07155 if (monitor_thread != AST_PTHREADT_NULL) {
07156
07157 pthread_kill(monitor_thread, SIGURG);
07158 } else {
07159
07160 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07161 ast_mutex_unlock(&monlock);
07162 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07163 pthread_attr_destroy(&attr);
07164 return -1;
07165 }
07166 }
07167 ast_mutex_unlock(&monlock);
07168 pthread_attr_destroy(&attr);
07169 return 0;
07170 }
07171
07172 #ifdef HAVE_PRI
07173 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07174 {
07175 int x;
07176 int trunkgroup;
07177
07178 trunkgroup = pris[*span].mastertrunkgroup;
07179 if (trunkgroup) {
07180
07181 for (x = 0; x < NUM_SPANS; x++) {
07182 if (pris[x].trunkgroup == trunkgroup) {
07183 *span = x;
07184 return 0;
07185 }
07186 }
07187 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07188 *span = -1;
07189 } else {
07190 if (pris[*span].trunkgroup) {
07191 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07192 *span = -1;
07193 } else if (pris[*span].mastertrunkgroup) {
07194 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07195 *span = -1;
07196 } else {
07197 if (si->totalchans == 31) {
07198
07199 pris[*span].dchannels[0] = 16 + offset;
07200 } else if (si->totalchans == 24) {
07201
07202 pris[*span].dchannels[0] = 24 + offset;
07203 } else if (si->totalchans == 3) {
07204
07205 pris[*span].dchannels[0] = 3 + offset;
07206 } else {
07207 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);
07208 *span = -1;
07209 return 0;
07210 }
07211 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07212 pris[*span].offset = offset;
07213 pris[*span].span = *span + 1;
07214 }
07215 }
07216 return 0;
07217 }
07218
07219 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07220 {
07221 struct dahdi_spaninfo si;
07222 struct dahdi_params p;
07223 int fd;
07224 int span;
07225 int ospan=0;
07226 int x,y;
07227 for (x = 0; x < NUM_SPANS; x++) {
07228 if (pris[x].trunkgroup == trunkgroup) {
07229 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07230 return -1;
07231 }
07232 }
07233 for (y = 0; y < NUM_DCHANS; y++) {
07234 if (!channels[y])
07235 break;
07236 memset(&si, 0, sizeof(si));
07237 memset(&p, 0, sizeof(p));
07238 #ifdef HAVE_ZAPTEL
07239 fd = open("/dev/zap/channel", O_RDWR);
07240 #else
07241 fd = open("/dev/dahdi/channel", O_RDWR);
07242 #endif
07243 if (fd < 0) {
07244 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07245 return -1;
07246 }
07247 x = channels[y];
07248 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07249 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07250 close(fd);
07251 return -1;
07252 }
07253 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07254 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07255 return -1;
07256 }
07257 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07258 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07259 close(fd);
07260 return -1;
07261 }
07262 span = p.spanno - 1;
07263 if (pris[span].trunkgroup) {
07264 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07265 close(fd);
07266 return -1;
07267 }
07268 if (pris[span].pvts[0]) {
07269 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07270 close(fd);
07271 return -1;
07272 }
07273 if (!y) {
07274 pris[span].trunkgroup = trunkgroup;
07275 pris[span].offset = channels[y] - p.chanpos;
07276 ospan = span;
07277 }
07278 pris[ospan].dchannels[y] = channels[y];
07279 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07280 pris[span].span = span + 1;
07281 close(fd);
07282 }
07283 return 0;
07284 }
07285
07286 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07287 {
07288 if (pris[span].mastertrunkgroup) {
07289 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);
07290 return -1;
07291 }
07292 pris[span].mastertrunkgroup = trunkgroup;
07293 pris[span].prilogicalspan = logicalspan;
07294 return 0;
07295 }
07296
07297 #endif
07298
07299 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07300 {
07301
07302 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
07303 char fn[80];
07304 #if 1
07305 struct dahdi_bufferinfo bi;
07306 #endif
07307 int res;
07308 int span=0;
07309 int here = 0;
07310 int x;
07311 struct dahdi_pvt **wlist;
07312 struct dahdi_pvt **wend;
07313 struct dahdi_params p;
07314
07315 wlist = &iflist;
07316 wend = &ifend;
07317
07318 #ifdef HAVE_PRI
07319 if (pri) {
07320 wlist = &pri->crvs;
07321 wend = &pri->crvend;
07322 }
07323 #endif
07324
07325 tmp2 = *wlist;
07326 prev = NULL;
07327
07328 while (tmp2) {
07329 if (!tmp2->destroy) {
07330 if (tmp2->channel == channel) {
07331 tmp = tmp2;
07332 here = 1;
07333 break;
07334 }
07335 if (tmp2->channel > channel) {
07336 break;
07337 }
07338 }
07339 prev = tmp2;
07340 tmp2 = tmp2->next;
07341 }
07342
07343 if (!here && reloading != 1) {
07344 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07345 if (tmp)
07346 free(tmp);
07347 return NULL;
07348 }
07349 ast_mutex_init(&tmp->lock);
07350 ifcount++;
07351 for (x = 0; x < 3; x++)
07352 tmp->subs[x].dfd = -1;
07353 tmp->channel = channel;
07354 }
07355
07356 if (tmp) {
07357 int chan_sig = conf->chan.sig;
07358 if (!here) {
07359 if ((channel != CHAN_PSEUDO) && !pri) {
07360 int count = 0;
07361 snprintf(fn, sizeof(fn), "%d", channel);
07362
07363 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07364 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
07365 usleep(1);
07366 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07367 count++;
07368 }
07369
07370 if (tmp->subs[SUB_REAL].dfd < 0) {
07371 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);
07372 destroy_dahdi_pvt(&tmp);
07373 return NULL;
07374 }
07375 memset(&p, 0, sizeof(p));
07376 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07377 if (res < 0) {
07378 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07379 destroy_dahdi_pvt(&tmp);
07380 return NULL;
07381 }
07382 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07383 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));
07384 destroy_dahdi_pvt(&tmp);
07385 return NULL;
07386 }
07387 tmp->law = p.curlaw;
07388 tmp->span = p.spanno;
07389 span = p.spanno - 1;
07390 } else {
07391 if (channel == CHAN_PSEUDO)
07392 chan_sig = 0;
07393 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07394 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07395 return NULL;
07396 }
07397 }
07398 #ifdef HAVE_PRI
07399 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07400 int offset;
07401 int myswitchtype;
07402 int matchesdchan;
07403 int x,y;
07404 offset = 0;
07405 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07406 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07407 destroy_dahdi_pvt(&tmp);
07408 return NULL;
07409 }
07410 if (span >= NUM_SPANS) {
07411 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07412 destroy_dahdi_pvt(&tmp);
07413 return NULL;
07414 } else {
07415 struct dahdi_spaninfo si;
07416 si.spanno = 0;
07417 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07418 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07419 destroy_dahdi_pvt(&tmp);
07420 return NULL;
07421 }
07422
07423 tmp->logicalspan = pris[span].prilogicalspan;
07424 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07425 if (span < 0) {
07426 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07427 destroy_dahdi_pvt(&tmp);
07428 return NULL;
07429 }
07430 if (chan_sig == SIG_PRI)
07431 myswitchtype = conf->pri.switchtype;
07432 else
07433 myswitchtype = PRI_SWITCH_GR303_TMC;
07434
07435 matchesdchan=0;
07436 for (x = 0; x < NUM_SPANS; x++) {
07437 for (y = 0; y < NUM_DCHANS; y++) {
07438 if (pris[x].dchannels[y] == tmp->channel) {
07439 matchesdchan = 1;
07440 break;
07441 }
07442 }
07443 }
07444 offset = p.chanpos;
07445 if (!matchesdchan) {
07446 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07447 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07448 destroy_dahdi_pvt(&tmp);
07449 return NULL;
07450 }
07451 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07452 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07453 destroy_dahdi_pvt(&tmp);
07454 return NULL;
07455 }
07456 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07457 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07458 destroy_dahdi_pvt(&tmp);
07459 return NULL;
07460 }
07461 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07462 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07463 destroy_dahdi_pvt(&tmp);
07464 return NULL;
07465 }
07466 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07467 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07468 destroy_dahdi_pvt(&tmp);
07469 return NULL;
07470 }
07471 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07472 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07473 destroy_dahdi_pvt(&tmp);
07474 return NULL;
07475 }
07476 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07477 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07478 destroy_dahdi_pvt(&tmp);
07479 return NULL;
07480 }
07481 if (pris[span].numchans >= MAX_CHANNELS) {
07482 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07483 pris[span].trunkgroup);
07484 destroy_dahdi_pvt(&tmp);
07485 return NULL;
07486 }
07487 pris[span].nodetype = conf->pri.nodetype;
07488 pris[span].switchtype = myswitchtype;
07489 pris[span].nsf = conf->pri.nsf;
07490 pris[span].dialplan = conf->pri.dialplan;
07491 pris[span].localdialplan = conf->pri.localdialplan;
07492 pris[span].pvts[pris[span].numchans++] = tmp;
07493 pris[span].minunused = conf->pri.minunused;
07494 pris[span].minidle = conf->pri.minidle;
07495 pris[span].overlapdial = conf->pri.overlapdial;
07496 #ifdef HAVE_PRI_INBANDDISCONNECT
07497 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07498 #endif
07499 pris[span].facilityenable = conf->pri.facilityenable;
07500 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07501 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07502 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07503 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07504 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07505 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07506 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07507 pris[span].resetinterval = conf->pri.resetinterval;
07508
07509 tmp->pri = &pris[span];
07510 tmp->prioffset = offset;
07511 tmp->call = NULL;
07512 } else {
07513 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07514 destroy_dahdi_pvt(&tmp);
07515 return NULL;
07516 }
07517 }
07518 } else {
07519 tmp->prioffset = 0;
07520 }
07521 #endif
07522 } else {
07523 chan_sig = tmp->sig;
07524 memset(&p, 0, sizeof(p));
07525 if (tmp->subs[SUB_REAL].dfd > -1)
07526 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07527 }
07528
07529 switch (chan_sig) {
07530 case SIG_FXSKS:
07531 case SIG_FXSLS:
07532 case SIG_EM:
07533 case SIG_EM_E1:
07534 case SIG_EMWINK:
07535 case SIG_FEATD:
07536 case SIG_FEATDMF:
07537 case SIG_FEATDMF_TA:
07538 case SIG_FEATB:
07539 case SIG_E911:
07540 case SIG_SF:
07541 case SIG_SFWINK:
07542 case SIG_FGC_CAMA:
07543 case SIG_FGC_CAMAMF:
07544 case SIG_SF_FEATD:
07545 case SIG_SF_FEATDMF:
07546 case SIG_SF_FEATB:
07547 p.starttime = 250;
07548 break;
07549 }
07550
07551 if (tmp->radio) {
07552
07553 p.channo = channel;
07554 p.rxwinktime = 1;
07555 p.rxflashtime = 1;
07556 p.starttime = 1;
07557 p.debouncetime = 5;
07558 }
07559 if (!tmp->radio) {
07560 p.channo = channel;
07561
07562 if (conf->timing.prewinktime >= 0)
07563 p.prewinktime = conf->timing.prewinktime;
07564 if (conf->timing.preflashtime >= 0)
07565 p.preflashtime = conf->timing.preflashtime;
07566 if (conf->timing.winktime >= 0)
07567 p.winktime = conf->timing.winktime;
07568 if (conf->timing.flashtime >= 0)
07569 p.flashtime = conf->timing.flashtime;
07570 if (conf->timing.starttime >= 0)
07571 p.starttime = conf->timing.starttime;
07572 if (conf->timing.rxwinktime >= 0)
07573 p.rxwinktime = conf->timing.rxwinktime;
07574 if (conf->timing.rxflashtime >= 0)
07575 p.rxflashtime = conf->timing.rxflashtime;
07576 if (conf->timing.debouncetime >= 0)
07577 p.debouncetime = conf->timing.debouncetime;
07578 }
07579
07580
07581 if (tmp->subs[SUB_REAL].dfd >= 0)
07582 {
07583 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07584 if (res < 0) {
07585 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07586 destroy_dahdi_pvt(&tmp);
07587 return NULL;
07588 }
07589 }
07590 #if 1
07591 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07592 memset(&bi, 0, sizeof(bi));
07593 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07594 if (!res) {
07595 bi.txbufpolicy = conf->chan.buf_policy;
07596 bi.rxbufpolicy = conf->chan.buf_policy;
07597 bi.numbufs = conf->chan.buf_no;
07598 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07599 if (res < 0) {
07600 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07601 }
07602 } else
07603 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07604 }
07605 #endif
07606 tmp->immediate = conf->chan.immediate;
07607 tmp->transfertobusy = conf->chan.transfertobusy;
07608 tmp->sig = chan_sig;
07609 tmp->outsigmod = conf->chan.outsigmod;
07610 tmp->ringt_base = ringt_base;
07611 tmp->firstradio = 0;
07612 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07613 tmp->permcallwaiting = conf->chan.callwaiting;
07614 else
07615 tmp->permcallwaiting = 0;
07616
07617 tmp->destroy = 0;
07618 tmp->drings = drings;
07619 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07620 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07621 tmp->threewaycalling = conf->chan.threewaycalling;
07622 tmp->adsi = conf->chan.adsi;
07623 tmp->use_smdi = conf->chan.use_smdi;
07624 tmp->permhidecallerid = conf->chan.hidecallerid;
07625 tmp->callreturn = conf->chan.callreturn;
07626 tmp->echocancel = conf->chan.echocancel;
07627 tmp->echotraining = conf->chan.echotraining;
07628 tmp->pulse = conf->chan.pulse;
07629 if (tmp->echocancel)
07630 tmp->echocanbridged = conf->chan.echocanbridged;
07631 else {
07632 if (conf->chan.echocanbridged)
07633 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07634 tmp->echocanbridged = 0;
07635 }
07636 tmp->busydetect = conf->chan.busydetect;
07637 tmp->busycount = conf->chan.busycount;
07638 tmp->busycompare = conf->chan.busycompare;
07639 tmp->busytonelength = conf->chan.busytonelength;
07640 tmp->busyquietlength = conf->chan.busyquietlength;
07641 tmp->busyfuzziness = conf->chan.busyfuzziness;
07642 tmp->silencethreshold = conf->chan.silencethreshold;
07643 tmp->callprogress = conf->chan.callprogress;
07644 tmp->cancallforward = conf->chan.cancallforward;
07645 tmp->dtmfrelax = conf->chan.dtmfrelax;
07646 tmp->callwaiting = tmp->permcallwaiting;
07647 tmp->hidecallerid = tmp->permhidecallerid;
07648 tmp->channel = channel;
07649 tmp->stripmsd = conf->chan.stripmsd;
07650 tmp->use_callerid = conf->chan.use_callerid;
07651 tmp->cid_signalling = conf->chan.cid_signalling;
07652 tmp->cid_start = conf->chan.cid_start;
07653 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07654 tmp->restrictcid = conf->chan.restrictcid;
07655 tmp->use_callingpres = conf->chan.use_callingpres;
07656 tmp->priindication_oob = conf->chan.priindication_oob;
07657 tmp->priexclusive = conf->chan.priexclusive;
07658 if (tmp->usedistinctiveringdetection) {
07659 if (!tmp->use_callerid) {
07660 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07661 tmp->use_callerid = 1;
07662 }
07663 }
07664
07665 if (tmp->cid_signalling == CID_SIG_SMDI) {
07666 if (!tmp->use_smdi) {
07667 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07668 tmp->use_smdi = 1;
07669 }
07670 }
07671 if (tmp->use_smdi) {
07672 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07673 if (!(tmp->smdi_iface)) {
07674 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07675 tmp->use_smdi = 0;
07676 }
07677 }
07678
07679 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07680 tmp->amaflags = conf->chan.amaflags;
07681 if (!here) {
07682 tmp->confno = -1;
07683 tmp->propconfno = -1;
07684 }
07685 tmp->canpark = conf->chan.canpark;
07686 tmp->transfer = conf->chan.transfer;
07687 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07688 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07689 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07690 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07691 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07692 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07693 tmp->cid_ton = 0;
07694 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07695 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07696 tmp->msgstate = -1;
07697 tmp->group = conf->chan.group;
07698 tmp->callgroup = conf->chan.callgroup;
07699 tmp->pickupgroup= conf->chan.pickupgroup;
07700 tmp->rxgain = conf->chan.rxgain;
07701 tmp->txgain = conf->chan.txgain;
07702 tmp->tonezone = conf->chan.tonezone;
07703 tmp->onhooktime = time(NULL);
07704 if (tmp->subs[SUB_REAL].dfd > -1) {
07705 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07706 if (tmp->dsp)
07707 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07708 update_conf(tmp);
07709 if (!here) {
07710 if (chan_sig != SIG_PRI)
07711
07712 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07713 }
07714 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
07715 #ifdef HAVE_PRI
07716
07717 if (tmp->pri && !pri_is_up(tmp->pri)) {
07718 tmp->inalarm = 1;
07719 }
07720 #endif
07721 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
07722 tmp->inalarm = 1;
07723 handle_alarms(tmp, res);
07724 } else {
07725
07726
07727
07728
07729
07730
07731
07732
07733
07734
07735 tmp->unknown_alarm = 1;
07736 }
07737 }
07738
07739 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07740 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07741 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07742 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07743
07744 }
07745 if (tmp && !here) {
07746
07747 if (!*wlist) {
07748 *wlist = tmp;
07749 tmp->prev = NULL;
07750 tmp->next = NULL;
07751 *wend = tmp;
07752 } else {
07753
07754 struct dahdi_pvt *working = *wlist;
07755
07756
07757 if (working->channel > tmp->channel) {
07758 tmp->next = *wlist;
07759 tmp->prev = NULL;
07760 (*wlist)->prev = tmp;
07761 *wlist = tmp;
07762 } else {
07763
07764 while (working) {
07765
07766 if (working->next) {
07767 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07768 tmp->next = working->next;
07769 tmp->prev = working;
07770 working->next->prev = tmp;
07771 working->next = tmp;
07772 break;
07773 }
07774 } else {
07775
07776 if (working->channel < tmp->channel) {
07777 working->next = tmp;
07778 tmp->next = NULL;
07779 tmp->prev = working;
07780 *wend = tmp;
07781 break;
07782 }
07783 }
07784 working = working->next;
07785 }
07786 }
07787 }
07788 }
07789 return tmp;
07790 }
07791
07792 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
07793 {
07794 int res;
07795 struct dahdi_params par;
07796
07797
07798 if (groupmatch) {
07799 if ((p->group & groupmatch) != groupmatch)
07800 return 0;
07801 *groupmatched = 1;
07802 }
07803
07804 if (channelmatch != -1) {
07805 if (p->channel != channelmatch)
07806 return 0;
07807 *channelmatched = 1;
07808 }
07809
07810 if (busy) {
07811 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07812 *busy = 1;
07813 }
07814
07815 if (p->dnd)
07816 return 0;
07817
07818 if (p->guardtime && (time(NULL) < p->guardtime))
07819 return 0;
07820
07821
07822 if (!p->owner) {
07823 #ifdef HAVE_PRI
07824
07825 if (p->pri) {
07826 if (p->resetting || p->call)
07827 return 0;
07828 else
07829 return 1;
07830 }
07831 #endif
07832 if (!(p->radio || (p->oprmode < 0)))
07833 {
07834 if (!p->sig || (p->sig == SIG_FXSLS))
07835 return 1;
07836
07837 if (p->subs[SUB_REAL].dfd > -1)
07838 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
07839 else {
07840
07841 res = 0;
07842 par.rxisoffhook = 0;
07843 }
07844 if (res) {
07845 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
07846 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07847
07848
07849
07850 if (par.rxbits > -1)
07851 return 1;
07852 if (par.rxisoffhook)
07853 return 1;
07854 else
07855 #ifdef DAHDI_CHECK_HOOKSTATE
07856 return 0;
07857 #else
07858 return 1;
07859 #endif
07860 } else if (par.rxisoffhook) {
07861 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07862
07863 return 0;
07864 }
07865 }
07866 return 1;
07867 }
07868
07869
07870 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
07871 return 0;
07872
07873 if (!p->callwaiting) {
07874
07875 return 0;
07876 }
07877
07878 if (p->subs[SUB_CALLWAIT].dfd > -1) {
07879
07880 return 0;
07881 }
07882
07883 if ((p->owner->_state != AST_STATE_UP) &&
07884 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07885
07886 return 0;
07887 }
07888 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07889
07890 return 0;
07891 }
07892
07893 return 1;
07894 }
07895
07896 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
07897 {
07898 struct dahdi_pvt *p;
07899 struct dahdi_bufferinfo bi;
07900 int res;
07901
07902 if ((p = ast_malloc(sizeof(*p)))) {
07903 memcpy(p, src, sizeof(struct dahdi_pvt));
07904 ast_mutex_init(&p->lock);
07905 #ifdef HAVE_ZAPTEL
07906 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
07907 #else
07908 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
07909 #endif
07910
07911 if (p->subs[SUB_REAL].dfd < 0) {
07912 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
07913 destroy_dahdi_pvt(&p);
07914 return NULL;
07915 }
07916 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07917 if (!res) {
07918 bi.txbufpolicy = p->buf_policy;
07919 bi.rxbufpolicy = p->buf_policy;
07920 bi.numbufs = p->buf_no;
07921 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07922 if (res < 0) {
07923 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
07924 }
07925 } else
07926 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
07927 }
07928 p->destroy = 1;
07929 p->next = iflist;
07930 p->prev = NULL;
07931 iflist = p;
07932 if (iflist->next)
07933 iflist->next->prev = p;
07934 return p;
07935 }
07936
07937
07938 #ifdef HAVE_PRI
07939 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
07940 {
07941 int x;
07942 if (backwards)
07943 x = pri->numchans;
07944 else
07945 x = 0;
07946 for (;;) {
07947 if (backwards && (x < 0))
07948 break;
07949 if (!backwards && (x >= pri->numchans))
07950 break;
07951 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
07952 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
07953 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
07954 return x;
07955 }
07956 if (backwards)
07957 x--;
07958 else
07959 x++;
07960 }
07961 return -1;
07962 }
07963 #endif
07964
07965 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
07966 {
07967 ast_group_t groupmatch = 0;
07968 int channelmatch = -1;
07969 int roundrobin = 0;
07970 int callwait = 0;
07971 int busy = 0;
07972 struct dahdi_pvt *p;
07973 struct ast_channel *tmp = NULL;
07974 char *dest=NULL;
07975 int x;
07976 char *s;
07977 char opt=0;
07978 int res=0, y=0;
07979 int backwards = 0;
07980 #ifdef HAVE_PRI
07981 int crv;
07982 int bearer = -1;
07983 int trunkgroup;
07984 struct dahdi_pri *pri=NULL;
07985 #endif
07986 struct dahdi_pvt *exit, *start, *end;
07987 ast_mutex_t *lock;
07988 int channelmatched = 0;
07989 int groupmatched = 0;
07990
07991
07992 lock = &iflock;
07993 start = iflist;
07994 end = ifend;
07995 if (data) {
07996 dest = ast_strdupa((char *)data);
07997 } else {
07998 ast_log(LOG_WARNING, "Channel requested with no data\n");
07999 return NULL;
08000 }
08001 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08002
08003 char *stringp=NULL;
08004 stringp=dest + 1;
08005 s = strsep(&stringp, "/");
08006 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08007 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08008 return NULL;
08009 }
08010 groupmatch = ((ast_group_t) 1 << x);
08011 if (toupper(dest[0]) == 'G') {
08012 if (dest[0] == 'G') {
08013 backwards = 1;
08014 p = ifend;
08015 } else
08016 p = iflist;
08017 } else {
08018 if (dest[0] == 'R') {
08019 backwards = 1;
08020 p = round_robin[x]?round_robin[x]->prev:ifend;
08021 if (!p)
08022 p = ifend;
08023 } else {
08024 p = round_robin[x]?round_robin[x]->next:iflist;
08025 if (!p)
08026 p = iflist;
08027 }
08028 roundrobin = 1;
08029 }
08030 } else {
08031 char *stringp=NULL;
08032 stringp=dest;
08033 s = strsep(&stringp, "/");
08034 p = iflist;
08035 if (!strcasecmp(s, "pseudo")) {
08036
08037 x = CHAN_PSEUDO;
08038 channelmatch = x;
08039 }
08040 #ifdef HAVE_PRI
08041 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08042 if ((trunkgroup < 1) || (crv < 1)) {
08043 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08044 return NULL;
08045 }
08046 res--;
08047 for (x = 0; x < NUM_SPANS; x++) {
08048 if (pris[x].trunkgroup == trunkgroup) {
08049 pri = pris + x;
08050 lock = &pri->lock;
08051 start = pri->crvs;
08052 end = pri->crvend;
08053 break;
08054 }
08055 }
08056 if (!pri) {
08057 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08058 return NULL;
08059 }
08060 channelmatch = crv;
08061 p = pris[x].crvs;
08062 }
08063 #endif
08064 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08065 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08066 return NULL;
08067 } else {
08068 channelmatch = x;
08069 }
08070 }
08071
08072 ast_mutex_lock(lock);
08073 exit = p;
08074 while (p && !tmp) {
08075 if (roundrobin)
08076 round_robin[x] = p;
08077 #if 0
08078 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08079 #endif
08080
08081 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08082 if (option_debug)
08083 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08084 if (p->inalarm)
08085 goto next;
08086
08087 callwait = (p->owner != NULL);
08088 #ifdef HAVE_PRI
08089 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08090 if (p->sig != SIG_FXSKS) {
08091
08092
08093 bearer = pri_find_empty_chan(pri, 0);
08094 if (bearer < 0) {
08095 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08096 p = NULL;
08097 break;
08098 }
08099 pri_assign_bearer(p, pri, pri->pvts[bearer]);
08100 } else {
08101 if (alloc_sub(p, 0)) {
08102 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08103 p = NULL;
08104 break;
08105 } else
08106 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08107 p->pri = pri;
08108 }
08109 }
08110 #endif
08111 if (p->channel == CHAN_PSEUDO) {
08112 p = chandup(p);
08113 if (!p) {
08114 break;
08115 }
08116 }
08117 if (p->owner) {
08118 if (alloc_sub(p, SUB_CALLWAIT)) {
08119 p = NULL;
08120 break;
08121 }
08122 }
08123 p->outgoing = 1;
08124 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08125 #ifdef HAVE_PRI
08126 if (p->bearer) {
08127
08128 p->bearer->owner = tmp;
08129 }
08130 #endif
08131
08132 if (res > 1) {
08133 if (opt == 'c') {
08134
08135 p->confirmanswer = 1;
08136 } else if (opt == 'r') {
08137
08138 if (res < 3)
08139 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08140 else
08141 p->distinctivering = y;
08142 } else if (opt == 'd') {
08143
08144 p->digital = 1;
08145 if (tmp)
08146 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08147 } else {
08148 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08149 }
08150 }
08151
08152 if (tmp && callwait)
08153 tmp->cdrflags |= AST_CDR_CALLWAIT;
08154 break;
08155 }
08156 next:
08157 if (backwards) {
08158 p = p->prev;
08159 if (!p)
08160 p = end;
08161 } else {
08162 p = p->next;
08163 if (!p)
08164 p = start;
08165 }
08166
08167 if (p == exit)
08168 break;
08169 }
08170 ast_mutex_unlock(lock);
08171 restart_monitor();
08172 if (callwait)
08173 *cause = AST_CAUSE_BUSY;
08174 else if (!tmp) {
08175 if (channelmatched) {
08176 if (busy)
08177 *cause = AST_CAUSE_BUSY;
08178 } else if (groupmatched) {
08179 *cause = AST_CAUSE_CONGESTION;
08180 }
08181 }
08182
08183 return tmp;
08184 }
08185
08186
08187 #ifdef HAVE_PRI
08188 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08189 {
08190 struct dahdi_pvt *p;
08191 p = pri->crvs;
08192 while (p) {
08193 if (p->channel == crv)
08194 return p;
08195 p = p->next;
08196 }
08197 return NULL;
08198 }
08199
08200
08201 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08202 {
08203 int x;
08204 int span = PRI_SPAN(channel);
08205 int spanfd;
08206 struct dahdi_params param;
08207 int principle = -1;
08208 int explicit = PRI_EXPLICIT(channel);
08209 channel = PRI_CHANNEL(channel);
08210
08211 if (!explicit) {
08212 spanfd = pri_active_dchan_fd(pri);
08213 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
08214 return -1;
08215 span = pris[param.spanno - 1].prilogicalspan;
08216 }
08217
08218 for (x = 0; x < pri->numchans; x++) {
08219 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08220 principle = x;
08221 break;
08222 }
08223 }
08224
08225 return principle;
08226 }
08227
08228 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08229 {
08230 int x;
08231 struct dahdi_pvt *crv;
08232 if (!c) {
08233 if (principle < 0)
08234 return -1;
08235 return principle;
08236 }
08237 if ((principle > -1) &&
08238 (principle < pri->numchans) &&
08239 (pri->pvts[principle]) &&
08240 (pri->pvts[principle]->call == c))
08241 return principle;
08242
08243 for (x = 0; x < pri->numchans; x++) {
08244 if (!pri->pvts[x])
08245 continue;
08246 if (pri->pvts[x]->call == c) {
08247
08248 if (principle != x) {
08249 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08250
08251 if (option_verbose > 2)
08252 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08253 old->channel, new->channel);
08254 if (new->owner) {
08255 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08256 old->channel, new->channel, new->channel);
08257 return -1;
08258 }
08259
08260 new->owner = old->owner;
08261 old->owner = NULL;
08262 if (new->owner) {
08263 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08264 new->owner->tech_pvt = new;
08265 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08266 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08267 old->subs[SUB_REAL].owner = NULL;
08268 } else
08269 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);
08270 new->call = old->call;
08271 old->call = NULL;
08272
08273
08274 new->dsp = old->dsp;
08275 new->dsp_features = old->dsp_features;
08276 old->dsp = NULL;
08277 old->dsp_features = 0;
08278 }
08279 return principle;
08280 }
08281 }
08282
08283 crv = pri->crvs;
08284 while (crv) {
08285 if (crv->call == c) {
08286
08287 if (crv->bearer)
08288 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08289 else if (pri->pvts[principle]->owner)
08290 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08291 else {
08292
08293
08294 dahdi_close_sub(crv, SUB_REAL);
08295 pri->pvts[principle]->call = crv->call;
08296 pri_assign_bearer(crv, pri, pri->pvts[principle]);
08297 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08298 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08299 pri->trunkgroup, crv->channel);
08300 wakeup_sub(crv, SUB_REAL, pri);
08301 }
08302 return principle;
08303 }
08304 crv = crv->next;
08305 }
08306 ast_log(LOG_WARNING, "Call specified, but not found?\n");
08307 return -1;
08308 }
08309
08310 static void *do_idle_thread(void *vchan)
08311 {
08312 struct ast_channel *chan = vchan;
08313 struct dahdi_pvt *pvt = chan->tech_pvt;
08314 struct ast_frame *f;
08315 char ex[80];
08316
08317 int newms, ms = 30000;
08318 if (option_verbose > 2)
08319 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08320 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08321 if (ast_call(chan, ex, 0)) {
08322 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08323 ast_hangup(chan);
08324 return NULL;
08325 }
08326 while ((newms = ast_waitfor(chan, ms)) > 0) {
08327 f = ast_read(chan);
08328 if (!f) {
08329
08330 break;
08331 }
08332 if (f->frametype == AST_FRAME_CONTROL) {
08333 switch (f->subclass) {
08334 case AST_CONTROL_ANSWER:
08335
08336 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08337 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08338 chan->priority = 1;
08339 if (option_verbose > 3)
08340 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08341 ast_pbx_run(chan);
08342
08343 return NULL;
08344 case AST_CONTROL_BUSY:
08345 if (option_verbose > 3)
08346 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08347 break;
08348 case AST_CONTROL_CONGESTION:
08349 if (option_verbose > 3)
08350 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08351 break;
08352 };
08353 }
08354 ast_frfree(f);
08355 ms = newms;
08356 }
08357
08358 ast_hangup(chan);
08359 return NULL;
08360 }
08361
08362 #ifndef PRI_RESTART
08363 #error "Upgrade your libpri"
08364 #endif
08365 static void dahdi_pri_message(struct pri *pri, char *s)
08366 {
08367 int x, y;
08368 int dchan = -1, span = -1;
08369 int dchancount = 0;
08370
08371 if (pri) {
08372 for (x = 0; x < NUM_SPANS; x++) {
08373 for (y = 0; y < NUM_DCHANS; y++) {
08374 if (pris[x].dchans[y])
08375 dchancount++;
08376
08377 if (pris[x].dchans[y] == pri)
08378 dchan = y;
08379 }
08380 if (dchan >= 0) {
08381 span = x;
08382 break;
08383 }
08384 dchancount = 0;
08385 }
08386 if ((dchan >= 0) && (span >= 0)) {
08387 if (dchancount > 1)
08388 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08389 else
08390 ast_verbose("%s", s);
08391 } else
08392 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08393 } else
08394 ast_verbose("%s", s);
08395
08396 ast_mutex_lock(&pridebugfdlock);
08397
08398 if (pridebugfd >= 0)
08399 write(pridebugfd, s, strlen(s));
08400
08401 ast_mutex_unlock(&pridebugfdlock);
08402 }
08403
08404 static void dahdi_pri_error(struct pri *pri, char *s)
08405 {
08406 int x, y;
08407 int dchan = -1, span = -1;
08408 int dchancount = 0;
08409
08410 if (pri) {
08411 for (x = 0; x < NUM_SPANS; x++) {
08412 for (y = 0; y < NUM_DCHANS; y++) {
08413 if (pris[x].dchans[y])
08414 dchancount++;
08415
08416 if (pris[x].dchans[y] == pri)
08417 dchan = y;
08418 }
08419 if (dchan >= 0) {
08420 span = x;
08421 break;
08422 }
08423 dchancount = 0;
08424 }
08425 if ((dchan >= 0) && (span >= 0)) {
08426 if (dchancount > 1)
08427 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08428 else
08429 ast_log(LOG_ERROR, "%s", s);
08430 } else
08431 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08432 } else
08433 ast_log(LOG_ERROR, "%s", s);
08434
08435 ast_mutex_lock(&pridebugfdlock);
08436
08437 if (pridebugfd >= 0)
08438 write(pridebugfd, s, strlen(s));
08439
08440 ast_mutex_unlock(&pridebugfdlock);
08441 }
08442
08443 static int pri_check_restart(struct dahdi_pri *pri)
08444 {
08445 do {
08446 pri->resetpos++;
08447 } while ((pri->resetpos < pri->numchans) &&
08448 (!pri->pvts[pri->resetpos] ||
08449 pri->pvts[pri->resetpos]->call ||
08450 pri->pvts[pri->resetpos]->resetting));
08451 if (pri->resetpos < pri->numchans) {
08452
08453 pri->pvts[pri->resetpos]->resetting = 1;
08454 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08455 } else {
08456 pri->resetting = 0;
08457 time(&pri->lastreset);
08458 }
08459 return 0;
08460 }
08461
08462 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08463 {
08464 int x;
08465 int redo;
08466 ast_mutex_unlock(&pri->lock);
08467 ast_mutex_lock(&p->lock);
08468 do {
08469 redo = 0;
08470 for (x = 0; x < 3; x++) {
08471 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08472 redo++;
08473 DEADLOCK_AVOIDANCE(&p->lock);
08474 }
08475 if (p->subs[x].owner) {
08476 ast_queue_hangup(p->subs[x].owner);
08477 ast_mutex_unlock(&p->subs[x].owner->lock);
08478 }
08479 }
08480 } while (redo);
08481 ast_mutex_unlock(&p->lock);
08482 ast_mutex_lock(&pri->lock);
08483 return 0;
08484 }
08485
08486 static char * redirectingreason2str(int redirectingreason)
08487 {
08488 switch (redirectingreason) {
08489 case 0:
08490 return "UNKNOWN";
08491 case 1:
08492 return "BUSY";
08493 case 2:
08494 return "NO_REPLY";
08495 case 0xF:
08496 return "UNCONDITIONAL";
08497 default:
08498 return "NOREDIRECT";
08499 }
08500 }
08501
08502 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08503 {
08504 switch (plan) {
08505 case PRI_INTERNATIONAL_ISDN:
08506 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08507 break;
08508 case PRI_NATIONAL_ISDN:
08509 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08510 break;
08511 case PRI_LOCAL_ISDN:
08512 snprintf(buf, size, "%s%s", pri->localprefix, number);
08513 break;
08514 case PRI_PRIVATE:
08515 snprintf(buf, size, "%s%s", pri->privateprefix, number);
08516 break;
08517 case PRI_UNKNOWN:
08518 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08519 break;
08520 default:
08521 snprintf(buf, size, "%s", number);
08522 break;
08523 }
08524 }
08525
08526 static int dahdi_setlaw(int dfd, int law)
08527 {
08528 int res;
08529 res = ioctl(dfd, DAHDI_SETLAW, &law);
08530 if (res)
08531 return res;
08532 return 0;
08533 }
08534
08535 static void *pri_dchannel(void *vpri)
08536 {
08537 struct dahdi_pri *pri = vpri;
08538 pri_event *e;
08539 struct pollfd fds[NUM_DCHANS];
08540 int res;
08541 int chanpos = 0;
08542 int x;
08543 int haveidles;
08544 int activeidles;
08545 int nextidle = -1;
08546 struct ast_channel *c;
08547 struct timeval tv, lowest, *next;
08548 struct timeval lastidle = { 0, 0 };
08549 int doidling=0;
08550 char *cc;
08551 char idlen[80];
08552 struct ast_channel *idle;
08553 pthread_t p;
08554 time_t t;
08555 int i, which=-1;
08556 int numdchans;
08557 int cause=0;
08558 struct dahdi_pvt *crv;
08559 pthread_t threadid;
08560 pthread_attr_t attr;
08561 char ani2str[6];
08562 char plancallingnum[256];
08563 char plancallingani[256];
08564 char calledtonstr[10];
08565
08566 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08567
08568 gettimeofday(&lastidle, NULL);
08569 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08570
08571 cc = strchr(pri->idleext, '@');
08572 if (cc) {
08573 *cc = '\0';
08574 cc++;
08575 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08576 #if 0
08577
08578 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08579 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08580 else
08581 #endif
08582 doidling = 1;
08583 } else
08584 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08585 }
08586 for (;;) {
08587 for (i = 0; i < NUM_DCHANS; i++) {
08588 if (!pri->dchannels[i])
08589 break;
08590 fds[i].fd = pri->fds[i];
08591 fds[i].events = POLLIN | POLLPRI;
08592 fds[i].revents = 0;
08593 }
08594 numdchans = i;
08595 time(&t);
08596 ast_mutex_lock(&pri->lock);
08597 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08598 if (pri->resetting && pri_is_up(pri)) {
08599 if (pri->resetpos < 0)
08600 pri_check_restart(pri);
08601 } else {
08602 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
08603 pri->resetting = 1;
08604 pri->resetpos = -1;
08605 }
08606 }
08607 }
08608
08609 if (doidling && pri_is_up(pri)) {
08610 nextidle = -1;
08611 haveidles = 0;
08612 activeidles = 0;
08613 for (x = pri->numchans; x >= 0; x--) {
08614 if (pri->pvts[x] && !pri->pvts[x]->owner &&
08615 !pri->pvts[x]->call) {
08616 if (haveidles < pri->minunused) {
08617 haveidles++;
08618 } else if (!pri->pvts[x]->resetting) {
08619 nextidle = x;
08620 break;
08621 }
08622 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08623 activeidles++;
08624 }
08625 if (nextidle > -1) {
08626 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08627
08628 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08629 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08630 if (idle) {
08631 pri->pvts[nextidle]->isidlecall = 1;
08632 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08633 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08634 dahdi_hangup(idle);
08635 }
08636 } else
08637 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08638 gettimeofday(&lastidle, NULL);
08639 }
08640 } else if ((haveidles < pri->minunused) &&
08641 (activeidles > pri->minidle)) {
08642
08643
08644 for (x = pri->numchans; x >= 0; x--) {
08645
08646 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08647 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08648 haveidles++;
08649
08650
08651 if ((haveidles >= pri->minunused) ||
08652 (activeidles <= pri->minidle))
08653 break;
08654 }
08655 }
08656 }
08657 }
08658
08659 lowest = ast_tv(60, 0);
08660 for (i = 0; i < NUM_DCHANS; i++) {
08661
08662 if (!pri->dchannels[i])
08663 break;
08664 if ((next = pri_schedule_next(pri->dchans[i]))) {
08665
08666 tv = ast_tvsub(*next, ast_tvnow());
08667 if (tv.tv_sec < 0) {
08668 tv = ast_tv(0,0);
08669 }
08670 if (doidling || pri->resetting) {
08671 if (tv.tv_sec > 1) {
08672 tv = ast_tv(1, 0);
08673 }
08674 } else {
08675 if (tv.tv_sec > 60) {
08676 tv = ast_tv(60, 0);
08677 }
08678 }
08679 } else if (doidling || pri->resetting) {
08680
08681
08682 tv = ast_tv(1,0);
08683 } else {
08684
08685 tv = ast_tv(60, 0);
08686 }
08687 if (!i || ast_tvcmp(tv, lowest) < 0) {
08688 lowest = tv;
08689 }
08690 }
08691 ast_mutex_unlock(&pri->lock);
08692
08693 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08694 pthread_testcancel();
08695 e = NULL;
08696 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
08697 pthread_testcancel();
08698 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08699
08700 ast_mutex_lock(&pri->lock);
08701 if (!res) {
08702 for (which = 0; which < NUM_DCHANS; which++) {
08703 if (!pri->dchans[which])
08704 break;
08705
08706 e = pri_schedule_run(pri->dchans[which]);
08707 if (e)
08708 break;
08709 }
08710 } else if (res > -1) {
08711 for (which = 0; which < NUM_DCHANS; which++) {
08712 if (!pri->dchans[which])
08713 break;
08714 if (fds[which].revents & POLLPRI) {
08715
08716 x = 0;
08717 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
08718 if (x)
08719 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);
08720
08721 if (x == DAHDI_EVENT_ALARM) {
08722 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
08723 pri_find_dchan(pri);
08724 } else if (x == DAHDI_EVENT_NOALARM) {
08725 pri->dchanavail[which] |= DCHAN_NOTINALARM;
08726 pri_restart(pri->dchans[which]);
08727 }
08728
08729 if (option_debug)
08730 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
08731 } else if (fds[which].revents & POLLIN) {
08732 e = pri_check_event(pri->dchans[which]);
08733 }
08734 if (e)
08735 break;
08736 }
08737 } else if (errno != EINTR)
08738 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
08739
08740 if (e) {
08741 if (pri->debug)
08742 pri_dump_event(pri->dchans[which], e);
08743
08744 if (e->e != PRI_EVENT_DCHAN_DOWN) {
08745 if (!(pri->dchanavail[which] & DCHAN_UP)) {
08746 if (option_verbose > 1)
08747 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
08748 }
08749 pri->dchanavail[which] |= DCHAN_UP;
08750 } else {
08751 if (pri->dchanavail[which] & DCHAN_UP) {
08752 if (option_verbose > 1)
08753 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
08754 }
08755 pri->dchanavail[which] &= ~DCHAN_UP;
08756 }
08757
08758 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
08759
08760 pri->pri = pri->dchans[which];
08761
08762 switch (e->e) {
08763 case PRI_EVENT_DCHAN_UP:
08764 if (!pri->pri) pri_find_dchan(pri);
08765
08766
08767 time(&pri->lastreset);
08768
08769
08770 if (pri->resetinterval > -1) {
08771 pri->lastreset -= pri->resetinterval;
08772 pri->lastreset += 5;
08773 }
08774 pri->resetting = 0;
08775
08776 for (i = 0; i < pri->numchans; i++)
08777 if (pri->pvts[i]) {
08778 pri->pvts[i]->inalarm = 0;
08779 }
08780 break;
08781 case PRI_EVENT_DCHAN_DOWN:
08782 pri_find_dchan(pri);
08783 if (!pri_is_up(pri)) {
08784 pri->resetting = 0;
08785
08786 for (i = 0; i < pri->numchans; i++) {
08787 struct dahdi_pvt *p = pri->pvts[i];
08788 if (p) {
08789 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08790
08791 if (p->call) {
08792 if (p->pri && p->pri->pri) {
08793 pri_hangup(p->pri->pri, p->call, -1);
08794 pri_destroycall(p->pri->pri, p->call);
08795 p->call = NULL;
08796 } else
08797 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
08798 }
08799 if (p->realcall) {
08800 pri_hangup_all(p->realcall, pri);
08801 } else if (p->owner)
08802 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08803 }
08804 p->inalarm = 1;
08805 }
08806 }
08807 }
08808 break;
08809 case PRI_EVENT_RESTART:
08810 if (e->restart.channel > -1) {
08811 chanpos = pri_find_principle(pri, e->restart.channel);
08812 if (chanpos < 0)
08813 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
08814 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08815 else {
08816 if (option_verbose > 2)
08817 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
08818 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08819 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08820 if (pri->pvts[chanpos]->call) {
08821 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
08822 pri->pvts[chanpos]->call = NULL;
08823 }
08824
08825 if (pri->pvts[chanpos]->realcall)
08826 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08827 else if (pri->pvts[chanpos]->owner)
08828 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08829 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08830 }
08831 } else {
08832 if (option_verbose > 2)
08833 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
08834 for (x = 0; x < pri->numchans; x++)
08835 if (pri->pvts[x]) {
08836 ast_mutex_lock(&pri->pvts[x]->lock);
08837 if (pri->pvts[x]->call) {
08838 pri_destroycall(pri->pri, pri->pvts[x]->call);
08839 pri->pvts[x]->call = NULL;
08840 }
08841 if (pri->pvts[chanpos]->realcall)
08842 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08843 else if (pri->pvts[x]->owner)
08844 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08845 ast_mutex_unlock(&pri->pvts[x]->lock);
08846 }
08847 }
08848 break;
08849 case PRI_EVENT_KEYPAD_DIGIT:
08850 chanpos = pri_find_principle(pri, e->digit.channel);
08851 if (chanpos < 0) {
08852 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
08853 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
08854 } else {
08855 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
08856 if (chanpos > -1) {
08857 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08858
08859 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
08860
08861 int digitlen = strlen(e->digit.digits);
08862 char digit;
08863 int i;
08864 for (i = 0; i < digitlen; i++) {
08865 digit = e->digit.digits[i];
08866 {
08867 struct ast_frame f = { AST_FRAME_DTMF, digit, };
08868 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08869 }
08870 }
08871 }
08872 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08873 }
08874 }
08875 break;
08876
08877 case PRI_EVENT_INFO_RECEIVED:
08878 chanpos = pri_find_principle(pri, e->ring.channel);
08879 if (chanpos < 0) {
08880 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
08881 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08882 } else {
08883 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
08884 if (chanpos > -1) {
08885 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08886
08887 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
08888
08889 int digitlen = strlen(e->ring.callednum);
08890 char digit;
08891 int i;
08892 for (i = 0; i < digitlen; i++) {
08893 digit = e->ring.callednum[i];
08894 {
08895 struct ast_frame f = { AST_FRAME_DTMF, digit, };
08896 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08897 }
08898 }
08899 }
08900 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08901 }
08902 }
08903 break;
08904 case PRI_EVENT_RING:
08905 crv = NULL;
08906 if (e->ring.channel == -1)
08907 chanpos = pri_find_empty_chan(pri, 1);
08908 else
08909 chanpos = pri_find_principle(pri, e->ring.channel);
08910
08911 if (chanpos < 0) {
08912 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
08913 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08914 } else {
08915 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08916 if (pri->pvts[chanpos]->owner) {
08917 if (pri->pvts[chanpos]->call == e->ring.call) {
08918 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
08919 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08920 break;
08921 } else {
08922
08923 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
08924 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08925 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08926 chanpos = -1;
08927 }
08928 }
08929 if (chanpos > -1)
08930 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08931 }
08932 if ((chanpos < 0) && (e->ring.flexible))
08933 chanpos = pri_find_empty_chan(pri, 1);
08934 if (chanpos > -1) {
08935 ast_mutex_lock(&pri->pvts[chanpos]->lock);
08936 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
08937
08938 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
08939 if (crv)
08940 ast_mutex_lock(&crv->lock);
08941 if (!crv || crv->owner) {
08942 pri->pvts[chanpos]->call = NULL;
08943 if (crv) {
08944 if (crv->owner)
08945 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08946 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);
08947 } else
08948 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);
08949 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
08950 if (crv)
08951 ast_mutex_unlock(&crv->lock);
08952 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08953 break;
08954 }
08955 }
08956 pri->pvts[chanpos]->call = e->ring.call;
08957 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
08958 if (pri->pvts[chanpos]->use_callerid) {
08959 ast_shrink_phone_number(plancallingnum);
08960 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
08961 #ifdef PRI_ANI
08962 if (!ast_strlen_zero(e->ring.callingani)) {
08963 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
08964 ast_shrink_phone_number(plancallingani);
08965 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
08966 } else {
08967 pri->pvts[chanpos]->cid_ani[0] = '\0';
08968 }
08969 #endif
08970 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
08971 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
08972 } else {
08973 pri->pvts[chanpos]->cid_num[0] = '\0';
08974 pri->pvts[chanpos]->cid_ani[0] = '\0';
08975 pri->pvts[chanpos]->cid_name[0] = '\0';
08976 pri->pvts[chanpos]->cid_ton = 0;
08977 }
08978 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
08979 e->ring.redirectingnum, e->ring.callingplanrdnis);
08980
08981 if (pri->pvts[chanpos]->immediate) {
08982 if (option_verbose > 2)
08983 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
08984 pri->pvts[chanpos]->exten[0] = 's';
08985 pri->pvts[chanpos]->exten[1] = '\0';
08986 }
08987
08988 else if (!ast_strlen_zero(e->ring.callednum)) {
08989 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
08990 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
08991 } else if (pri->overlapdial)
08992 pri->pvts[chanpos]->exten[0] = '\0';
08993 else {
08994
08995 pri->pvts[chanpos]->exten[0] = 's';
08996 pri->pvts[chanpos]->exten[1] = '\0';
08997 }
08998
08999 if (!ast_strlen_zero(e->ring.callednum))
09000 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09001
09002 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09003 if (option_verbose > 2)
09004 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09005 pri->pvts[chanpos]->exten[0] = 's';
09006 pri->pvts[chanpos]->exten[1] = '\0';
09007 }
09008
09009 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09010 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09011
09012 int law;
09013 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09014
09015 law = 1;
09016 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09017 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09018 }
09019 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09020 law = DAHDI_LAW_ALAW;
09021 else
09022 law = DAHDI_LAW_MULAW;
09023 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09024 if (res < 0)
09025 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09026 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09027 if (res < 0)
09028 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09029 if (e->ring.complete || !pri->overlapdial) {
09030
09031 pri->pvts[chanpos]->proceeding = 1;
09032 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09033 } else {
09034 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
09035 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09036 else
09037 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09038 }
09039
09040 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09041
09042
09043 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09044
09045 ast_mutex_unlock(&pri->lock);
09046 if (crv) {
09047
09048 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09049 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09050 pri->pvts[chanpos]->owner = &inuse;
09051 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09052 } else {
09053 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09054 }
09055
09056 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09057
09058 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09059 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09060 }
09061 if (e->ring.ani2 >= 0) {
09062 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09063 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09064 }
09065
09066 #ifdef SUPPORT_USERUSER
09067 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09068 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09069 }
09070 #endif
09071
09072 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09073 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09074 if (e->ring.redirectingreason >= 0)
09075 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09076
09077 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09078 ast_mutex_lock(&pri->lock);
09079
09080 pthread_attr_init(&attr);
09081 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09082 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09083 if (option_verbose > 2)
09084 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09085 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09086 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09087 } else {
09088 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09089 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09090 if (c)
09091 ast_hangup(c);
09092 else {
09093 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09094 pri->pvts[chanpos]->call = NULL;
09095 }
09096 }
09097 pthread_attr_destroy(&attr);
09098 } else {
09099 ast_mutex_unlock(&pri->lock);
09100
09101 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09102 if (c) {
09103 char calledtonstr[10];
09104
09105 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09106
09107 if (e->ring.ani2 >= 0) {
09108 snprintf(ani2str, 5, "%d", e->ring.ani2);
09109 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09110 }
09111
09112 #ifdef SUPPORT_USERUSER
09113 if (!ast_strlen_zero(e->ring.useruserinfo)) {
09114 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09115 }
09116 #endif
09117
09118 if (e->ring.redirectingreason >= 0)
09119 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09120
09121 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09122 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09123
09124 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09125 ast_mutex_lock(&pri->lock);
09126
09127 if (option_verbose > 2)
09128 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09129 plancallingnum, pri->pvts[chanpos]->exten,
09130 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09131 dahdi_enable_ec(pri->pvts[chanpos]);
09132 } else {
09133
09134 ast_mutex_lock(&pri->lock);
09135
09136 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
09137 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09138 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09139 pri->pvts[chanpos]->call = NULL;
09140 }
09141 }
09142 } else {
09143 if (option_verbose > 2)
09144 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
09145 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
09146 pri->pvts[chanpos]->prioffset, pri->span);
09147 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09148 pri->pvts[chanpos]->call = NULL;
09149 pri->pvts[chanpos]->exten[0] = '\0';
09150 }
09151 if (crv)
09152 ast_mutex_unlock(&crv->lock);
09153 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09154 } else {
09155 if (e->ring.flexible)
09156 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09157 else
09158 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09159 }
09160 break;
09161 case PRI_EVENT_RINGING:
09162 chanpos = pri_find_principle(pri, e->ringing.channel);
09163 if (chanpos < 0) {
09164 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
09165 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09166 } else {
09167 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09168 if (chanpos < 0) {
09169 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
09170 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09171 } else {
09172 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09173 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09174 dahdi_enable_ec(pri->pvts[chanpos]);
09175 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09176 pri->pvts[chanpos]->alerting = 1;
09177 } else
09178 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09179 #ifdef PRI_PROGRESS_MASK
09180 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09181 #else
09182 if (e->ringing.progress == 8) {
09183 #endif
09184
09185 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09186
09187 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09188 pri->pvts[chanpos]->dsp_features = 0;
09189 }
09190 }
09191
09192 #ifdef SUPPORT_USERUSER
09193 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09194 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09195 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09196 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09197 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09198 }
09199 #endif
09200
09201 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09202 }
09203 }
09204 break;
09205 case PRI_EVENT_PROGRESS:
09206
09207 chanpos = pri_find_principle(pri, e->proceeding.channel);
09208 if (chanpos > -1) {
09209 #ifdef PRI_PROGRESS_MASK
09210 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09211 #else
09212 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09213 #endif
09214 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09215
09216 if (e->proceeding.cause > -1) {
09217 if (option_verbose > 2)
09218 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09219
09220
09221 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09222 if (pri->pvts[chanpos]->owner) {
09223 if (option_verbose > 2)
09224 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09225
09226 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09227 f.subclass = AST_CONTROL_BUSY;
09228 }
09229 }
09230 }
09231
09232 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09233 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09234 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09235 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09236 #ifdef PRI_PROGRESS_MASK
09237 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09238 #else
09239 if (e->proceeding.progress == 8) {
09240 #endif
09241
09242 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09243 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09244 pri->pvts[chanpos]->dsp_features = 0;
09245 }
09246 }
09247 pri->pvts[chanpos]->progress = 1;
09248 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09249 }
09250 }
09251 break;
09252 case PRI_EVENT_PROCEEDING:
09253 chanpos = pri_find_principle(pri, e->proceeding.channel);
09254 if (chanpos > -1) {
09255 if (!pri->pvts[chanpos]->proceeding) {
09256 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09257
09258 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09259 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09260 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09261 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09262 #ifdef PRI_PROGRESS_MASK
09263 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09264 #else
09265 if (e->proceeding.progress == 8) {
09266 #endif
09267
09268 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09269 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09270 pri->pvts[chanpos]->dsp_features = 0;
09271 }
09272
09273 f.subclass = AST_CONTROL_PROGRESS;
09274 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09275 }
09276 pri->pvts[chanpos]->proceeding = 1;
09277 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09278 }
09279 }
09280 break;
09281 case PRI_EVENT_FACNAME:
09282 chanpos = pri_find_principle(pri, e->facname.channel);
09283 if (chanpos < 0) {
09284 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
09285 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09286 } else {
09287 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09288 if (chanpos < 0) {
09289 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
09290 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09291 } else {
09292
09293 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09294 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09295 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09296 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09297 dahdi_enable_ec(pri->pvts[chanpos]);
09298 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09299 }
09300 }
09301 break;
09302 case PRI_EVENT_ANSWER:
09303 chanpos = pri_find_principle(pri, e->answer.channel);
09304 if (chanpos < 0) {
09305 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
09306 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09307 } else {
09308 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09309 if (chanpos < 0) {
09310 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
09311 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09312 } else {
09313 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09314
09315
09316
09317
09318
09319 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09320 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09321 pri->pvts[chanpos]->dsp_features = 0;
09322 }
09323 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09324 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09325 x = DAHDI_START;
09326 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09327 if (res < 0) {
09328 if (errno != EINPROGRESS) {
09329 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09330 }
09331 }
09332 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09333 pri->pvts[chanpos]->dialing = 1;
09334
09335 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09336 if (res < 0) {
09337 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09338 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09339 } else
09340 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09341 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09342 } else if (pri->pvts[chanpos]->confirmanswer) {
09343 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09344 } else {
09345 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09346
09347 dahdi_enable_ec(pri->pvts[chanpos]);
09348 }
09349
09350 #ifdef SUPPORT_USERUSER
09351 if (!ast_strlen_zero(e->answer.useruserinfo)) {
09352 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09353 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09354 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09355 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09356 }
09357 #endif
09358
09359 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09360 }
09361 }
09362 break;
09363 case PRI_EVENT_HANGUP:
09364 chanpos = pri_find_principle(pri, e->hangup.channel);
09365 if (chanpos < 0) {
09366 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
09367 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09368 } else {
09369 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09370 if (chanpos > -1) {
09371 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09372 if (!pri->pvts[chanpos]->alreadyhungup) {
09373
09374 pri->pvts[chanpos]->alreadyhungup = 1;
09375 if (pri->pvts[chanpos]->realcall)
09376 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09377 else if (pri->pvts[chanpos]->owner) {
09378
09379 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09380 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09381 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09382 else {
09383 switch (e->hangup.cause) {
09384 case PRI_CAUSE_USER_BUSY:
09385 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09386 break;
09387 case PRI_CAUSE_CALL_REJECTED:
09388 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09389 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09390 case PRI_CAUSE_SWITCH_CONGESTION:
09391 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09392 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09393 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09394 break;
09395 default:
09396 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09397 }
09398 }
09399 }
09400 if (option_verbose > 2)
09401 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
09402 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09403 } else {
09404 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09405 pri->pvts[chanpos]->call = NULL;
09406 }
09407 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09408 if (option_verbose > 2)
09409 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
09410 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09411 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09412 pri->pvts[chanpos]->resetting = 1;
09413 }
09414 if (e->hangup.aoc_units > -1)
09415 if (option_verbose > 2)
09416 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09417 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09418
09419 #ifdef SUPPORT_USERUSER
09420 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09421 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09422 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09423 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09424 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09425 }
09426 #endif
09427
09428 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09429 } else {
09430 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
09431 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09432 }
09433 }
09434 break;
09435 #ifndef PRI_EVENT_HANGUP_REQ
09436 #error please update libpri
09437 #endif
09438 case PRI_EVENT_HANGUP_REQ:
09439 chanpos = pri_find_principle(pri, e->hangup.channel);
09440 if (chanpos < 0) {
09441 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
09442 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09443 } else {
09444 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09445 if (chanpos > -1) {
09446 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09447 if (pri->pvts[chanpos]->realcall)
09448 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09449 else if (pri->pvts[chanpos]->owner) {
09450 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09451 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09452 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09453 else {
09454 switch (e->hangup.cause) {
09455 case PRI_CAUSE_USER_BUSY:
09456 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09457 break;
09458 case PRI_CAUSE_CALL_REJECTED:
09459 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09460 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09461 case PRI_CAUSE_SWITCH_CONGESTION:
09462 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09463 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09464 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09465 break;
09466 default:
09467 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09468 }
09469 }
09470 if (option_verbose > 2)
09471 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);
09472 if (e->hangup.aoc_units > -1)
09473 if (option_verbose > 2)
09474 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09475 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09476 } else {
09477 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09478 pri->pvts[chanpos]->call = NULL;
09479 }
09480 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09481 if (option_verbose > 2)
09482 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
09483 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09484 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09485 pri->pvts[chanpos]->resetting = 1;
09486 }
09487
09488 #ifdef SUPPORT_USERUSER
09489 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09490 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09491 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09492 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09493 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09494 }
09495 #endif
09496
09497 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09498 } else {
09499 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);
09500 }
09501 }
09502 break;
09503 case PRI_EVENT_HANGUP_ACK:
09504 chanpos = pri_find_principle(pri, e->hangup.channel);
09505 if (chanpos < 0) {
09506 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
09507 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09508 } else {
09509 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09510 if (chanpos > -1) {
09511 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09512 pri->pvts[chanpos]->call = NULL;
09513 pri->pvts[chanpos]->resetting = 0;
09514 if (pri->pvts[chanpos]->owner) {
09515 if (option_verbose > 2)
09516 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);
09517 }
09518
09519 #ifdef SUPPORT_USERUSER
09520 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09521 struct ast_channel *owner = pri->pvts[chanpos]->owner;
09522 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09523 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09524 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09525 }
09526 #endif
09527
09528 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09529 }
09530 }
09531 break;
09532 case PRI_EVENT_CONFIG_ERR:
09533 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09534 break;
09535 case PRI_EVENT_RESTART_ACK:
09536 chanpos = pri_find_principle(pri, e->restartack.channel);
09537 if (chanpos < 0) {
09538
09539
09540
09541 for (x = 0; x < pri->numchans; x++) {
09542 if (pri->pvts[x] && pri->pvts[x]->resetting) {
09543 chanpos = x;
09544 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09545 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
09546 pri->pvts[chanpos]->prioffset, pri->span);
09547 if (pri->pvts[chanpos]->realcall)
09548 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09549 else if (pri->pvts[chanpos]->owner) {
09550 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
09551 pri->pvts[chanpos]->prioffset, pri->span);
09552 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09553 }
09554 pri->pvts[chanpos]->resetting = 0;
09555 if (option_verbose > 2)
09556 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09557 pri->pvts[chanpos]->prioffset, pri->span);
09558 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09559 if (pri->resetting)
09560 pri_check_restart(pri);
09561 break;
09562 }
09563 }
09564 if (chanpos < 0) {
09565 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
09566 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09567 }
09568 } else {
09569 if (pri->pvts[chanpos]) {
09570 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09571 if (pri->pvts[chanpos]->realcall)
09572 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09573 else if (pri->pvts[chanpos]->owner) {
09574 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09575 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09576 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09577 }
09578 pri->pvts[chanpos]->resetting = 0;
09579 if (option_verbose > 2)
09580 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
09581 pri->pvts[chanpos]->prioffset, pri->span);
09582 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09583 if (pri->resetting)
09584 pri_check_restart(pri);
09585 }
09586 }
09587 break;
09588 case PRI_EVENT_SETUP_ACK:
09589 chanpos = pri_find_principle(pri, e->setup_ack.channel);
09590 if (chanpos < 0) {
09591 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
09592 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09593 } else {
09594 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09595 if (chanpos > -1) {
09596 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09597 pri->pvts[chanpos]->setup_ack = 1;
09598
09599 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09600 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09601 pri_information(pri->pri, pri->pvts[chanpos]->call,
09602 pri->pvts[chanpos]->dialdest[x]);
09603 }
09604 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09605 } else
09606 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09607 }
09608 break;
09609 case PRI_EVENT_NOTIFY:
09610 chanpos = pri_find_principle(pri, e->notify.channel);
09611 if (chanpos < 0) {
09612 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09613 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09614 } else {
09615 struct ast_frame f = { AST_FRAME_CONTROL, };
09616 ast_mutex_lock(&pri->pvts[chanpos]->lock);
09617 switch (e->notify.info) {
09618 case PRI_NOTIFY_REMOTE_HOLD:
09619 f.subclass = AST_CONTROL_HOLD;
09620 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09621 break;
09622 case PRI_NOTIFY_REMOTE_RETRIEVAL:
09623 f.subclass = AST_CONTROL_UNHOLD;
09624 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09625 break;
09626 }
09627 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09628 }
09629 break;
09630 default:
09631 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09632 }
09633 }
09634 ast_mutex_unlock(&pri->lock);
09635 }
09636
09637 return NULL;
09638 }
09639
09640 static int start_pri(struct dahdi_pri *pri)
09641 {
09642 int res, x;
09643 struct dahdi_params p;
09644 struct dahdi_bufferinfo bi;
09645 struct dahdi_spaninfo si;
09646 int i;
09647
09648 for (i = 0; i < NUM_DCHANS; i++) {
09649 if (!pri->dchannels[i])
09650 break;
09651 #ifdef HAVE_ZAPTEL
09652 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
09653 #else
09654 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
09655 #endif
09656 x = pri->dchannels[i];
09657 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09658 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09659 return -1;
09660 }
09661 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09662 if (res) {
09663 dahdi_close_pri_fd(pri, i);
09664 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09665 return -1;
09666 }
09667 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
09668 dahdi_close_pri_fd(pri, i);
09669 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
09670 return -1;
09671 }
09672 memset(&si, 0, sizeof(si));
09673 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
09674 if (res) {
09675 dahdi_close_pri_fd(pri, i);
09676 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
09677 }
09678 if (!si.alarms)
09679 pri->dchanavail[i] |= DCHAN_NOTINALARM;
09680 else
09681 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
09682 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
09683 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
09684 bi.numbufs = 32;
09685 bi.bufsize = 1024;
09686 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
09687 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
09688 dahdi_close_pri_fd(pri, i);
09689 return -1;
09690 }
09691 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
09692
09693 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
09694 pri->overlapdial = 1;
09695 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
09696 #ifdef HAVE_PRI_INBANDDISCONNECT
09697 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
09698 #endif
09699
09700 if (i)
09701 pri_enslave(pri->dchans[0], pri->dchans[i]);
09702 if (!pri->dchans[i]) {
09703 dahdi_close_pri_fd(pri, i);
09704 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
09705 return -1;
09706 }
09707 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
09708 pri_set_nsf(pri->dchans[i], pri->nsf);
09709 #ifdef PRI_GETSET_TIMERS
09710 for (x = 0; x < PRI_MAX_TIMERS; x++) {
09711 if (pritimers[x] != 0)
09712 pri_set_timer(pri->dchans[i], x, pritimers[x]);
09713 }
09714 #endif
09715 }
09716
09717 pri->pri = pri->dchans[0];
09718 pri->resetpos = -1;
09719 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
09720 for (i = 0; i < NUM_DCHANS; i++) {
09721 if (!pri->dchannels[i])
09722 break;
09723 dahdi_close_pri_fd(pri, i);
09724 }
09725 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
09726 return -1;
09727 }
09728 return 0;
09729 }
09730
09731 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
09732 {
09733 int which, span;
09734 char *ret = NULL;
09735
09736 if (pos != rpos)
09737 return ret;
09738
09739 for (which = span = 0; span < NUM_SPANS; span++) {
09740 if (pris[span].pri && ++which > state) {
09741 asprintf(&ret, "%d", span + 1);
09742 break;
09743 }
09744 }
09745 return ret;
09746 }
09747
09748 static char *complete_span_4(const char *line, const char *word, int pos, int state)
09749 {
09750 return complete_span_helper(line,word,pos,state,3);
09751 }
09752
09753 static char *complete_span_5(const char *line, const char *word, int pos, int state)
09754 {
09755 return complete_span_helper(line,word,pos,state,4);
09756 }
09757
09758 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
09759 {
09760 int myfd;
09761
09762 if (!strncasecmp(argv[1], "set", 3)) {
09763 if (argc < 5)
09764 return RESULT_SHOWUSAGE;
09765
09766 if (ast_strlen_zero(argv[4]))
09767 return RESULT_SHOWUSAGE;
09768
09769 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
09770 if (myfd < 0) {
09771 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
09772 return RESULT_SUCCESS;
09773 }
09774
09775 ast_mutex_lock(&pridebugfdlock);
09776
09777 if (pridebugfd >= 0)
09778 close(pridebugfd);
09779
09780 pridebugfd = myfd;
09781 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
09782
09783 ast_mutex_unlock(&pridebugfdlock);
09784
09785 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
09786 } else {
09787
09788 ast_mutex_lock(&pridebugfdlock);
09789 close(pridebugfd);
09790 pridebugfd = -1;
09791 ast_cli(fd, "PRI debug output to file disabled\n");
09792 ast_mutex_unlock(&pridebugfdlock);
09793 }
09794
09795 return RESULT_SUCCESS;
09796 }
09797
09798 #ifdef HAVE_PRI_VERSION
09799 static int handle_pri_version(int fd, int agc, char *argv[]) {
09800 ast_cli(fd, "libpri version: %s\n", pri_get_version());
09801 return RESULT_SUCCESS;
09802 }
09803 #endif
09804
09805 static int handle_pri_debug(int fd, int argc, char *argv[])
09806 {
09807 int span;
09808 int x;
09809 if (argc < 4) {
09810 return RESULT_SHOWUSAGE;
09811 }
09812 span = atoi(argv[3]);
09813 if ((span < 1) || (span > NUM_SPANS)) {
09814 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
09815 return RESULT_SUCCESS;
09816 }
09817 if (!pris[span-1].pri) {
09818 ast_cli(fd, "No PRI running on span %d\n", span);
09819 return RESULT_SUCCESS;
09820 }
09821 for (x = 0; x < NUM_DCHANS; x++) {
09822 if (pris[span-1].dchans[x])
09823 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09824 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09825 PRI_DEBUG_Q921_STATE);
09826 }
09827 ast_cli(fd, "Enabled debugging on span %d\n", span);
09828 return RESULT_SUCCESS;
09829 }
09830
09831
09832
09833 static int handle_pri_no_debug(int fd, int argc, char *argv[])
09834 {
09835 int span;
09836 int x;
09837 if (argc < 5)
09838 return RESULT_SHOWUSAGE;
09839 span = atoi(argv[4]);
09840 if ((span < 1) || (span > NUM_SPANS)) {
09841 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09842 return RESULT_SUCCESS;
09843 }
09844 if (!pris[span-1].pri) {
09845 ast_cli(fd, "No PRI running on span %d\n", span);
09846 return RESULT_SUCCESS;
09847 }
09848 for (x = 0; x < NUM_DCHANS; x++) {
09849 if (pris[span-1].dchans[x])
09850 pri_set_debug(pris[span-1].dchans[x], 0);
09851 }
09852 ast_cli(fd, "Disabled debugging on span %d\n", span);
09853 return RESULT_SUCCESS;
09854 }
09855
09856 static int handle_pri_really_debug(int fd, int argc, char *argv[])
09857 {
09858 int span;
09859 int x;
09860 if (argc < 5)
09861 return RESULT_SHOWUSAGE;
09862 span = atoi(argv[4]);
09863 if ((span < 1) || (span > NUM_SPANS)) {
09864 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09865 return RESULT_SUCCESS;
09866 }
09867 if (!pris[span-1].pri) {
09868 ast_cli(fd, "No PRI running on span %d\n", span);
09869 return RESULT_SUCCESS;
09870 }
09871 for (x = 0; x < NUM_DCHANS; x++) {
09872 if (pris[span-1].dchans[x])
09873 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09874 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09875 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
09876 }
09877 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
09878 return RESULT_SUCCESS;
09879 }
09880
09881 static void build_status(char *s, size_t len, int status, int active)
09882 {
09883 if (!s || len < 1) {
09884 return;
09885 }
09886 s[0] = '\0';
09887 if (status & DCHAN_PROVISIONED)
09888 strncat(s, "Provisioned, ", len - strlen(s) - 1);
09889 if (!(status & DCHAN_NOTINALARM))
09890 strncat(s, "In Alarm, ", len - strlen(s) - 1);
09891 if (status & DCHAN_UP)
09892 strncat(s, "Up", len - strlen(s) - 1);
09893 else
09894 strncat(s, "Down", len - strlen(s) - 1);
09895 if (active)
09896 strncat(s, ", Active", len - strlen(s) - 1);
09897 else
09898 strncat(s, ", Standby", len - strlen(s) - 1);
09899 s[len - 1] = '\0';
09900 }
09901
09902 static int handle_pri_show_spans(int fd, int argc, char *argv[])
09903 {
09904 int span;
09905 int x;
09906 char status[256];
09907 if (argc != 3)
09908 return RESULT_SHOWUSAGE;
09909
09910 for (span = 0; span < NUM_SPANS; span++) {
09911 if (pris[span].pri) {
09912 for (x = 0; x < NUM_DCHANS; x++) {
09913 if (pris[span].dchannels[x]) {
09914 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
09915 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
09916 }
09917 }
09918 }
09919 }
09920 return RESULT_SUCCESS;
09921 }
09922
09923 static int handle_pri_show_span(int fd, int argc, char *argv[])
09924 {
09925 int span;
09926 int x;
09927 char status[256];
09928 if (argc < 4)
09929 return RESULT_SHOWUSAGE;
09930 span = atoi(argv[3]);
09931 if ((span < 1) || (span > NUM_SPANS)) {
09932 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
09933 return RESULT_SUCCESS;
09934 }
09935 if (!pris[span-1].pri) {
09936 ast_cli(fd, "No PRI running on span %d\n", span);
09937 return RESULT_SUCCESS;
09938 }
09939 for (x = 0; x < NUM_DCHANS; x++) {
09940 if (pris[span-1].dchannels[x]) {
09941 #ifdef PRI_DUMP_INFO_STR
09942 char *info_str = NULL;
09943 #endif
09944 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
09945 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
09946 ast_cli(fd, "Status: %s\n", status);
09947 #ifdef PRI_DUMP_INFO_STR
09948 info_str = pri_dump_info_str(pris[span-1].pri);
09949 if (info_str) {
09950 ast_cli(fd, "%s", info_str);
09951 free(info_str);
09952 }
09953 #else
09954 pri_dump_info(pris[span-1].pri);
09955 #endif
09956 ast_cli(fd, "\n");
09957 }
09958 }
09959 return RESULT_SUCCESS;
09960 }
09961
09962 static int handle_pri_show_debug(int fd, int argc, char *argv[])
09963 {
09964 int x;
09965 int span;
09966 int count=0;
09967 int debug=0;
09968
09969 for (span = 0; span < NUM_SPANS; span++) {
09970 if (pris[span].pri) {
09971 for (x = 0; x < NUM_DCHANS; x++) {
09972 debug = 0;
09973 if (pris[span].dchans[x]) {
09974 debug = pri_get_debug(pris[span].dchans[x]);
09975 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" );
09976 count++;
09977 }
09978 }
09979 }
09980
09981 }
09982 ast_mutex_lock(&pridebugfdlock);
09983 if (pridebugfd >= 0)
09984 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
09985 ast_mutex_unlock(&pridebugfdlock);
09986
09987 if (!count)
09988 ast_cli(fd, "No debug set or no PRI running\n");
09989 return RESULT_SUCCESS;
09990 }
09991
09992 static const char pri_debug_help[] =
09993 "Usage: pri debug span <span>\n"
09994 " Enables debugging on a given PRI span\n";
09995
09996 static const char pri_no_debug_help[] =
09997 "Usage: pri no debug span <span>\n"
09998 " Disables debugging on a given PRI span\n";
09999
10000 static const char pri_really_debug_help[] =
10001 "Usage: pri intensive debug span <span>\n"
10002 " Enables debugging down to the Q.921 level\n";
10003
10004 static const char pri_show_span_help[] =
10005 "Usage: pri show span <span>\n"
10006 " Displays PRI Information on a given PRI span\n";
10007
10008 static const char pri_show_spans_help[] =
10009 "Usage: pri show spans\n"
10010 " Displays PRI Information\n";
10011
10012 static struct ast_cli_entry dahdi_pri_cli[] = {
10013 { { "pri", "debug", "span", NULL },
10014 handle_pri_debug, "Enables PRI debugging on a span",
10015 pri_debug_help, complete_span_4 },
10016
10017 { { "pri", "no", "debug", "span", NULL },
10018 handle_pri_no_debug, "Disables PRI debugging on a span",
10019 pri_no_debug_help, complete_span_5 },
10020
10021 { { "pri", "intense", "debug", "span", NULL },
10022 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10023 pri_really_debug_help, complete_span_5 },
10024
10025 { { "pri", "show", "spans", NULL },
10026 handle_pri_show_spans, "Displays PRI Information",
10027 pri_show_spans_help },
10028
10029 { { "pri", "show", "span", NULL },
10030 handle_pri_show_span, "Displays PRI Information",
10031 pri_show_span_help, complete_span_4 },
10032
10033 { { "pri", "show", "debug", NULL },
10034 handle_pri_show_debug, "Displays current PRI debug settings" },
10035
10036 { { "pri", "set", "debug", "file", NULL },
10037 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10038
10039 { { "pri", "unset", "debug", "file", NULL },
10040 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10041
10042 #ifdef HAVE_PRI_VERSION
10043 { { "pri", "show", "version", NULL },
10044 handle_pri_version, "Displays version of libpri" },
10045 #endif
10046 };
10047
10048 #endif
10049
10050 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10051 {
10052 int channel;
10053
10054 if (argc != 4)
10055 return RESULT_SHOWUSAGE;
10056
10057 channel = atoi(argv[3]);
10058
10059 return dahdi_destroy_channel_bynum(channel);
10060 }
10061
10062 static void dahdi_softhangup_all(void)
10063 {
10064 struct dahdi_pvt *p;
10065 retry:
10066 ast_mutex_lock(&iflock);
10067 for (p = iflist; p; p = p->next) {
10068 ast_mutex_lock(&p->lock);
10069 if (p->owner && !p->restartpending) {
10070 if (ast_channel_trylock(p->owner)) {
10071 if (option_debug > 2)
10072 ast_verbose("Avoiding deadlock\n");
10073
10074 ast_mutex_unlock(&p->lock);
10075 ast_mutex_unlock(&iflock);
10076 goto retry;
10077 }
10078 if (option_debug > 2)
10079 ast_verbose("Softhanging up on %s\n", p->owner->name);
10080 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10081 p->restartpending = 1;
10082 num_restart_pending++;
10083 ast_channel_unlock(p->owner);
10084 }
10085 ast_mutex_unlock(&p->lock);
10086 }
10087 ast_mutex_unlock(&iflock);
10088 }
10089
10090 static int setup_dahdi(int reload);
10091 static int dahdi_restart(void)
10092 {
10093 #if defined(HAVE_PRI)
10094 int i, j;
10095 #endif
10096 int cancel_code;
10097 struct dahdi_pvt *p;
10098
10099 ast_mutex_lock(&restart_lock);
10100
10101 if (option_verbose)
10102 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10103 dahdi_softhangup_all();
10104 if (option_verbose > 3)
10105 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10106
10107 #if defined(HAVE_PRI)
10108 for (i = 0; i < NUM_SPANS; i++) {
10109 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10110 cancel_code = pthread_cancel(pris[i].master);
10111 pthread_kill(pris[i].master, SIGURG);
10112 if (option_debug > 3)
10113 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10114 pthread_join(pris[i].master, NULL);
10115 if (option_debug > 3)
10116 ast_verbose("Joined thread of span %d\n", i);
10117 }
10118 }
10119 #endif
10120
10121 ast_mutex_lock(&monlock);
10122 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10123 cancel_code = pthread_cancel(monitor_thread);
10124 pthread_kill(monitor_thread, SIGURG);
10125 if (option_debug > 3)
10126 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10127 pthread_join(monitor_thread, NULL);
10128 if (option_debug > 3)
10129 ast_verbose("Joined monitor thread\n");
10130 }
10131 monitor_thread = AST_PTHREADT_NULL;
10132
10133 ast_mutex_lock(&ss_thread_lock);
10134 while (ss_thread_count > 0) {
10135 int x = DAHDI_FLASH;
10136 if (option_debug > 2)
10137 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10138
10139 for (p = iflist; p; p = p->next) {
10140 if (p->owner)
10141 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10142 }
10143 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10144 }
10145
10146
10147 dahdi_softhangup_all();
10148 if (option_verbose > 3)
10149 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10150 destroy_all_channels();
10151 if (option_debug)
10152 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10153
10154 ast_mutex_unlock(&monlock);
10155
10156 #ifdef HAVE_PRI
10157 for (i = 0; i < NUM_SPANS; i++) {
10158 for (j = 0; j < NUM_DCHANS; j++)
10159 dahdi_close_pri_fd(&(pris[i]), j);
10160 }
10161
10162 memset(pris, 0, sizeof(pris));
10163 for (i = 0; i < NUM_SPANS; i++) {
10164 ast_mutex_init(&pris[i].lock);
10165 pris[i].offset = -1;
10166 pris[i].master = AST_PTHREADT_NULL;
10167 for (j = 0; j < NUM_DCHANS; j++)
10168 pris[i].fds[j] = -1;
10169 }
10170 pri_set_error(dahdi_pri_error);
10171 pri_set_message(dahdi_pri_message);
10172 #endif
10173
10174 if (setup_dahdi(2) != 0) {
10175 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10176 ast_mutex_unlock(&ss_thread_lock);
10177 return 1;
10178 }
10179 ast_mutex_unlock(&ss_thread_lock);
10180 ast_mutex_unlock(&restart_lock);
10181 return 0;
10182 }
10183
10184 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10185 {
10186 if (argc != 2) {
10187 return RESULT_SHOWUSAGE;
10188 }
10189
10190 if (dahdi_restart() != 0)
10191 return RESULT_FAILURE;
10192 return RESULT_SUCCESS;
10193 }
10194
10195 static int dahdi_show_channels(int fd, int argc, char **argv)
10196 {
10197 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10198 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10199 struct dahdi_pvt *tmp = NULL;
10200 char tmps[20] = "";
10201 ast_mutex_t *lock;
10202 struct dahdi_pvt *start;
10203 #ifdef HAVE_PRI
10204 int trunkgroup;
10205 struct dahdi_pri *pri = NULL;
10206 int x;
10207 #endif
10208
10209 lock = &iflock;
10210 start = iflist;
10211
10212 #ifdef HAVE_PRI
10213 if (argc == 4) {
10214 if ((trunkgroup = atoi(argv[3])) < 1)
10215 return RESULT_SHOWUSAGE;
10216 for (x = 0; x < NUM_SPANS; x++) {
10217 if (pris[x].trunkgroup == trunkgroup) {
10218 pri = pris + x;
10219 break;
10220 }
10221 }
10222 if (pri) {
10223 start = pri->crvs;
10224 lock = &pri->lock;
10225 } else {
10226 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10227 return RESULT_FAILURE;
10228 }
10229 } else
10230 #endif
10231 if (argc != 3)
10232 return RESULT_SHOWUSAGE;
10233
10234 ast_mutex_lock(lock);
10235 #ifdef HAVE_PRI
10236 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10237 #else
10238 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10239 #endif
10240
10241 tmp = start;
10242 while (tmp) {
10243 if (tmp->channel > 0) {
10244 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10245 } else
10246 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10247 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10248 tmp = tmp->next;
10249 }
10250 ast_mutex_unlock(lock);
10251 return RESULT_SUCCESS;
10252 #undef FORMAT
10253 #undef FORMAT2
10254 }
10255
10256 static int dahdi_show_channel(int fd, int argc, char **argv)
10257 {
10258 int channel;
10259 struct dahdi_pvt *tmp = NULL;
10260 struct dahdi_confinfo ci;
10261 struct dahdi_params ps;
10262 int x;
10263 ast_mutex_t *lock;
10264 struct dahdi_pvt *start;
10265 #ifdef HAVE_PRI
10266 char *c;
10267 int trunkgroup;
10268 struct dahdi_pri *pri=NULL;
10269 #endif
10270
10271 lock = &iflock;
10272 start = iflist;
10273
10274 if (argc != 4)
10275 return RESULT_SHOWUSAGE;
10276 #ifdef HAVE_PRI
10277 if ((c = strchr(argv[3], ':'))) {
10278 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10279 return RESULT_SHOWUSAGE;
10280 if ((trunkgroup < 1) || (channel < 1))
10281 return RESULT_SHOWUSAGE;
10282 for (x = 0; x < NUM_SPANS; x++) {
10283 if (pris[x].trunkgroup == trunkgroup) {
10284 pri = pris + x;
10285 break;
10286 }
10287 }
10288 if (pri) {
10289 start = pri->crvs;
10290 lock = &pri->lock;
10291 } else {
10292 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10293 return RESULT_FAILURE;
10294 }
10295 } else
10296 #endif
10297 channel = atoi(argv[3]);
10298
10299 ast_mutex_lock(lock);
10300 tmp = start;
10301 while (tmp) {
10302 if (tmp->channel == channel) {
10303 #ifdef HAVE_PRI
10304 if (pri)
10305 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10306 else
10307 #endif
10308 ast_cli(fd, "Channel: %d\n", tmp->channel);
10309 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10310 ast_cli(fd, "Span: %d\n", tmp->span);
10311 ast_cli(fd, "Extension: %s\n", tmp->exten);
10312 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10313 ast_cli(fd, "Context: %s\n", tmp->context);
10314 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10315 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10316 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10317 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10318 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10319 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10320 ast_cli(fd, "Radio: %d\n", tmp->radio);
10321 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10322 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)" : "");
10323 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)" : "");
10324 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)" : "");
10325 ast_cli(fd, "Confno: %d\n", tmp->confno);
10326 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10327 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10328 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10329 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10330 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10331 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10332 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10333 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10334 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10335 if (tmp->master)
10336 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10337 for (x = 0; x < MAX_SLAVES; x++) {
10338 if (tmp->slaves[x])
10339 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10340 }
10341 #ifdef HAVE_PRI
10342 if (tmp->pri) {
10343 ast_cli(fd, "PRI Flags: ");
10344 if (tmp->resetting)
10345 ast_cli(fd, "Resetting ");
10346 if (tmp->call)
10347 ast_cli(fd, "Call ");
10348 if (tmp->bearer)
10349 ast_cli(fd, "Bearer ");
10350 ast_cli(fd, "\n");
10351 if (tmp->logicalspan)
10352 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10353 else
10354 ast_cli(fd, "PRI Logical Span: Implicit\n");
10355 }
10356
10357 #endif
10358 memset(&ci, 0, sizeof(ci));
10359 ps.channo = tmp->channel;
10360 if (tmp->subs[SUB_REAL].dfd > -1) {
10361 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10362 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10363 }
10364 #ifdef DAHDI_GETCONFMUTE
10365 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10366 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10367 }
10368 #endif
10369 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10370 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10371 } else {
10372 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10373 }
10374 }
10375 if (ISTRUNK(tmp)) {
10376 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
10377 if (!ast_strlen_zero(progzone))
10378 ast_cli(fd, "Progress Zone: %s\n", progzone);
10379 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
10380 if(tmp->busydetect) {
10381 ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10382 if(tmp->busytonelength > 0) {
10383 ast_cli(fd, "Busy Pattern:\n");
10384 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10385 if (tmp->busyquietlength > 0)
10386 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10387 else
10388 ast_cli(fd, " -- Detect Tone Only\n");
10389 if(tmp->busyfuzziness > 0)
10390 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10391 }
10392 }
10393 }
10394 ast_mutex_unlock(lock);
10395 return RESULT_SUCCESS;
10396 }
10397 tmp = tmp->next;
10398 }
10399
10400 ast_cli(fd, "Unable to find given channel %d\n", channel);
10401 ast_mutex_unlock(lock);
10402 return RESULT_FAILURE;
10403 }
10404
10405 static char dahdi_show_cadences_usage[] =
10406 "Usage: dahdi show cadences\n"
10407 " Shows all cadences currently defined\n";
10408
10409 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10410 {
10411 int i, j;
10412 for (i = 0; i < num_cadence; i++) {
10413 char output[1024];
10414 char tmp[16], tmp2[64];
10415 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10416 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10417
10418 for (j = 0; j < 16; j++) {
10419 if (cadences[i].ringcadence[j] == 0)
10420 break;
10421 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10422 if (cidrings[i] * 2 - 1 == j)
10423 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10424 else
10425 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10426 if (j != 0)
10427 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10428 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10429 }
10430 ast_cli(fd,"%s\n",output);
10431 }
10432 return 0;
10433 }
10434
10435
10436 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10437 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10438 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10439
10440 int span;
10441 int res;
10442 char alarms[50];
10443
10444 int ctl;
10445 struct dahdi_spaninfo s;
10446
10447 #ifdef HAVE_ZAPTEL
10448 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10449 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10450 ast_cli(fd, "No Zaptel interface found.\n");
10451 return RESULT_FAILURE;
10452 }
10453 #else
10454 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10455 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10456 ast_cli(fd, "No DAHDI interface found.\n");
10457 return RESULT_FAILURE;
10458 }
10459 #endif
10460 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10461
10462 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10463 s.spanno = span;
10464 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10465 if (res) {
10466 continue;
10467 }
10468 alarms[0] = '\0';
10469 if (s.alarms > 0) {
10470 if (s.alarms & DAHDI_ALARM_BLUE)
10471 strcat(alarms, "BLU/");
10472 if (s.alarms & DAHDI_ALARM_YELLOW)
10473 strcat(alarms, "YEL/");
10474 if (s.alarms & DAHDI_ALARM_RED)
10475 strcat(alarms, "RED/");
10476 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10477 strcat(alarms, "LB/");
10478 if (s.alarms & DAHDI_ALARM_RECOVER)
10479 strcat(alarms, "REC/");
10480 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10481 strcat(alarms, "NOP/");
10482 if (!strlen(alarms))
10483 strcat(alarms, "UUU/");
10484 if (strlen(alarms)) {
10485
10486 alarms[strlen(alarms) - 1] = '\0';
10487 }
10488 } else {
10489 if (s.numchans)
10490 strcpy(alarms, "OK");
10491 else
10492 strcpy(alarms, "UNCONFIGURED");
10493 }
10494
10495 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10496 }
10497 close(ctl);
10498
10499 return RESULT_SUCCESS;
10500 #undef FORMAT
10501 #undef FORMAT2
10502 }
10503
10504 static char show_channels_usage[] =
10505 "Usage: dahdi show channels\n"
10506 " Shows a list of available channels\n";
10507
10508 static char show_channel_usage[] =
10509 "Usage: dahdi show channel <chan num>\n"
10510 " Detailed information about a given channel\n";
10511
10512 static char dahdi_show_status_usage[] =
10513 "Usage: dahdi show status\n"
10514 " Shows a list of DAHDI cards with status\n";
10515
10516 static char destroy_channel_usage[] =
10517 "Usage: dahdi destroy channel <chan num>\n"
10518 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10519
10520 static char dahdi_restart_usage[] =
10521 "Usage: dahdi restart\n"
10522 " Restarts the DAHDI channels: destroys them all and then\n"
10523 " re-reads them from chan_dahdi.conf.\n"
10524 " Note that this will STOP any running CALL on DAHDI channels.\n"
10525 "";
10526
10527 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10528 { "zap", "show", "cadences", NULL },
10529 handle_dahdi_show_cadences, NULL,
10530 NULL };
10531
10532 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10533 { "zap", "show", "channels", NULL },
10534 dahdi_show_channels, NULL,
10535 NULL };
10536
10537 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10538 { "zap", "show", "channel", NULL },
10539 dahdi_show_channel, NULL,
10540 NULL };
10541
10542 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10543 { "zap", "destroy", "channel", NULL },
10544 dahdi_destroy_channel, NULL,
10545 NULL };
10546
10547 static struct ast_cli_entry cli_zap_restart_deprecated = {
10548 { "zap", "restart", NULL },
10549 dahdi_restart_cmd, NULL,
10550 NULL };
10551
10552 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10553 { "zap", "show", "status", NULL },
10554 dahdi_show_status, NULL,
10555 NULL };
10556
10557 static struct ast_cli_entry dahdi_cli[] = {
10558 { { "dahdi", "show", "cadences", NULL },
10559 handle_dahdi_show_cadences, "List cadences",
10560 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10561
10562 { { "dahdi", "show", "channels", NULL},
10563 dahdi_show_channels, "Show active DAHDI channels",
10564 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10565
10566 { { "dahdi", "show", "channel", NULL},
10567 dahdi_show_channel, "Show information on a channel",
10568 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10569
10570 { { "dahdi", "destroy", "channel", NULL},
10571 dahdi_destroy_channel, "Destroy a channel",
10572 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10573
10574 { { "dahdi", "restart", NULL},
10575 dahdi_restart_cmd, "Fully restart DAHDI channels",
10576 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10577
10578 { { "dahdi", "show", "status", NULL},
10579 dahdi_show_status, "Show all DAHDI cards status",
10580 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10581 };
10582
10583 #define TRANSFER 0
10584 #define HANGUP 1
10585
10586 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10587 {
10588 if (p) {
10589 switch (mode) {
10590 case TRANSFER:
10591 p->fake_event = DAHDI_EVENT_WINKFLASH;
10592 break;
10593 case HANGUP:
10594 p->fake_event = DAHDI_EVENT_ONHOOK;
10595 break;
10596 default:
10597 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10598 }
10599 }
10600 return 0;
10601 }
10602 static struct dahdi_pvt *find_channel(int channel)
10603 {
10604 struct dahdi_pvt *p = iflist;
10605 while (p) {
10606 if (p->channel == channel) {
10607 break;
10608 }
10609 p = p->next;
10610 }
10611 return p;
10612 }
10613
10614 #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)
10615 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10616
10617 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10618 {
10619 struct dahdi_pvt *p = NULL;
10620 const char *channel = local_astman_header(m, "Channel", zap_mode);
10621
10622 if (ast_strlen_zero(channel)) {
10623 astman_send_error(s, m, "No channel specified");
10624 return 0;
10625 }
10626 if (!(p = find_channel(atoi(channel)))) {
10627 astman_send_error(s, m, "No such channel");
10628 return 0;
10629 }
10630 p->dnd = dnd;
10631 local_astman_ack(s, m, "DND", zap_mode);
10632
10633 return 0;
10634 }
10635
10636 static int zap_action_dndon(struct mansession *s, const struct message *m)
10637 {
10638 return __action_dnd(s, m, 1, 1);
10639 }
10640
10641 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10642 {
10643 return __action_dnd(s, m, 0, 1);
10644 }
10645
10646 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10647 {
10648 return __action_dnd(s, m, 1, 0);
10649 }
10650
10651 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10652 {
10653 return __action_dnd(s, m, 0, 0);
10654 }
10655
10656 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10657 {
10658 struct dahdi_pvt *p = NULL;
10659 const char *channel = local_astman_header(m, "Channel", zap_mode);
10660
10661 if (ast_strlen_zero(channel)) {
10662 astman_send_error(s, m, "No channel specified");
10663 return 0;
10664 }
10665 if (!(p = find_channel(atoi(channel)))) {
10666 astman_send_error(s, m, "No such channel");
10667 return 0;
10668 }
10669 dahdi_fake_event(p,TRANSFER);
10670 local_astman_ack(s, m, "Transfer", zap_mode);
10671
10672 return 0;
10673 }
10674
10675 static int zap_action_transfer(struct mansession *s, const struct message *m)
10676 {
10677 return __action_transfer(s, m, 1);
10678 }
10679
10680 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10681 {
10682 return __action_transfer(s, m, 0);
10683 }
10684
10685 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10686 {
10687 struct dahdi_pvt *p = NULL;
10688 const char *channel = local_astman_header(m, "Channel", zap_mode);
10689
10690 if (ast_strlen_zero(channel)) {
10691 astman_send_error(s, m, "No channel specified");
10692 return 0;
10693 }
10694 if (!(p = find_channel(atoi(channel)))) {
10695 astman_send_error(s, m, "No such channel");
10696 return 0;
10697 }
10698 dahdi_fake_event(p, HANGUP);
10699 local_astman_ack(s, m, "Hangup", zap_mode);
10700 return 0;
10701 }
10702
10703 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10704 {
10705 return __action_transferhangup(s, m, 1);
10706 }
10707
10708 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10709 {
10710 return __action_transferhangup(s, m, 0);
10711 }
10712
10713 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10714 {
10715 struct dahdi_pvt *p = NULL;
10716 const char *channel = local_astman_header(m, "Channel", zap_mode);
10717 const char *number = astman_get_header(m, "Number");
10718 int i;
10719
10720 if (ast_strlen_zero(channel)) {
10721 astman_send_error(s, m, "No channel specified");
10722 return 0;
10723 }
10724 if (ast_strlen_zero(number)) {
10725 astman_send_error(s, m, "No number specified");
10726 return 0;
10727 }
10728 if (!(p = find_channel(atoi(channel)))) {
10729 astman_send_error(s, m, "No such channel");
10730 return 0;
10731 }
10732 if (!p->owner) {
10733 astman_send_error(s, m, "Channel does not have an owner");
10734 return 0;
10735 }
10736 for (i = 0; i < strlen(number); i++) {
10737 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10738
10739 dahdi_queue_frame(p, &f, NULL);
10740 }
10741 local_astman_ack(s, m, "DialOffHook", zap_mode);
10742
10743 return 0;
10744 }
10745
10746 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10747 {
10748 return __action_dialoffhook(s, m, 1);
10749 }
10750
10751 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10752 {
10753 return __action_dialoffhook(s, m, 0);
10754 }
10755
10756 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10757 {
10758 struct dahdi_pvt *tmp = NULL;
10759 const char *id = astman_get_header(m, "ActionID");
10760 char idText[256] = "";
10761
10762 local_astman_ack(s, m, " channel status will follow", zap_mode);
10763 if (!ast_strlen_zero(id))
10764 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10765
10766 ast_mutex_lock(&iflock);
10767
10768 tmp = iflist;
10769 while (tmp) {
10770 if (tmp->channel > 0) {
10771 int alarm = get_alarms(tmp);
10772 astman_append(s,
10773 "Event: %sShowChannels\r\n"
10774 "Channel: %d\r\n"
10775 "Signalling: %s\r\n"
10776 "Context: %s\r\n"
10777 "DND: %s\r\n"
10778 "Alarm: %s\r\n"
10779 "%s"
10780 "\r\n",
10781 dahdi_chan_name,
10782 tmp->channel, sig2str(tmp->sig), tmp->context,
10783 tmp->dnd ? "Enabled" : "Disabled",
10784 alarm2str(alarm), idText);
10785 }
10786
10787 tmp = tmp->next;
10788 }
10789
10790 ast_mutex_unlock(&iflock);
10791
10792 astman_append(s,
10793 "Event: %sShowChannelsComplete\r\n"
10794 "%s"
10795 "\r\n",
10796 dahdi_chan_name,
10797 idText);
10798 return 0;
10799 }
10800
10801 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10802 {
10803 return __action_showchannels(s, m, 1);
10804 }
10805
10806 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10807 {
10808 return __action_showchannels(s, m, 0);
10809 }
10810
10811 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10812 {
10813 if (dahdi_restart() != 0) {
10814 if (zap_mode) {
10815 astman_send_error(s, m, "Failed to restart Zap");
10816 } else {
10817 astman_send_error(s, m, "Failed to restart DAHDI");
10818 }
10819 return 1;
10820 }
10821 local_astman_ack(s, m, "Restart: Success", zap_mode);
10822 return 0;
10823 }
10824
10825 static int zap_action_restart(struct mansession *s, const struct message *m)
10826 {
10827 return __action_restart(s, m, 1);
10828 }
10829
10830 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10831 {
10832 return __action_restart(s, m, 0);
10833 }
10834
10835 #define local_astman_unregister(a) do { \
10836 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10837 ast_manager_unregister("DAHDI" a); \
10838 } \
10839 ast_manager_unregister("Zap" a); \
10840 } while (0)
10841
10842 static int __unload_module(void)
10843 {
10844 struct dahdi_pvt *p;
10845
10846 #ifdef HAVE_PRI
10847 int i, j;
10848 for (i = 0; i < NUM_SPANS; i++) {
10849 if (pris[i].master != AST_PTHREADT_NULL)
10850 pthread_cancel(pris[i].master);
10851 }
10852 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10853
10854 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10855 ast_unregister_application(dahdi_send_keypad_facility_app);
10856 }
10857 ast_unregister_application(zap_send_keypad_facility_app);
10858 #endif
10859 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10860 local_astman_unregister("DialOffHook");
10861 local_astman_unregister("Hangup");
10862 local_astman_unregister("Transfer");
10863 local_astman_unregister("DNDoff");
10864 local_astman_unregister("DNDon");
10865 local_astman_unregister("ShowChannels");
10866 local_astman_unregister("Restart");
10867 ast_channel_unregister(chan_tech);
10868 ast_mutex_lock(&iflock);
10869
10870 p = iflist;
10871 while (p) {
10872 if (p->owner)
10873 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10874 p = p->next;
10875 }
10876 ast_mutex_unlock(&iflock);
10877 ast_mutex_lock(&monlock);
10878 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10879 pthread_cancel(monitor_thread);
10880 pthread_kill(monitor_thread, SIGURG);
10881 pthread_join(monitor_thread, NULL);
10882 }
10883 monitor_thread = AST_PTHREADT_STOP;
10884 ast_mutex_unlock(&monlock);
10885
10886 destroy_all_channels();
10887 #ifdef HAVE_PRI
10888 for (i = 0; i < NUM_SPANS; i++) {
10889 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10890 pthread_join(pris[i].master, NULL);
10891 for (j = 0; j < NUM_DCHANS; j++) {
10892 dahdi_close_pri_fd(&(pris[i]), j);
10893 }
10894 }
10895 #endif
10896 ast_cond_destroy(&ss_thread_complete);
10897 return 0;
10898 }
10899
10900 static int unload_module(void)
10901 {
10902 #ifdef HAVE_PRI
10903 int y;
10904 for (y = 0; y < NUM_SPANS; y++)
10905 ast_mutex_destroy(&pris[y].lock);
10906 #endif
10907 return __unload_module();
10908 }
10909
10910 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10911 {
10912 char *c, *chan;
10913 int x, start, finish;
10914 struct dahdi_pvt *tmp;
10915 #ifdef HAVE_PRI
10916 struct dahdi_pri *pri;
10917 int trunkgroup, y;
10918 #endif
10919
10920 if ((reload == 0) && (conf->chan.sig < 0)) {
10921 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10922 return -1;
10923 }
10924
10925 c = ast_strdupa(value);
10926
10927 #ifdef HAVE_PRI
10928 pri = NULL;
10929 if (iscrv) {
10930 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10931 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10932 return -1;
10933 }
10934 if (trunkgroup < 1) {
10935 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10936 return -1;
10937 }
10938 c += y;
10939 for (y = 0; y < NUM_SPANS; y++) {
10940 if (pris[y].trunkgroup == trunkgroup) {
10941 pri = pris + y;
10942 break;
10943 }
10944 }
10945 if (!pri) {
10946 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10947 return -1;
10948 }
10949 }
10950 #endif
10951
10952 while ((chan = strsep(&c, ","))) {
10953 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10954
10955 } else if (sscanf(chan, "%d", &start)) {
10956
10957 finish = start;
10958 } else if (!strcasecmp(chan, "pseudo")) {
10959 finish = start = CHAN_PSEUDO;
10960 if (found_pseudo)
10961 *found_pseudo = 1;
10962 } else {
10963 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10964 return -1;
10965 }
10966 if (finish < start) {
10967 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10968 x = finish;
10969 finish = start;
10970 start = x;
10971 }
10972
10973 for (x = start; x <= finish; x++) {
10974 #ifdef HAVE_PRI
10975 tmp = mkintf(x, conf, pri, reload);
10976 #else
10977 tmp = mkintf(x, conf, NULL, reload);
10978 #endif
10979
10980 if (tmp) {
10981 if (option_verbose > 2) {
10982 #ifdef HAVE_PRI
10983 if (pri)
10984 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10985 else
10986 #endif
10987 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10988 }
10989 } else {
10990 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10991 (reload == 1) ? "reconfigure" : "register", value);
10992 return -1;
10993 }
10994 }
10995 }
10996
10997 return 0;
10998 }
10999
11000
11001
11002 #define MAX_CHANLIST_LEN 80
11003 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
11004 {
11005 struct dahdi_pvt *tmp;
11006 int y;
11007 int found_pseudo = 0;
11008 char dahdichan[MAX_CHANLIST_LEN] = {};
11009
11010 for (; v; v = v->next) {
11011 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11012 continue;
11013
11014
11015 if (!strcasecmp(v->name, "channel")
11016 #ifdef HAVE_PRI
11017 || !strcasecmp(v->name, "crv")
11018 #endif
11019 ) {
11020 int iscrv;
11021 if (skipchannels)
11022 continue;
11023 iscrv = !strcasecmp(v->name, "crv");
11024 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11025 return -1;
11026 } else if (!strcasecmp(v->name, "buffers")) {
11027 int res;
11028 char policy[8] = "";
11029 res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
11030 if (res != 2) {
11031 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11032 confp->chan.buf_no = numbufs;
11033 continue;
11034 }
11035 if (confp->chan.buf_no < 0)
11036 confp->chan.buf_no = numbufs;
11037 if (!strcasecmp(policy, "full")) {
11038 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11039 } else if (!strcasecmp(policy, "half")) {
11040 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE ;
11041 } else if (!strcasecmp(policy, "immediate")) {
11042 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11043 } else {
11044 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11045 }
11046 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11047 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11048 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11049 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11050 }
11051 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11052 if (ast_true(v->value))
11053 confp->chan.usedistinctiveringdetection = 1;
11054 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11055 if (ast_true(v->value))
11056 distinctiveringaftercid = 1;
11057 } else if (!strcasecmp(v->name, "dring1context")) {
11058 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11059 } else if (!strcasecmp(v->name, "dring2context")) {
11060 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11061 } else if (!strcasecmp(v->name, "dring3context")) {
11062 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11063 } else if (!strcasecmp(v->name, "dring1")) {
11064 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11065 } else if (!strcasecmp(v->name, "dring2")) {
11066 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11067 } else if (!strcasecmp(v->name, "dring3")) {
11068 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11069 } else if (!strcasecmp(v->name, "usecallerid")) {
11070 confp->chan.use_callerid = ast_true(v->value);
11071 } else if (!strcasecmp(v->name, "cidsignalling")) {
11072 if (!strcasecmp(v->value, "bell"))
11073 confp->chan.cid_signalling = CID_SIG_BELL;
11074 else if (!strcasecmp(v->value, "v23"))
11075 confp->chan.cid_signalling = CID_SIG_V23;
11076 else if (!strcasecmp(v->value, "dtmf"))
11077 confp->chan.cid_signalling = CID_SIG_DTMF;
11078 else if (!strcasecmp(v->value, "smdi"))
11079 confp->chan.cid_signalling = CID_SIG_SMDI;
11080 else if (!strcasecmp(v->value, "v23_jp"))
11081 confp->chan.cid_signalling = CID_SIG_V23_JP;
11082 else if (ast_true(v->value))
11083 confp->chan.cid_signalling = CID_SIG_BELL;
11084 } else if (!strcasecmp(v->name, "cidstart")) {
11085 if (!strcasecmp(v->value, "ring"))
11086 confp->chan.cid_start = CID_START_RING;
11087 else if (!strcasecmp(v->value, "polarity"))
11088 confp->chan.cid_start = CID_START_POLARITY;
11089 else if (ast_true(v->value))
11090 confp->chan.cid_start = CID_START_RING;
11091 } else if (!strcasecmp(v->name, "threewaycalling")) {
11092 confp->chan.threewaycalling = ast_true(v->value);
11093 } else if (!strcasecmp(v->name, "cancallforward")) {
11094 confp->chan.cancallforward = ast_true(v->value);
11095 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11096 if (ast_true(v->value))
11097 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11098 else
11099 confp->chan.dtmfrelax = 0;
11100 } else if (!strcasecmp(v->name, "mailbox")) {
11101 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11102 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11103 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11104 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11105 }
11106 } else if (!strcasecmp(v->name, "adsi")) {
11107 confp->chan.adsi = ast_true(v->value);
11108 } else if (!strcasecmp(v->name, "usesmdi")) {
11109 confp->chan.use_smdi = ast_true(v->value);
11110 } else if (!strcasecmp(v->name, "smdiport")) {
11111 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11112 } else if (!strcasecmp(v->name, "transfer")) {
11113 confp->chan.transfer = ast_true(v->value);
11114 } else if (!strcasecmp(v->name, "canpark")) {
11115 confp->chan.canpark = ast_true(v->value);
11116 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11117 confp->chan.echocanbridged = ast_true(v->value);
11118 } else if (!strcasecmp(v->name, "busydetect")) {
11119 confp->chan.busydetect = ast_true(v->value);
11120 } else if (!strcasecmp(v->name, "busycount")) {
11121 confp->chan.busycount = atoi(v->value);
11122 } else if (!strcasecmp(v->name, "silencethreshold")) {
11123 confp->chan.silencethreshold = atoi(v->value);
11124 } else if (!strcasecmp(v->name, "busycompare")) {
11125 confp->chan.busycompare = ast_true(v->value);
11126 } else if (!strcasecmp(v->name, "busypattern")) {
11127 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11128 if (count == 1)
11129 confp->chan.busyquietlength = 0;
11130 else if (count < 1)
11131 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11132 } else if (!strcasecmp(v->name, "busyfuzziness")) {
11133 confp->chan.busyfuzziness = atoi(v->value);
11134 } else if (!strcasecmp(v->name, "callprogress")) {
11135 if (ast_true(v->value))
11136 confp->chan.callprogress |= 1;
11137 else
11138 confp->chan.callprogress &= ~1;
11139 } else if (!strcasecmp(v->name, "faxdetect")) {
11140 if (!strcasecmp(v->value, "incoming")) {
11141 confp->chan.callprogress |= 4;
11142 confp->chan.callprogress &= ~2;
11143 } else if (!strcasecmp(v->value, "outgoing")) {
11144 confp->chan.callprogress &= ~4;
11145 confp->chan.callprogress |= 2;
11146 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11147 confp->chan.callprogress |= 6;
11148 else
11149 confp->chan.callprogress &= ~6;
11150 } else if (!strcasecmp(v->name, "echocancel")) {
11151 if (!ast_strlen_zero(v->value)) {
11152 y = atoi(v->value);
11153 } else
11154 y = 0;
11155 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11156 confp->chan.echocancel = y;
11157 else {
11158 confp->chan.echocancel = ast_true(v->value);
11159 if (confp->chan.echocancel)
11160 confp->chan.echocancel=128;
11161 }
11162 } else if (!strcasecmp(v->name, "echotraining")) {
11163 if (sscanf(v->value, "%d", &y) == 1) {
11164 if ((y < 10) || (y > 4000)) {
11165 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11166 } else {
11167 confp->chan.echotraining = y;
11168 }
11169 } else if (ast_true(v->value)) {
11170 confp->chan.echotraining = 400;
11171 } else
11172 confp->chan.echotraining = 0;
11173 } else if (!strcasecmp(v->name, "hidecallerid")) {
11174 confp->chan.hidecallerid = ast_true(v->value);
11175 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11176 confp->chan.hidecalleridname = ast_true(v->value);
11177 } else if (!strcasecmp(v->name, "pulsedial")) {
11178 confp->chan.pulse = ast_true(v->value);
11179 } else if (!strcasecmp(v->name, "callreturn")) {
11180 confp->chan.callreturn = ast_true(v->value);
11181 } else if (!strcasecmp(v->name, "callwaiting")) {
11182 confp->chan.callwaiting = ast_true(v->value);
11183 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11184 confp->chan.callwaitingcallerid = ast_true(v->value);
11185 } else if (!strcasecmp(v->name, "context")) {
11186 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11187 } else if (!strcasecmp(v->name, "language")) {
11188 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11189 } else if (!strcasecmp(v->name, "progzone")) {
11190 ast_copy_string(progzone, v->value, sizeof(progzone));
11191 } else if (!strcasecmp(v->name, "mohinterpret")
11192 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11193 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11194 } else if (!strcasecmp(v->name, "mohsuggest")) {
11195 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11196 } else if (!strcasecmp(v->name, "stripmsd")) {
11197 confp->chan.stripmsd = atoi(v->value);
11198 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11199 numbufs = atoi(v->value);
11200 } else if (!strcasecmp(v->name, "group")) {
11201 confp->chan.group = ast_get_group(v->value);
11202 } else if (!strcasecmp(v->name, "callgroup")) {
11203 confp->chan.callgroup = ast_get_group(v->value);
11204 } else if (!strcasecmp(v->name, "pickupgroup")) {
11205 confp->chan.pickupgroup = ast_get_group(v->value);
11206 } else if (!strcasecmp(v->name, "immediate")) {
11207 confp->chan.immediate = ast_true(v->value);
11208 } else if (!strcasecmp(v->name, "transfertobusy")) {
11209 confp->chan.transfertobusy = ast_true(v->value);
11210 } else if (!strcasecmp(v->name, "rxgain")) {
11211 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11212 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11213 }
11214 } else if (!strcasecmp(v->name, "txgain")) {
11215 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11216 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11217 }
11218 } else if (!strcasecmp(v->name, "tonezone")) {
11219 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11220 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11221 }
11222 } else if (!strcasecmp(v->name, "callerid")) {
11223 if (!strcasecmp(v->value, "asreceived")) {
11224 confp->chan.cid_num[0] = '\0';
11225 confp->chan.cid_name[0] = '\0';
11226 } else {
11227 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11228 }
11229 } else if (!strcasecmp(v->name, "fullname")) {
11230 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11231 } else if (!strcasecmp(v->name, "cid_number")) {
11232 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11233 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11234 confp->chan.dahditrcallerid = ast_true(v->value);
11235 if (strstr(v->name, "zap")) {
11236 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11237 }
11238 } else if (!strcasecmp(v->name, "restrictcid")) {
11239 confp->chan.restrictcid = ast_true(v->value);
11240 } else if (!strcasecmp(v->name, "usecallingpres")) {
11241 confp->chan.use_callingpres = ast_true(v->value);
11242 } else if (!strcasecmp(v->name, "accountcode")) {
11243 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11244 } else if (!strcasecmp(v->name, "amaflags")) {
11245 y = ast_cdr_amaflags2int(v->value);
11246 if (y < 0)
11247 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11248 else
11249 confp->chan.amaflags = y;
11250 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11251 confp->chan.polarityonanswerdelay = atoi(v->value);
11252 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11253 confp->chan.answeronpolarityswitch = ast_true(v->value);
11254 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11255 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11256 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11257 confp->chan.sendcalleridafter = atoi(v->value);
11258 } else if (reload != 1){
11259 if (!strcasecmp(v->name, "signalling")) {
11260 confp->chan.outsigmod = -1;
11261 if (!strcasecmp(v->value, "em")) {
11262 confp->chan.sig = SIG_EM;
11263 } else if (!strcasecmp(v->value, "em_e1")) {
11264 confp->chan.sig = SIG_EM_E1;
11265 } else if (!strcasecmp(v->value, "em_w")) {
11266 confp->chan.sig = SIG_EMWINK;
11267 confp->chan.radio = 0;
11268 } else if (!strcasecmp(v->value, "fxs_ls")) {
11269 confp->chan.sig = SIG_FXSLS;
11270 confp->chan.radio = 0;
11271 } else if (!strcasecmp(v->value, "fxs_gs")) {
11272 confp->chan.sig = SIG_FXSGS;
11273 confp->chan.radio = 0;
11274 } else if (!strcasecmp(v->value, "fxs_ks")) {
11275 confp->chan.sig = SIG_FXSKS;
11276 confp->chan.radio = 0;
11277 } else if (!strcasecmp(v->value, "fxo_ls")) {
11278 confp->chan.sig = SIG_FXOLS;
11279 confp->chan.radio = 0;
11280 } else if (!strcasecmp(v->value, "fxo_gs")) {
11281 confp->chan.sig = SIG_FXOGS;
11282 confp->chan.radio = 0;
11283 } else if (!strcasecmp(v->value, "fxo_ks")) {
11284 confp->chan.sig = SIG_FXOKS;
11285 confp->chan.radio = 0;
11286 } else if (!strcasecmp(v->value, "fxs_rx")) {
11287 confp->chan.sig = SIG_FXSKS;
11288 confp->chan.radio = 1;
11289 } else if (!strcasecmp(v->value, "fxo_rx")) {
11290 confp->chan.sig = SIG_FXOLS;
11291 confp->chan.radio = 1;
11292 } else if (!strcasecmp(v->value, "fxs_tx")) {
11293 confp->chan.sig = SIG_FXSLS;
11294 confp->chan.radio = 1;
11295 } else if (!strcasecmp(v->value, "fxo_tx")) {
11296 confp->chan.sig = SIG_FXOGS;
11297 confp->chan.radio = 1;
11298 } else if (!strcasecmp(v->value, "em_rx")) {
11299 confp->chan.sig = SIG_EM;
11300 confp->chan.radio = 1;
11301 } else if (!strcasecmp(v->value, "em_tx")) {
11302 confp->chan.sig = SIG_EM;
11303 confp->chan.radio = 1;
11304 } else if (!strcasecmp(v->value, "em_rxtx")) {
11305 confp->chan.sig = SIG_EM;
11306 confp->chan.radio = 2;
11307 } else if (!strcasecmp(v->value, "em_txrx")) {
11308 confp->chan.sig = SIG_EM;
11309 confp->chan.radio = 2;
11310 } else if (!strcasecmp(v->value, "sf")) {
11311 confp->chan.sig = SIG_SF;
11312 confp->chan.radio = 0;
11313 } else if (!strcasecmp(v->value, "sf_w")) {
11314 confp->chan.sig = SIG_SFWINK;
11315 confp->chan.radio = 0;
11316 } else if (!strcasecmp(v->value, "sf_featd")) {
11317 confp->chan.sig = SIG_FEATD;
11318 confp->chan.radio = 0;
11319 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11320 confp->chan.sig = SIG_FEATDMF;
11321 confp->chan.radio = 0;
11322 } else if (!strcasecmp(v->value, "sf_featb")) {
11323 confp->chan.sig = SIG_SF_FEATB;
11324 confp->chan.radio = 0;
11325 } else if (!strcasecmp(v->value, "sf")) {
11326 confp->chan.sig = SIG_SF;
11327 confp->chan.radio = 0;
11328 } else if (!strcasecmp(v->value, "sf_rx")) {
11329 confp->chan.sig = SIG_SF;
11330 confp->chan.radio = 1;
11331 } else if (!strcasecmp(v->value, "sf_tx")) {
11332 confp->chan.sig = SIG_SF;
11333 confp->chan.radio = 1;
11334 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11335 confp->chan.sig = SIG_SF;
11336 confp->chan.radio = 2;
11337 } else if (!strcasecmp(v->value, "sf_txrx")) {
11338 confp->chan.sig = SIG_SF;
11339 confp->chan.radio = 2;
11340 } else if (!strcasecmp(v->value, "featd")) {
11341 confp->chan.sig = SIG_FEATD;
11342 confp->chan.radio = 0;
11343 } else if (!strcasecmp(v->value, "featdmf")) {
11344 confp->chan.sig = SIG_FEATDMF;
11345 confp->chan.radio = 0;
11346 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11347 confp->chan.sig = SIG_FEATDMF_TA;
11348 confp->chan.radio = 0;
11349 } else if (!strcasecmp(v->value, "e911")) {
11350 confp->chan.sig = SIG_E911;
11351 confp->chan.radio = 0;
11352 } else if (!strcasecmp(v->value, "fgccama")) {
11353 confp->chan.sig = SIG_FGC_CAMA;
11354 confp->chan.radio = 0;
11355 } else if (!strcasecmp(v->value, "fgccamamf")) {
11356 confp->chan.sig = SIG_FGC_CAMAMF;
11357 confp->chan.radio = 0;
11358 } else if (!strcasecmp(v->value, "featb")) {
11359 confp->chan.sig = SIG_FEATB;
11360 confp->chan.radio = 0;
11361 #ifdef HAVE_PRI
11362 } else if (!strcasecmp(v->value, "pri_net")) {
11363 confp->chan.radio = 0;
11364 confp->chan.sig = SIG_PRI;
11365 confp->pri.nodetype = PRI_NETWORK;
11366 } else if (!strcasecmp(v->value, "pri_cpe")) {
11367 confp->chan.sig = SIG_PRI;
11368 confp->chan.radio = 0;
11369 confp->pri.nodetype = PRI_CPE;
11370 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11371 confp->chan.sig = SIG_GR303FXOKS;
11372 confp->chan.radio = 0;
11373 confp->pri.nodetype = PRI_NETWORK;
11374 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11375 confp->chan.sig = SIG_GR303FXSKS;
11376 confp->chan.radio = 0;
11377 confp->pri.nodetype = PRI_CPE;
11378 #endif
11379 } else {
11380 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11381 }
11382 } else if (!strcasecmp(v->name, "outsignalling")) {
11383 if (!strcasecmp(v->value, "em")) {
11384 confp->chan.outsigmod = SIG_EM;
11385 } else if (!strcasecmp(v->value, "em_e1")) {
11386 confp->chan.outsigmod = SIG_EM_E1;
11387 } else if (!strcasecmp(v->value, "em_w")) {
11388 confp->chan.outsigmod = SIG_EMWINK;
11389 } else if (!strcasecmp(v->value, "sf")) {
11390 confp->chan.outsigmod = SIG_SF;
11391 } else if (!strcasecmp(v->value, "sf_w")) {
11392 confp->chan.outsigmod = SIG_SFWINK;
11393 } else if (!strcasecmp(v->value, "sf_featd")) {
11394 confp->chan.outsigmod = SIG_FEATD;
11395 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11396 confp->chan.outsigmod = SIG_FEATDMF;
11397 } else if (!strcasecmp(v->value, "sf_featb")) {
11398 confp->chan.outsigmod = SIG_SF_FEATB;
11399 } else if (!strcasecmp(v->value, "sf")) {
11400 confp->chan.outsigmod = SIG_SF;
11401 } else if (!strcasecmp(v->value, "featd")) {
11402 confp->chan.outsigmod = SIG_FEATD;
11403 } else if (!strcasecmp(v->value, "featdmf")) {
11404 confp->chan.outsigmod = SIG_FEATDMF;
11405 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11406 confp->chan.outsigmod = SIG_FEATDMF_TA;
11407 } else if (!strcasecmp(v->value, "e911")) {
11408 confp->chan.outsigmod = SIG_E911;
11409 } else if (!strcasecmp(v->value, "fgccama")) {
11410 confp->chan.outsigmod = SIG_FGC_CAMA;
11411 } else if (!strcasecmp(v->value, "fgccamamf")) {
11412 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11413 } else if (!strcasecmp(v->value, "featb")) {
11414 confp->chan.outsigmod = SIG_FEATB;
11415 } else {
11416 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11417 }
11418 #ifdef HAVE_PRI
11419 } else if (!strcasecmp(v->name, "pridialplan")) {
11420 if (!strcasecmp(v->value, "national")) {
11421 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11422 } else if (!strcasecmp(v->value, "unknown")) {
11423 confp->pri.dialplan = PRI_UNKNOWN + 1;
11424 } else if (!strcasecmp(v->value, "private")) {
11425 confp->pri.dialplan = PRI_PRIVATE + 1;
11426 } else if (!strcasecmp(v->value, "international")) {
11427 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11428 } else if (!strcasecmp(v->value, "local")) {
11429 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11430 } else if (!strcasecmp(v->value, "dynamic")) {
11431 confp->pri.dialplan = -1;
11432 } else {
11433 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11434 }
11435 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11436 if (!strcasecmp(v->value, "national")) {
11437 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11438 } else if (!strcasecmp(v->value, "unknown")) {
11439 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11440 } else if (!strcasecmp(v->value, "private")) {
11441 confp->pri.localdialplan = PRI_PRIVATE + 1;
11442 } else if (!strcasecmp(v->value, "international")) {
11443 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11444 } else if (!strcasecmp(v->value, "local")) {
11445 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11446 } else if (!strcasecmp(v->value, "dynamic")) {
11447 confp->pri.localdialplan = -1;
11448 } else {
11449 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11450 }
11451 } else if (!strcasecmp(v->name, "switchtype")) {
11452 if (!strcasecmp(v->value, "national"))
11453 confp->pri.switchtype = PRI_SWITCH_NI2;
11454 else if (!strcasecmp(v->value, "ni1"))
11455 confp->pri.switchtype = PRI_SWITCH_NI1;
11456 else if (!strcasecmp(v->value, "dms100"))
11457 confp->pri.switchtype = PRI_SWITCH_DMS100;
11458 else if (!strcasecmp(v->value, "4ess"))
11459 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11460 else if (!strcasecmp(v->value, "5ess"))
11461 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11462 else if (!strcasecmp(v->value, "euroisdn"))
11463 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11464 else if (!strcasecmp(v->value, "qsig"))
11465 confp->pri.switchtype = PRI_SWITCH_QSIG;
11466 else {
11467 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11468 return -1;
11469 }
11470 } else if (!strcasecmp(v->name, "nsf")) {
11471 if (!strcasecmp(v->value, "sdn"))
11472 confp->pri.nsf = PRI_NSF_SDN;
11473 else if (!strcasecmp(v->value, "megacom"))
11474 confp->pri.nsf = PRI_NSF_MEGACOM;
11475 else if (!strcasecmp(v->value, "tollfreemegacom"))
11476 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11477 else if (!strcasecmp(v->value, "accunet"))
11478 confp->pri.nsf = PRI_NSF_ACCUNET;
11479 else if (!strcasecmp(v->value, "none"))
11480 confp->pri.nsf = PRI_NSF_NONE;
11481 else {
11482 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11483 confp->pri.nsf = PRI_NSF_NONE;
11484 }
11485 } else if (!strcasecmp(v->name, "priindication")) {
11486 if (!strcasecmp(v->value, "outofband"))
11487 confp->chan.priindication_oob = 1;
11488 else if (!strcasecmp(v->value, "inband"))
11489 confp->chan.priindication_oob = 0;
11490 else
11491 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11492 v->value, v->lineno);
11493 } else if (!strcasecmp(v->name, "priexclusive")) {
11494 confp->chan.priexclusive = ast_true(v->value);
11495 } else if (!strcasecmp(v->name, "internationalprefix")) {
11496 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11497 } else if (!strcasecmp(v->name, "nationalprefix")) {
11498 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11499 } else if (!strcasecmp(v->name, "localprefix")) {
11500 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11501 } else if (!strcasecmp(v->name, "privateprefix")) {
11502 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11503 } else if (!strcasecmp(v->name, "unknownprefix")) {
11504 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11505 } else if (!strcasecmp(v->name, "resetinterval")) {
11506 if (!strcasecmp(v->value, "never"))
11507 confp->pri.resetinterval = -1;
11508 else if (atoi(v->value) >= 60)
11509 confp->pri.resetinterval = atoi(v->value);
11510 else
11511 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11512 v->value, v->lineno);
11513 } else if (!strcasecmp(v->name, "minunused")) {
11514 confp->pri.minunused = atoi(v->value);
11515 } else if (!strcasecmp(v->name, "minidle")) {
11516 confp->pri.minidle = atoi(v->value);
11517 } else if (!strcasecmp(v->name, "idleext")) {
11518 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11519 } else if (!strcasecmp(v->name, "idledial")) {
11520 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11521 } else if (!strcasecmp(v->name, "overlapdial")) {
11522 confp->pri.overlapdial = ast_true(v->value);
11523 #ifdef HAVE_PRI_INBANDDISCONNECT
11524 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11525 confp->pri.inbanddisconnect = ast_true(v->value);
11526 #endif
11527 } else if (!strcasecmp(v->name, "pritimer")) {
11528 #ifdef PRI_GETSET_TIMERS
11529 char *timerc, *c;
11530 int timer, timeridx;
11531 c = v->value;
11532 timerc = strsep(&c, ",");
11533 if (timerc) {
11534 timer = atoi(c);
11535 if (!timer)
11536 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11537 else {
11538 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11539 pritimers[timeridx] = timer;
11540 else
11541 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11542 }
11543 } else
11544 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11545
11546 } else if (!strcasecmp(v->name, "facilityenable")) {
11547 confp->pri.facilityenable = ast_true(v->value);
11548 #endif
11549 #endif
11550 } else if (!strcasecmp(v->name, "cadence")) {
11551
11552 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11553 int i;
11554 struct dahdi_ring_cadence new_cadence;
11555 int cid_location = -1;
11556 int firstcadencepos = 0;
11557 char original_args[80];
11558 int cadence_is_ok = 1;
11559
11560 ast_copy_string(original_args, v->value, sizeof(original_args));
11561
11562 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]);
11563
11564
11565 if (element_count % 2 == 1) {
11566 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11567 cadence_is_ok = 0;
11568 }
11569
11570
11571 for (i = 0; i < element_count; i++) {
11572 if (c[i] == 0) {
11573 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11574 cadence_is_ok = 0;
11575 break;
11576 } else if (c[i] < 0) {
11577 if (i % 2 == 1) {
11578
11579 if (cid_location == -1) {
11580 cid_location = i;
11581 c[i] *= -1;
11582 } else {
11583 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11584 cadence_is_ok = 0;
11585 break;
11586 }
11587 } else {
11588 if (firstcadencepos == 0) {
11589 firstcadencepos = i;
11590
11591 } else {
11592 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11593 cadence_is_ok = 0;
11594 break;
11595 }
11596 }
11597 }
11598 }
11599
11600
11601 for (i = 0; i < 16; i++) {
11602 new_cadence.ringcadence[i] = c[i];
11603 }
11604
11605 if (cadence_is_ok) {
11606
11607 if (element_count < 2) {
11608 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11609 } else {
11610 if (cid_location == -1) {
11611
11612 cid_location = 1;
11613 } else {
11614
11615 cid_location = (cid_location + 1) / 2;
11616 }
11617
11618 if (!user_has_defined_cadences++)
11619
11620 num_cadence = 0;
11621 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11622 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11623 else {
11624 cadences[num_cadence] = new_cadence;
11625 cidrings[num_cadence++] = cid_location;
11626 if (option_verbose > 2)
11627 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11628 }
11629 }
11630 }
11631 } else if (!strcasecmp(v->name, "ringtimeout")) {
11632 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11633 } else if (!strcasecmp(v->name, "prewink")) {
11634 confp->timing.prewinktime = atoi(v->value);
11635 } else if (!strcasecmp(v->name, "preflash")) {
11636 confp->timing.preflashtime = atoi(v->value);
11637 } else if (!strcasecmp(v->name, "wink")) {
11638 confp->timing.winktime = atoi(v->value);
11639 } else if (!strcasecmp(v->name, "flash")) {
11640 confp->timing.flashtime = atoi(v->value);
11641 } else if (!strcasecmp(v->name, "start")) {
11642 confp->timing.starttime = atoi(v->value);
11643 } else if (!strcasecmp(v->name, "rxwink")) {
11644 confp->timing.rxwinktime = atoi(v->value);
11645 } else if (!strcasecmp(v->name, "rxflash")) {
11646 confp->timing.rxflashtime = atoi(v->value);
11647 } else if (!strcasecmp(v->name, "debounce")) {
11648 confp->timing.debouncetime = atoi(v->value);
11649 } else if (!strcasecmp(v->name, "toneduration")) {
11650 int toneduration;
11651 int ctlfd;
11652 int res;
11653 struct dahdi_dialparams dps;
11654
11655 #ifdef HAVE_ZAPTEL
11656 ctlfd = open("/dev/zap/ctl", O_RDWR);
11657 #else
11658 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11659 #endif
11660
11661 if (ctlfd == -1) {
11662 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11663 return -1;
11664 }
11665
11666 toneduration = atoi(v->value);
11667 if (toneduration > -1) {
11668 memset(&dps, 0, sizeof(dps));
11669
11670 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11671 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11672 if (res < 0) {
11673 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11674 return -1;
11675 }
11676 }
11677 close(ctlfd);
11678 } else if (!strcasecmp(v->name, "defaultcic")) {
11679 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11680 } else if (!strcasecmp(v->name, "defaultozz")) {
11681 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11682 }
11683 } else if (!skipchannels)
11684 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11685 }
11686 if (dahdichan[0]) {
11687
11688
11689 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11690 return -1;
11691 }
11692 }
11693
11694
11695 if (!found_pseudo && reload == 0) {
11696
11697
11698
11699 confp->chan.group = 0;
11700 confp->chan.callgroup = 0;
11701 confp->chan.pickupgroup = 0;
11702
11703 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11704
11705 if (tmp) {
11706 if (option_verbose > 2)
11707 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11708 } else {
11709 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11710 }
11711 }
11712 return 0;
11713 }
11714
11715 static int setup_dahdi(int reload)
11716 {
11717 struct ast_config *cfg;
11718 struct ast_variable *v;
11719 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11720 int res;
11721
11722 #ifdef HAVE_PRI
11723 char *c;
11724 int spanno;
11725 int i, x;
11726 int logicalspan;
11727 int trunkgroup;
11728 int dchannels[NUM_DCHANS];
11729 #endif
11730
11731 #ifdef HAVE_ZAPTEL
11732 int load_from_zapata_conf = 1;
11733 #else
11734 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11735 #endif
11736
11737 if (load_from_zapata_conf) {
11738 if (!(cfg = ast_config_load("zapata.conf"))) {
11739 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11740 return 0;
11741 }
11742 } else {
11743 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11744 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11745 return 0;
11746 }
11747 }
11748
11749
11750 ast_mutex_lock(&iflock);
11751 #ifdef HAVE_PRI
11752 if (reload != 1) {
11753
11754 v = ast_variable_browse(cfg, "trunkgroups");
11755 while (v) {
11756 if (!strcasecmp(v->name, "trunkgroup")) {
11757 trunkgroup = atoi(v->value);
11758 if (trunkgroup > 0) {
11759 if ((c = strchr(v->value, ','))) {
11760 i = 0;
11761 memset(dchannels, 0, sizeof(dchannels));
11762 while (c && (i < NUM_DCHANS)) {
11763 dchannels[i] = atoi(c + 1);
11764 if (dchannels[i] < 0) {
11765 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);
11766 } else
11767 i++;
11768 c = strchr(c + 1, ',');
11769 }
11770 if (i) {
11771 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11772 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);
11773 } else if (option_verbose > 1)
11774 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");
11775 } else
11776 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11777 } else
11778 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11779 } else
11780 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11781 } else if (!strcasecmp(v->name, "spanmap")) {
11782 spanno = atoi(v->value);
11783 if (spanno > 0) {
11784 if ((c = strchr(v->value, ','))) {
11785 trunkgroup = atoi(c + 1);
11786 if (trunkgroup > 0) {
11787 if ((c = strchr(c + 1, ',')))
11788 logicalspan = atoi(c + 1);
11789 else
11790 logicalspan = 0;
11791 if (logicalspan >= 0) {
11792 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11793 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11794 } else if (option_verbose > 1)
11795 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11796 } else
11797 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);
11798 } else
11799 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11800 } else
11801 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11802 } else
11803 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11804 } else {
11805 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11806 }
11807 v = v->next;
11808 }
11809 }
11810 #endif
11811
11812
11813 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11814
11815 v = ast_variable_browse(cfg, "channels");
11816 res = process_dahdi(&conf, "", v, reload, 0);
11817 ast_mutex_unlock(&iflock);
11818 ast_config_destroy(cfg);
11819 if (res)
11820 return res;
11821 cfg = ast_config_load("users.conf");
11822 if (cfg) {
11823 char *cat;
11824 const char *chans;
11825 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11826 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11827 if (!strcasecmp(cat, "general"))
11828 continue;
11829 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11830 if (!ast_strlen_zero(chans)) {
11831 struct dahdi_chan_conf sect_conf;
11832 memcpy(§_conf, &conf, sizeof(sect_conf));
11833
11834 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11835 }
11836 }
11837 ast_config_destroy(cfg);
11838 }
11839 #ifdef HAVE_PRI
11840 if (reload != 1) {
11841 for (x = 0; x < NUM_SPANS; x++) {
11842 if (pris[x].pvts[0]) {
11843 if (start_pri(pris + x)) {
11844 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11845 return -1;
11846 } else if (option_verbose > 1)
11847 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11848 }
11849 }
11850 }
11851 #endif
11852
11853 restart_monitor();
11854 return 0;
11855 }
11856
11857 #define local_astman_register(a, b, c, d) do { \
11858 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11859 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11860 } \
11861 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11862 } while (0)
11863
11864 static int load_module(void)
11865 {
11866 int res;
11867
11868 #ifdef HAVE_PRI
11869 int y,i;
11870 memset(pris, 0, sizeof(pris));
11871 for (y = 0; y < NUM_SPANS; y++) {
11872 ast_mutex_init(&pris[y].lock);
11873 pris[y].offset = -1;
11874 pris[y].master = AST_PTHREADT_NULL;
11875 for (i = 0; i < NUM_DCHANS; i++)
11876 pris[y].fds[i] = -1;
11877 }
11878 pri_set_error(dahdi_pri_error);
11879 pri_set_message(dahdi_pri_message);
11880 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11881 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11882 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11883 }
11884 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11885 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11886 #endif
11887 if ((res = setup_dahdi(0))) {
11888 return AST_MODULE_LOAD_DECLINE;
11889 }
11890 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11891 chan_tech = &dahdi_tech;
11892 } else {
11893 chan_tech = &zap_tech;
11894 }
11895 if (ast_channel_register(chan_tech)) {
11896 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11897 __unload_module();
11898 return -1;
11899 }
11900 #ifdef HAVE_PRI
11901 ast_string_field_init(&inuse, 16);
11902 ast_string_field_set(&inuse, name, "GR-303InUse");
11903 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11904 #endif
11905 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11906
11907 memset(round_robin, 0, sizeof(round_robin));
11908 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11909 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11910 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11911 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11912 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11913 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11914 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11915
11916 ast_cond_init(&ss_thread_complete, NULL);
11917
11918 return res;
11919 }
11920
11921 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11922 {
11923 #define END_SILENCE_LEN 400
11924 #define HEADER_MS 50
11925 #define TRAILER_MS 5
11926 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11927 #define ASCII_BYTES_PER_CHAR 80
11928
11929 unsigned char *buf,*mybuf;
11930 struct dahdi_pvt *p = c->tech_pvt;
11931 struct pollfd fds[1];
11932 int size,res,fd,len,x;
11933 int bytes=0;
11934
11935 float cr = 1.0;
11936 float ci = 0.0;
11937 float scont = 0.0;
11938 int index;
11939
11940 index = dahdi_get_index(c, p, 0);
11941 if (index < 0) {
11942 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11943 return -1;
11944 }
11945 if (!text[0]) return(0);
11946 if ((!p->tdd) && (!p->mate)) return(0);
11947 if (p->mate)
11948 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11949 else
11950 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11951 if (!buf)
11952 return -1;
11953 mybuf = buf;
11954 if (p->mate) {
11955 int codec = AST_LAW(p);
11956 for (x = 0; x < HEADER_MS; x++) {
11957 PUT_CLID_MARKMS;
11958 }
11959
11960 for (x = 0; text[x]; x++) {
11961 PUT_CLID(text[x]);
11962 }
11963 for (x = 0; x < TRAILER_MS; x++) {
11964 PUT_CLID_MARKMS;
11965 }
11966 len = bytes;
11967 buf = mybuf;
11968 } else {
11969 len = tdd_generate(p->tdd, buf, text);
11970 if (len < 1) {
11971 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11972 free(mybuf);
11973 return -1;
11974 }
11975 }
11976 memset(buf + len, 0x7f, END_SILENCE_LEN);
11977 len += END_SILENCE_LEN;
11978 fd = p->subs[index].dfd;
11979 while (len) {
11980 if (ast_check_hangup(c)) {
11981 free(mybuf);
11982 return -1;
11983 }
11984 size = len;
11985 if (size > READ_SIZE)
11986 size = READ_SIZE;
11987 fds[0].fd = fd;
11988 fds[0].events = POLLOUT | POLLPRI;
11989 fds[0].revents = 0;
11990 res = poll(fds, 1, -1);
11991 if (!res) {
11992 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11993 continue;
11994 }
11995
11996 if (fds[0].revents & POLLPRI) {
11997 ast_free(mybuf);
11998 return -1;
11999 }
12000 if (!(fds[0].revents & POLLOUT)) {
12001 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12002 continue;
12003 }
12004 res = write(fd, buf, size);
12005 if (res != size) {
12006 if (res == -1) {
12007 free(mybuf);
12008 return -1;
12009 }
12010 if (option_debug)
12011 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12012 break;
12013 }
12014 len -= size;
12015 buf += size;
12016 }
12017 free(mybuf);
12018 return(0);
12019 }
12020
12021
12022 static int reload(void)
12023 {
12024 int res = 0;
12025
12026 res = setup_dahdi(1);
12027 if (res) {
12028 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12029 return -1;
12030 }
12031 return 0;
12032 }
12033
12034
12035
12036
12037
12038 #ifdef DAHDI_PRI
12039 #define tdesc "DAHDI Telephony w/PRI"
12040 #else
12041 #define tdesc "DAHDI Telephony"
12042 #endif
12043
12044 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12045 .load = load_module,
12046 .unload = unload_module,
12047 .reload = reload,
12048 );
12049
12050