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: 224337 $")
00051
00052 #ifdef __NetBSD__
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103
00104 #define SMDI_MD_WAIT_TIMEOUT 1500
00105
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116
00117
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120 .flags = 0,
00121 .max_size = -1,
00122 .resync_threshold = -1,
00123 .impl = ""
00124 };
00125 static struct ast_jb_conf global_jbconf;
00126
00127
00128 #undef SUPPORT_USERUSER
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 #define DEFAULT_CIDRINGS 1
00150
00151 #define CHANNEL_PSEUDO -12
00152
00153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00154
00155
00156
00157 #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))
00158
00159 static const char tdesc[] = "DAHDI Telephony Driver"
00160 #ifdef HAVE_PRI
00161 " w/PRI"
00162 #endif
00163 #ifdef HAVE_SS7
00164 " w/SS7"
00165 #endif
00166 ;
00167
00168 static const char config[] = "chan_dahdi.conf";
00169
00170 #define SIG_EM DAHDI_SIG_EM
00171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI DAHDI_SIG_CLEAR
00186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SF DAHDI_SIG_SF
00190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00197
00198 #ifdef LOTS_OF_SPANS
00199 #define NUM_SPANS DAHDI_MAX_SPANS
00200 #else
00201 #define NUM_SPANS 32
00202 #endif
00203 #define NUM_DCHANS 4
00204 #define MAX_CHANNELS 672
00205
00206 #define CHAN_PSEUDO -2
00207
00208 #define DCHAN_PROVISIONED (1 << 0)
00209 #define DCHAN_NOTINALARM (1 << 1)
00210 #define DCHAN_UP (1 << 2)
00211
00212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00213
00214
00215 #define DAHDI_OVERLAPDIAL_NONE 0
00216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00217 #define DAHDI_OVERLAPDIAL_INCOMING 2
00218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00219
00220
00221 #define CALLPROGRESS_PROGRESS 1
00222 #define CALLPROGRESS_FAX_OUTGOING 2
00223 #define CALLPROGRESS_FAX_INCOMING 4
00224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00225
00226 static char defaultcic[64] = "";
00227 static char defaultozz[64] = "";
00228
00229
00230 static char mwimonitornotify[PATH_MAX] = "";
00231
00232 static char progzone[10] = "";
00233
00234 static int usedistinctiveringdetection = 0;
00235 static int distinctiveringaftercid = 0;
00236
00237 static int numbufs = 4;
00238
00239 static int mwilevel = 512;
00240
00241 #ifdef HAVE_PRI
00242 static struct ast_channel inuse;
00243 #ifdef PRI_GETSET_TIMERS
00244 static int pritimers[PRI_MAX_TIMERS];
00245 #endif
00246 static int pridebugfd = -1;
00247 static char pridebugfilename[1024] = "";
00248 #endif
00249
00250
00251 static int firstdigittimeout = 16000;
00252
00253
00254 static int gendigittimeout = 8000;
00255
00256
00257 static int matchdigittimeout = 3000;
00258
00259
00260 AST_MUTEX_DEFINE_STATIC(iflock);
00261
00262
00263 static int ifcount = 0;
00264
00265 #ifdef HAVE_PRI
00266 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00267 #endif
00268
00269
00270
00271 AST_MUTEX_DEFINE_STATIC(monlock);
00272
00273
00274
00275 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00276 static ast_cond_t ss_thread_complete;
00277 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00278 AST_MUTEX_DEFINE_STATIC(restart_lock);
00279 static int ss_thread_count = 0;
00280 static int num_restart_pending = 0;
00281
00282 static int restart_monitor(void);
00283
00284 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);
00285
00286 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00287
00288 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00289 {
00290
00291
00292
00293
00294 }
00295
00296
00297 static inline int dahdi_get_event(int fd)
00298 {
00299 int j;
00300 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00301 return -1;
00302 return j;
00303 }
00304
00305
00306 static inline int dahdi_wait_event(int fd)
00307 {
00308 int i, j = 0;
00309 i = DAHDI_IOMUX_SIGEVENT;
00310 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00311 return -1;
00312 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00313 return -1;
00314 return j;
00315 }
00316
00317
00318 #define READ_SIZE 160
00319
00320 #define MASK_AVAIL (1 << 0)
00321 #define MASK_INUSE (1 << 1)
00322
00323 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00324 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00325 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00326 #define MIN_MS_SINCE_FLASH ( (2000) )
00327 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00328
00329 struct dahdi_pvt;
00330
00331
00332
00333
00334
00335 static int ringt_base = DEFAULT_RINGT;
00336
00337 #ifdef HAVE_SS7
00338
00339 #define LINKSTATE_INALARM (1 << 0)
00340 #define LINKSTATE_STARTING (1 << 1)
00341 #define LINKSTATE_UP (1 << 2)
00342 #define LINKSTATE_DOWN (1 << 3)
00343
00344 #define SS7_NAI_DYNAMIC -1
00345
00346 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00347
00348 struct dahdi_ss7 {
00349 pthread_t master;
00350 ast_mutex_t lock;
00351 int fds[NUM_DCHANS];
00352 int numsigchans;
00353 int linkstate[NUM_DCHANS];
00354 int numchans;
00355 int type;
00356 enum {
00357 LINKSET_STATE_DOWN = 0,
00358 LINKSET_STATE_UP
00359 } state;
00360 char called_nai;
00361 char calling_nai;
00362 char internationalprefix[10];
00363 char nationalprefix[10];
00364 char subscriberprefix[20];
00365 char unknownprefix[20];
00366 struct ss7 *ss7;
00367 struct dahdi_pvt *pvts[MAX_CHANNELS];
00368 int flags;
00369 };
00370
00371 static struct dahdi_ss7 linksets[NUM_SPANS];
00372
00373 static int cur_ss7type = -1;
00374 static int cur_linkset = -1;
00375 static int cur_pointcode = -1;
00376 static int cur_cicbeginswith = -1;
00377 static int cur_adjpointcode = -1;
00378 static int cur_networkindicator = -1;
00379 static int cur_defaultdpc = -1;
00380 #endif
00381
00382 #ifdef HAVE_PRI
00383
00384 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00385 #define PRI_CHANNEL(p) ((p) & 0xff)
00386 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00387 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00388
00389 struct dahdi_pri {
00390 pthread_t master;
00391 ast_mutex_t lock;
00392 char idleext[AST_MAX_EXTENSION];
00393 char idlecontext[AST_MAX_CONTEXT];
00394 char idledial[AST_MAX_EXTENSION];
00395 int minunused;
00396 int minidle;
00397 int nodetype;
00398 int switchtype;
00399 int nsf;
00400 int dialplan;
00401 int localdialplan;
00402 char internationalprefix[10];
00403 char nationalprefix[10];
00404 char localprefix[20];
00405 char privateprefix[20];
00406 char unknownprefix[20];
00407 int dchannels[NUM_DCHANS];
00408 int trunkgroup;
00409 int mastertrunkgroup;
00410 int prilogicalspan;
00411 int numchans;
00412 int overlapdial;
00413 int facilityenable;
00414 struct pri *dchans[NUM_DCHANS];
00415 int dchanavail[NUM_DCHANS];
00416 struct pri *pri;
00417
00418 int debug;
00419 int fds[NUM_DCHANS];
00420
00421 int offset;
00422
00423 int span;
00424
00425 int resetting;
00426
00427 int resetpos;
00428 #ifdef HAVE_PRI_INBANDDISCONNECT
00429 unsigned int inbanddisconnect:1;
00430 #endif
00431 time_t lastreset;
00432 long resetinterval;
00433
00434 int sig;
00435 struct dahdi_pvt *pvts[MAX_CHANNELS];
00436 struct dahdi_pvt *crvs;
00437 struct dahdi_pvt *crvend;
00438 };
00439
00440
00441 static struct dahdi_pri pris[NUM_SPANS];
00442
00443 #if 0
00444 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00445 #else
00446 #define DEFAULT_PRI_DEBUG 0
00447 #endif
00448
00449 static inline void pri_rel(struct dahdi_pri *pri)
00450 {
00451 ast_mutex_unlock(&pri->lock);
00452 }
00453
00454 #else
00455
00456 struct dahdi_pri;
00457 #endif
00458
00459 #define SUB_REAL 0
00460 #define SUB_CALLWAIT 1
00461 #define SUB_THREEWAY 2
00462
00463
00464 #define POLARITY_IDLE 0
00465 #define POLARITY_REV 1
00466
00467
00468 struct distRingData {
00469 int ring[3];
00470 int range;
00471 };
00472 struct ringContextData {
00473 char contextData[AST_MAX_CONTEXT];
00474 };
00475 struct dahdi_distRings {
00476 struct distRingData ringnum[3];
00477 struct ringContextData ringContext[3];
00478 };
00479
00480 static char *subnames[] = {
00481 "Real",
00482 "Callwait",
00483 "Threeway"
00484 };
00485
00486 struct dahdi_subchannel {
00487 int dfd;
00488 struct ast_channel *owner;
00489 int chan;
00490 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00491 struct ast_frame f;
00492 unsigned int needringing:1;
00493 unsigned int needbusy:1;
00494 unsigned int needcongestion:1;
00495 unsigned int needcallerid:1;
00496 unsigned int needanswer:1;
00497 unsigned int needflash:1;
00498 unsigned int needhold:1;
00499 unsigned int needunhold:1;
00500 unsigned int linear:1;
00501 unsigned int inthreeway:1;
00502 struct dahdi_confinfo curconf;
00503 };
00504
00505 #define CONF_USER_REAL (1 << 0)
00506 #define CONF_USER_THIRDCALL (1 << 1)
00507
00508 #define MAX_SLAVES 4
00509
00510 static struct dahdi_pvt {
00511 ast_mutex_t lock;
00512 struct ast_channel *owner;
00513
00514
00515 struct dahdi_subchannel sub_unused;
00516 struct dahdi_subchannel subs[3];
00517 struct dahdi_confinfo saveconf;
00518
00519 struct dahdi_pvt *slaves[MAX_SLAVES];
00520 struct dahdi_pvt *master;
00521 int inconference;
00522
00523 int buf_no;
00524 int buf_policy;
00525 int sig;
00526
00527
00528
00529
00530 int radio;
00531 int outsigmod;
00532 int oprmode;
00533 struct dahdi_pvt *oprpeer;
00534
00535 float cid_rxgain;
00536
00537 float rxgain;
00538
00539 float txgain;
00540 int tonezone;
00541 struct dahdi_pvt *next;
00542 struct dahdi_pvt *prev;
00543
00544
00545
00546
00547
00548
00549
00550 unsigned int adsi:1;
00551
00552
00553
00554
00555
00556 unsigned int answeronpolarityswitch:1;
00557
00558
00559
00560
00561
00562 unsigned int busydetect:1;
00563
00564
00565
00566
00567
00568 unsigned int callreturn:1;
00569
00570
00571
00572
00573
00574
00575 unsigned int callwaiting:1;
00576
00577
00578
00579
00580 unsigned int callwaitingcallerid:1;
00581
00582
00583
00584
00585
00586
00587 unsigned int cancallforward:1;
00588
00589
00590
00591
00592 unsigned int canpark:1;
00593
00594 unsigned int confirmanswer:1;
00595
00596
00597
00598
00599 unsigned int destroy:1;
00600 unsigned int didtdd:1;
00601
00602 unsigned int dialednone:1;
00603
00604 unsigned int dialing:1;
00605
00606 unsigned int digital:1;
00607
00608 unsigned int dnd:1;
00609
00610 unsigned int echobreak:1;
00611
00612
00613
00614
00615
00616 unsigned int echocanbridged:1;
00617
00618 unsigned int echocanon:1;
00619
00620 unsigned int faxhandled:1;
00621
00622 unsigned int firstradio:1;
00623
00624
00625
00626
00627 unsigned int hanguponpolarityswitch:1;
00628
00629 unsigned int hardwaredtmf:1;
00630
00631
00632
00633
00634
00635
00636 unsigned int hidecallerid:1;
00637
00638
00639
00640
00641
00642 unsigned int hidecalleridname:1;
00643
00644 unsigned int ignoredtmf:1;
00645
00646
00647
00648
00649
00650 unsigned int immediate:1;
00651
00652 unsigned int inalarm:1;
00653
00654 unsigned int mate:1;
00655
00656 unsigned int outgoing:1;
00657
00658
00659
00660
00661
00662
00663 unsigned int permcallwaiting:1;
00664
00665
00666
00667
00668 unsigned int permhidecallerid:1;
00669
00670
00671
00672
00673 unsigned int priindication_oob:1;
00674
00675
00676
00677
00678 unsigned int priexclusive:1;
00679
00680
00681
00682
00683 unsigned int pulse:1;
00684
00685 unsigned int pulsedial:1;
00686 unsigned int restartpending:1;
00687
00688
00689
00690
00691
00692 unsigned int restrictcid:1;
00693
00694
00695
00696
00697 unsigned int threewaycalling:1;
00698
00699
00700
00701
00702
00703
00704
00705
00706 unsigned int transfer:1;
00707
00708
00709
00710
00711
00712
00713
00714 unsigned int use_callerid:1;
00715
00716
00717
00718
00719
00720
00721 unsigned int use_callingpres:1;
00722
00723
00724
00725
00726
00727 unsigned int usedistinctiveringdetection:1;
00728
00729
00730
00731
00732 unsigned int dahditrcallerid:1;
00733
00734
00735
00736
00737 unsigned int transfertobusy:1;
00738
00739
00740
00741
00742 unsigned int mwimonitor_neon:1;
00743
00744
00745
00746
00747 unsigned int mwimonitor_fsk:1;
00748
00749 unsigned int mwimonitoractive:1;
00750
00751
00752
00753
00754 unsigned int inservice:1;
00755
00756
00757
00758
00759 unsigned int locallyblocked:1;
00760
00761
00762
00763
00764 unsigned int remotelyblocked:1;
00765 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00766
00767
00768
00769
00770 unsigned int rlt:1;
00771
00772 unsigned int alerting:1;
00773
00774 unsigned int alreadyhungup:1;
00775
00776
00777
00778
00779 unsigned int isidlecall:1;
00780
00781
00782
00783
00784 unsigned int proceeding:1;
00785
00786 unsigned int progress:1;
00787
00788
00789
00790
00791 unsigned int resetting:1;
00792
00793
00794
00795
00796 unsigned int setup_ack:1;
00797 #endif
00798
00799
00800
00801
00802 unsigned int use_smdi:1;
00803
00804 struct ast_smdi_interface *smdi_iface;
00805
00806
00807 struct dahdi_distRings drings;
00808
00809
00810
00811
00812
00813 char context[AST_MAX_CONTEXT];
00814
00815
00816
00817 char defcontext[AST_MAX_CONTEXT];
00818
00819 char exten[AST_MAX_EXTENSION];
00820
00821
00822
00823
00824 char language[MAX_LANGUAGE];
00825
00826
00827
00828
00829 char mohinterpret[MAX_MUSICCLASS];
00830
00831
00832
00833
00834 char mohsuggest[MAX_MUSICCLASS];
00835 #if defined(PRI_ANI) || defined(HAVE_SS7)
00836
00837 char cid_ani[AST_MAX_EXTENSION];
00838 #endif
00839
00840 int cid_ani2;
00841
00842 char cid_num[AST_MAX_EXTENSION];
00843
00844 int cid_ton;
00845
00846 char cid_name[AST_MAX_EXTENSION];
00847
00848 char lastcid_num[AST_MAX_EXTENSION];
00849
00850 char lastcid_name[AST_MAX_EXTENSION];
00851 char *origcid_num;
00852 char *origcid_name;
00853
00854 char callwait_num[AST_MAX_EXTENSION];
00855
00856 char callwait_name[AST_MAX_EXTENSION];
00857
00858 char rdnis[AST_MAX_EXTENSION];
00859
00860 char dnid[AST_MAX_EXTENSION];
00861
00862
00863
00864
00865 ast_group_t group;
00866
00867 int law;
00868 int confno;
00869 int confusers;
00870 int propconfno;
00871
00872
00873
00874
00875 ast_group_t callgroup;
00876
00877
00878
00879
00880 ast_group_t pickupgroup;
00881
00882
00883
00884
00885 struct ast_variable *vars;
00886 int channel;
00887 int span;
00888 time_t guardtime;
00889 int cid_signalling;
00890 int cid_start;
00891 int callingpres;
00892 int callwaitingrepeat;
00893 int cidcwexpire;
00894
00895 unsigned char *cidspill;
00896
00897 int cidpos;
00898
00899 int cidlen;
00900
00901 int ringt;
00902
00903
00904
00905
00906 int ringt_base;
00907
00908
00909
00910
00911
00912
00913 int stripmsd;
00914
00915 int callwaitcas;
00916
00917 int callwaitrings;
00918
00919 struct {
00920 struct dahdi_echocanparams head;
00921 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00922 } echocancel;
00923
00924
00925
00926
00927 int echotraining;
00928
00929 char echorest[20];
00930
00931
00932
00933
00934 int busycount;
00935
00936
00937
00938
00939 int busy_tonelength;
00940
00941
00942
00943
00944 int busy_quietlength;
00945
00946
00947
00948
00949 int callprogress;
00950 struct timeval flashtime;
00951
00952 struct ast_dsp *dsp;
00953
00954
00955 struct dahdi_dialoperation dop;
00956 int whichwink;
00957
00958 char finaldial[64];
00959 char accountcode[AST_MAX_ACCOUNT_CODE];
00960 int amaflags;
00961 struct tdd_state *tdd;
00962
00963 char call_forward[AST_MAX_EXTENSION];
00964
00965
00966
00967
00968 char mailbox[AST_MAX_EXTENSION];
00969
00970 struct ast_event_sub *mwi_event_sub;
00971
00972 char dialdest[256];
00973
00974 int onhooktime;
00975
00976 int msgstate;
00977 int distinctivering;
00978 int cidrings;
00979 int dtmfrelax;
00980
00981 int fake_event;
00982
00983
00984
00985
00986 int polarityonanswerdelay;
00987
00988 struct timeval polaritydelaytv;
00989
00990
00991
00992
00993 int sendcalleridafter;
00994 #ifdef HAVE_PRI
00995
00996 struct dahdi_pri *pri;
00997
00998 struct dahdi_pvt *bearer;
00999
01000 struct dahdi_pvt *realcall;
01001
01002 q931_call *call;
01003
01004 int prioffset;
01005
01006 int logicalspan;
01007 #endif
01008
01009 int polarity;
01010
01011 int dsp_features;
01012 #ifdef HAVE_SS7
01013
01014 struct dahdi_ss7 *ss7;
01015
01016 struct isup_call *ss7call;
01017 char charge_number[50];
01018 char gen_add_number[50];
01019 char gen_dig_number[50];
01020 char orig_called_num[50];
01021 char redirecting_num[50];
01022 char generic_name[50];
01023 unsigned char gen_add_num_plan;
01024 unsigned char gen_add_nai;
01025 unsigned char gen_add_pres_ind;
01026 unsigned char gen_add_type;
01027 unsigned char gen_dig_type;
01028 unsigned char gen_dig_scheme;
01029 char jip_number[50];
01030 unsigned char lspi_type;
01031 unsigned char lspi_scheme;
01032 unsigned char lspi_context;
01033 char lspi_ident[50];
01034 unsigned int call_ref_ident;
01035 unsigned int call_ref_pc;
01036 unsigned char calling_party_cat;
01037 int transcap;
01038 int cic;
01039 unsigned int dpc;
01040 unsigned int loopedback:1;
01041 #endif
01042
01043 char begindigit;
01044 } *iflist = NULL, *ifend = NULL;
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 struct dahdi_chan_conf {
01057 struct dahdi_pvt chan;
01058 #ifdef HAVE_PRI
01059 struct dahdi_pri pri;
01060 #endif
01061
01062 #ifdef HAVE_SS7
01063 struct dahdi_ss7 ss7;
01064 #endif
01065 struct dahdi_params timing;
01066 int is_sig_auto;
01067
01068
01069
01070
01071
01072 char smdi_port[SMDI_MAX_FILENAME_LEN];
01073 };
01074
01075
01076 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01077
01078
01079
01080 struct dahdi_chan_conf conf = {
01081 #ifdef HAVE_PRI
01082 .pri = {
01083 .nsf = PRI_NSF_NONE,
01084 .switchtype = PRI_SWITCH_NI2,
01085 .dialplan = PRI_NATIONAL_ISDN + 1,
01086 .localdialplan = PRI_NATIONAL_ISDN + 1,
01087 .nodetype = PRI_CPE,
01088
01089 .minunused = 2,
01090 .idleext = "",
01091 .idledial = "",
01092 .internationalprefix = "",
01093 .nationalprefix = "",
01094 .localprefix = "",
01095 .privateprefix = "",
01096 .unknownprefix = "",
01097 .resetinterval = -1,
01098 },
01099 #endif
01100 #ifdef HAVE_SS7
01101 .ss7 = {
01102 .called_nai = SS7_NAI_NATIONAL,
01103 .calling_nai = SS7_NAI_NATIONAL,
01104 .internationalprefix = "",
01105 .nationalprefix = "",
01106 .subscriberprefix = "",
01107 .unknownprefix = ""
01108 },
01109 #endif
01110 .chan = {
01111 .context = "default",
01112 .cid_num = "",
01113 .cid_name = "",
01114 .mohinterpret = "default",
01115 .mohsuggest = "",
01116 .transfertobusy = 1,
01117
01118 .cid_signalling = CID_SIG_BELL,
01119 .cid_start = CID_START_RING,
01120 .dahditrcallerid = 0,
01121 .use_callerid = 1,
01122 .sig = -1,
01123 .outsigmod = -1,
01124
01125 .cid_rxgain = +5.0,
01126
01127 .tonezone = -1,
01128
01129 .echocancel.head.tap_length = 1,
01130
01131 .busycount = 3,
01132
01133 .accountcode = "",
01134
01135 .mailbox = "",
01136
01137
01138 .polarityonanswerdelay = 600,
01139
01140 .sendcalleridafter = DEFAULT_CIDRINGS,
01141
01142 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01143 .buf_no = numbufs
01144 },
01145 .timing = {
01146 .prewinktime = -1,
01147 .preflashtime = -1,
01148 .winktime = -1,
01149 .flashtime = -1,
01150 .starttime = -1,
01151 .rxwinktime = -1,
01152 .rxflashtime = -1,
01153 .debouncetime = -1
01154 },
01155 .is_sig_auto = 1,
01156 .smdi_port = "/dev/ttyS0",
01157 };
01158
01159 return conf;
01160 }
01161
01162
01163 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01164 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01165 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01166 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01167 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01168 static int dahdi_hangup(struct ast_channel *ast);
01169 static int dahdi_answer(struct ast_channel *ast);
01170 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01171 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01172 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01173 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01174 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01175 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01176 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01177
01178 static const struct ast_channel_tech dahdi_tech = {
01179 .type = "DAHDI",
01180 .description = tdesc,
01181 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01182 .requester = dahdi_request,
01183 .send_digit_begin = dahdi_digit_begin,
01184 .send_digit_end = dahdi_digit_end,
01185 .send_text = dahdi_sendtext,
01186 .call = dahdi_call,
01187 .hangup = dahdi_hangup,
01188 .answer = dahdi_answer,
01189 .read = dahdi_read,
01190 .write = dahdi_write,
01191 .bridge = dahdi_bridge,
01192 .exception = dahdi_exception,
01193 .indicate = dahdi_indicate,
01194 .fixup = dahdi_fixup,
01195 .setoption = dahdi_setoption,
01196 .func_channel_read = dahdi_func_read,
01197 };
01198
01199 #ifdef HAVE_PRI
01200 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01201 #else
01202 #define GET_CHANNEL(p) ((p)->channel)
01203 #endif
01204
01205 struct dahdi_pvt *round_robin[32];
01206
01207 #ifdef HAVE_PRI
01208 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01209 {
01210 int res;
01211
01212 do {
01213 res = ast_mutex_trylock(&pri->lock);
01214 if (res) {
01215 DEADLOCK_AVOIDANCE(&pvt->lock);
01216 }
01217 } while (res);
01218
01219 if (pri->master != AST_PTHREADT_NULL)
01220 pthread_kill(pri->master, SIGURG);
01221 return 0;
01222 }
01223 #endif
01224
01225 #ifdef HAVE_SS7
01226 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01227 {
01228 ast_mutex_unlock(&ss7->lock);
01229 }
01230
01231 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01232 {
01233 int res;
01234
01235 do {
01236 res = ast_mutex_trylock(&pri->lock);
01237 if (res) {
01238 ast_mutex_unlock(&pvt->lock);
01239
01240 usleep(1);
01241 ast_mutex_lock(&pvt->lock);
01242 }
01243 } while (res);
01244
01245 if (pri->master != AST_PTHREADT_NULL)
01246 pthread_kill(pri->master, SIGURG);
01247 return 0;
01248 }
01249 #endif
01250 #define NUM_CADENCE_MAX 25
01251 static int num_cadence = 4;
01252 static int user_has_defined_cadences = 0;
01253
01254 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01255 { { 125, 125, 2000, 4000 } },
01256 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01257 { { 125, 125, 125, 125, 125, 4000 } },
01258 { { 1000, 500, 2500, 5000 } },
01259 };
01260
01261
01262
01263
01264
01265 static int cidrings[NUM_CADENCE_MAX] = {
01266 2,
01267 4,
01268 3,
01269 2,
01270 };
01271
01272 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01273 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01274
01275 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01276 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01277
01278 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01279 {
01280 int res;
01281 if (p->subs[SUB_REAL].owner == ast)
01282 res = 0;
01283 else if (p->subs[SUB_CALLWAIT].owner == ast)
01284 res = 1;
01285 else if (p->subs[SUB_THREEWAY].owner == ast)
01286 res = 2;
01287 else {
01288 res = -1;
01289 if (!nullok)
01290 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01291 }
01292 return res;
01293 }
01294
01295 #ifdef HAVE_PRI
01296 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01297 #else
01298 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01299 #endif
01300 {
01301 #ifdef HAVE_PRI
01302 if (pri)
01303 ast_mutex_unlock(&pri->lock);
01304 #endif
01305 for (;;) {
01306 if (p->subs[a].owner) {
01307 if (ast_channel_trylock(p->subs[a].owner)) {
01308 DEADLOCK_AVOIDANCE(&p->lock);
01309 } else {
01310 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01311 ast_channel_unlock(p->subs[a].owner);
01312 break;
01313 }
01314 } else
01315 break;
01316 }
01317 #ifdef HAVE_PRI
01318 if (pri)
01319 ast_mutex_lock(&pri->lock);
01320 #endif
01321 }
01322
01323 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01324 {
01325 #ifdef HAVE_PRI
01326 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01327 #endif
01328 #ifdef HAVE_SS7
01329 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01330 #endif
01331
01332 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01333 if (data) {
01334 switch (p->sig) {
01335 #ifdef HAVE_PRI
01336 case SIG_BRI:
01337 case SIG_BRI_PTMP:
01338 case SIG_PRI:
01339 ast_mutex_unlock(&pri->lock);
01340 break;
01341 #endif
01342 #ifdef HAVE_SS7
01343 case SIG_SS7:
01344 ast_mutex_unlock(&ss7->lock);
01345 break;
01346 #endif
01347 default:
01348 break;
01349 }
01350 }
01351 #endif
01352 for (;;) {
01353 if (p->owner) {
01354 if (ast_channel_trylock(p->owner)) {
01355 DEADLOCK_AVOIDANCE(&p->lock);
01356 } else {
01357 ast_queue_frame(p->owner, f);
01358 ast_channel_unlock(p->owner);
01359 break;
01360 }
01361 } else
01362 break;
01363 }
01364 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01365 if (data) {
01366 switch (p->sig) {
01367 #ifdef HAVE_PRI
01368 case SIG_BRI:
01369 case SIG_BRI_PTMP:
01370 case SIG_PRI:
01371 ast_mutex_lock(&pri->lock);
01372 break;
01373 #endif
01374 #ifdef HAVE_SS7
01375 case SIG_SS7:
01376 ast_mutex_lock(&ss7->lock);
01377 break;
01378 #endif
01379 default:
01380 break;
01381 }
01382 }
01383
01384 #endif
01385 }
01386
01387 static int restore_gains(struct dahdi_pvt *p);
01388
01389 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01390 {
01391 int tchan;
01392 int tinthreeway;
01393 struct ast_channel *towner;
01394
01395 ast_debug(1, "Swapping %d and %d\n", a, b);
01396
01397 tchan = p->subs[a].chan;
01398 towner = p->subs[a].owner;
01399 tinthreeway = p->subs[a].inthreeway;
01400
01401 p->subs[a].chan = p->subs[b].chan;
01402 p->subs[a].owner = p->subs[b].owner;
01403 p->subs[a].inthreeway = p->subs[b].inthreeway;
01404
01405 p->subs[b].chan = tchan;
01406 p->subs[b].owner = towner;
01407 p->subs[b].inthreeway = tinthreeway;
01408
01409 if (p->subs[a].owner)
01410 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01411 if (p->subs[b].owner)
01412 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01413 wakeup_sub(p, a, NULL);
01414 wakeup_sub(p, b, NULL);
01415 }
01416
01417 static int dahdi_open(char *fn)
01418 {
01419 int fd;
01420 int isnum;
01421 int chan = 0;
01422 int bs;
01423 int x;
01424 isnum = 1;
01425 for (x = 0; x < strlen(fn); x++) {
01426 if (!isdigit(fn[x])) {
01427 isnum = 0;
01428 break;
01429 }
01430 }
01431 if (isnum) {
01432 chan = atoi(fn);
01433 if (chan < 1) {
01434 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01435 return -1;
01436 }
01437 fn = "/dev/dahdi/channel";
01438 }
01439 fd = open(fn, O_RDWR | O_NONBLOCK);
01440 if (fd < 0) {
01441 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01442 return -1;
01443 }
01444 if (chan) {
01445 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01446 x = errno;
01447 close(fd);
01448 errno = x;
01449 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01450 return -1;
01451 }
01452 }
01453 bs = READ_SIZE;
01454 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01455 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
01456 x = errno;
01457 close(fd);
01458 errno = x;
01459 return -1;
01460 }
01461 return fd;
01462 }
01463
01464 static void dahdi_close(int fd)
01465 {
01466 if (fd > 0)
01467 close(fd);
01468 }
01469
01470 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01471 {
01472 dahdi_close(chan_pvt->subs[sub_num].dfd);
01473 chan_pvt->subs[sub_num].dfd = -1;
01474 }
01475
01476 #ifdef HAVE_PRI
01477 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01478 {
01479 dahdi_close(pri->fds[fd_num]);
01480 pri->fds[fd_num] = -1;
01481 }
01482 #endif
01483
01484 #ifdef HAVE_SS7
01485 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01486 {
01487 dahdi_close(ss7->fds[fd_num]);
01488 ss7->fds[fd_num] = -1;
01489 }
01490 #endif
01491
01492 static int dahdi_setlinear(int dfd, int linear)
01493 {
01494 int res;
01495 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01496 if (res)
01497 return res;
01498 return 0;
01499 }
01500
01501
01502 static int alloc_sub(struct dahdi_pvt *p, int x)
01503 {
01504 struct dahdi_bufferinfo bi;
01505 int res;
01506 if (p->subs[x].dfd >= 0) {
01507 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01508 return -1;
01509 }
01510
01511 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01512 if (p->subs[x].dfd <= -1) {
01513 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01514 return -1;
01515 }
01516
01517 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01518 if (!res) {
01519 bi.txbufpolicy = p->buf_policy;
01520 bi.rxbufpolicy = p->buf_policy;
01521 bi.numbufs = p->buf_no;
01522 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01523 if (res < 0) {
01524 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01525 }
01526 } else
01527 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01528
01529 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01530 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01531 dahdi_close_sub(p, x);
01532 p->subs[x].dfd = -1;
01533 return -1;
01534 }
01535 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01536 return 0;
01537 }
01538
01539 static int unalloc_sub(struct dahdi_pvt *p, int x)
01540 {
01541 if (!x) {
01542 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01543 return -1;
01544 }
01545 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01546 dahdi_close_sub(p, x);
01547 p->subs[x].linear = 0;
01548 p->subs[x].chan = 0;
01549 p->subs[x].owner = NULL;
01550 p->subs[x].inthreeway = 0;
01551 p->polarity = POLARITY_IDLE;
01552 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01553 return 0;
01554 }
01555
01556 static int digit_to_dtmfindex(char digit)
01557 {
01558 if (isdigit(digit))
01559 return DAHDI_TONE_DTMF_BASE + (digit - '0');
01560 else if (digit >= 'A' && digit <= 'D')
01561 return DAHDI_TONE_DTMF_A + (digit - 'A');
01562 else if (digit >= 'a' && digit <= 'd')
01563 return DAHDI_TONE_DTMF_A + (digit - 'a');
01564 else if (digit == '*')
01565 return DAHDI_TONE_DTMF_s;
01566 else if (digit == '#')
01567 return DAHDI_TONE_DTMF_p;
01568 else
01569 return -1;
01570 }
01571
01572 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01573 {
01574 struct dahdi_pvt *pvt;
01575 int index;
01576 int dtmf = -1;
01577
01578 pvt = chan->tech_pvt;
01579
01580 ast_mutex_lock(&pvt->lock);
01581
01582 index = dahdi_get_index(chan, pvt, 0);
01583
01584 if ((index != SUB_REAL) || !pvt->owner)
01585 goto out;
01586
01587 #ifdef HAVE_PRI
01588 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01589 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01590 if (pvt->setup_ack) {
01591 if (!pri_grab(pvt, pvt->pri)) {
01592 pri_information(pvt->pri->pri, pvt->call, digit);
01593 pri_rel(pvt->pri);
01594 } else
01595 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01596 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01597 int res;
01598 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01599 res = strlen(pvt->dialdest);
01600 pvt->dialdest[res++] = digit;
01601 pvt->dialdest[res] = '\0';
01602 }
01603 goto out;
01604 }
01605 #endif
01606 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01607 goto out;
01608
01609 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01610 int res;
01611 struct dahdi_dialoperation zo = {
01612 .op = DAHDI_DIAL_OP_APPEND,
01613 };
01614
01615 zo.dialstr[0] = 'T';
01616 zo.dialstr[1] = digit;
01617 zo.dialstr[2] = '\0';
01618 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01619 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01620 else
01621 pvt->dialing = 1;
01622 } else {
01623 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01624 pvt->dialing = 1;
01625 pvt->begindigit = digit;
01626 }
01627
01628 out:
01629 ast_mutex_unlock(&pvt->lock);
01630
01631 return 0;
01632 }
01633
01634 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01635 {
01636 struct dahdi_pvt *pvt;
01637 int res = 0;
01638 int index;
01639 int x;
01640
01641 pvt = chan->tech_pvt;
01642
01643 ast_mutex_lock(&pvt->lock);
01644
01645 index = dahdi_get_index(chan, pvt, 0);
01646
01647 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01648 goto out;
01649
01650 #ifdef HAVE_PRI
01651
01652 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01653 && !pvt->begindigit)
01654 goto out;
01655 #endif
01656
01657 if (pvt->begindigit) {
01658 x = -1;
01659 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01660 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01661 pvt->dialing = 0;
01662 pvt->begindigit = 0;
01663 }
01664
01665 out:
01666 ast_mutex_unlock(&pvt->lock);
01667
01668 return res;
01669 }
01670
01671 static char *events[] = {
01672 "No event",
01673 "On hook",
01674 "Ring/Answered",
01675 "Wink/Flash",
01676 "Alarm",
01677 "No more alarm",
01678 "HDLC Abort",
01679 "HDLC Overrun",
01680 "HDLC Bad FCS",
01681 "Dial Complete",
01682 "Ringer On",
01683 "Ringer Off",
01684 "Hook Transition Complete",
01685 "Bits Changed",
01686 "Pulse Start",
01687 "Timer Expired",
01688 "Timer Ping",
01689 "Polarity Reversal",
01690 "Ring Begin",
01691 };
01692
01693 static struct {
01694 int alarm;
01695 char *name;
01696 } alarms[] = {
01697 { DAHDI_ALARM_RED, "Red Alarm" },
01698 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01699 { DAHDI_ALARM_BLUE, "Blue Alarm" },
01700 { DAHDI_ALARM_RECOVER, "Recovering" },
01701 { DAHDI_ALARM_LOOPBACK, "Loopback" },
01702 { DAHDI_ALARM_NOTOPEN, "Not Open" },
01703 { DAHDI_ALARM_NONE, "None" },
01704 };
01705
01706 static char *alarm2str(int alarm)
01707 {
01708 int x;
01709 for (x = 0; x < ARRAY_LEN(alarms); x++) {
01710 if (alarms[x].alarm & alarm)
01711 return alarms[x].name;
01712 }
01713 return alarm ? "Unknown Alarm" : "No Alarm";
01714 }
01715
01716 static char *event2str(int event)
01717 {
01718 static char buf[256];
01719 if ((event < (ARRAY_LEN(events))) && (event > -1))
01720 return events[event];
01721 sprintf(buf, "Event %d", event);
01722 return buf;
01723 }
01724
01725 #ifdef HAVE_PRI
01726 static char *dialplan2str(int dialplan)
01727 {
01728 if (dialplan == -1 || dialplan == -2) {
01729 return("Dynamically set dialplan in ISDN");
01730 }
01731 return (pri_plan2str(dialplan));
01732 }
01733 #endif
01734
01735 static char *dahdi_sig2str(int sig)
01736 {
01737 static char buf[256];
01738 switch (sig) {
01739 case SIG_EM:
01740 return "E & M Immediate";
01741 case SIG_EMWINK:
01742 return "E & M Wink";
01743 case SIG_EM_E1:
01744 return "E & M E1";
01745 case SIG_FEATD:
01746 return "Feature Group D (DTMF)";
01747 case SIG_FEATDMF:
01748 return "Feature Group D (MF)";
01749 case SIG_FEATDMF_TA:
01750 return "Feature Groud D (MF) Tandem Access";
01751 case SIG_FEATB:
01752 return "Feature Group B (MF)";
01753 case SIG_E911:
01754 return "E911 (MF)";
01755 case SIG_FGC_CAMA:
01756 return "FGC/CAMA (Dialpulse)";
01757 case SIG_FGC_CAMAMF:
01758 return "FGC/CAMA (MF)";
01759 case SIG_FXSLS:
01760 return "FXS Loopstart";
01761 case SIG_FXSGS:
01762 return "FXS Groundstart";
01763 case SIG_FXSKS:
01764 return "FXS Kewlstart";
01765 case SIG_FXOLS:
01766 return "FXO Loopstart";
01767 case SIG_FXOGS:
01768 return "FXO Groundstart";
01769 case SIG_FXOKS:
01770 return "FXO Kewlstart";
01771 case SIG_PRI:
01772 return "ISDN PRI";
01773 case SIG_BRI:
01774 return "ISDN BRI Point to Point";
01775 case SIG_BRI_PTMP:
01776 return "ISDN BRI Point to MultiPoint";
01777 case SIG_SS7:
01778 return "SS7";
01779 case SIG_SF:
01780 return "SF (Tone) Immediate";
01781 case SIG_SFWINK:
01782 return "SF (Tone) Wink";
01783 case SIG_SF_FEATD:
01784 return "SF (Tone) with Feature Group D (DTMF)";
01785 case SIG_SF_FEATDMF:
01786 return "SF (Tone) with Feature Group D (MF)";
01787 case SIG_SF_FEATB:
01788 return "SF (Tone) with Feature Group B (MF)";
01789 case SIG_GR303FXOKS:
01790 return "GR-303 with FXOKS";
01791 case SIG_GR303FXSKS:
01792 return "GR-303 with FXSKS";
01793 case 0:
01794 return "Pseudo";
01795 default:
01796 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01797 return buf;
01798 }
01799 }
01800
01801 #define sig2str dahdi_sig2str
01802
01803 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01804 {
01805
01806
01807 struct dahdi_confinfo zi;
01808
01809 memset(&zi, 0, sizeof(zi));
01810 zi.chan = 0;
01811
01812 if (slavechannel > 0) {
01813
01814 zi.confmode = DAHDI_CONF_DIGITALMON;
01815 zi.confno = slavechannel;
01816 } else {
01817 if (!index) {
01818
01819 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01820 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01821 } else
01822 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01823 zi.confno = p->confno;
01824 }
01825 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01826 return 0;
01827 if (c->dfd < 0)
01828 return 0;
01829 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01830 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01831 return -1;
01832 }
01833 if (slavechannel < 1) {
01834 p->confno = zi.confno;
01835 }
01836 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01837 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01838 return 0;
01839 }
01840
01841 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01842 {
01843
01844 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01845 return 1;
01846
01847 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01848 return 1;
01849 return 0;
01850 }
01851
01852 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01853 {
01854 struct dahdi_confinfo zi;
01855 if (
01856 (c->dfd < 0) ||
01857
01858 !isourconf(p, c)
01859
01860 ) return 0;
01861 memset(&zi, 0, sizeof(zi));
01862 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01863 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01864 return -1;
01865 }
01866 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01867 memcpy(&c->curconf, &zi, sizeof(c->curconf));
01868 return 0;
01869 }
01870
01871 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01872 {
01873 int x;
01874 int useslavenative;
01875 struct dahdi_pvt *slave = NULL;
01876
01877 useslavenative = 1;
01878
01879 for (x = 0; x < 3; x++) {
01880
01881
01882 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01883 useslavenative = 0;
01884 }
01885
01886
01887 if (useslavenative) {
01888 for (x = 0; x < MAX_SLAVES; x++) {
01889 if (p->slaves[x]) {
01890 if (slave) {
01891
01892
01893 slave = NULL;
01894 useslavenative = 0;
01895 break;
01896 } else {
01897
01898 slave = p->slaves[x];
01899 }
01900 }
01901 }
01902 }
01903
01904 if (!slave)
01905 useslavenative = 0;
01906 else if (slave->law != p->law) {
01907 useslavenative = 0;
01908 slave = NULL;
01909 }
01910 if (out)
01911 *out = slave;
01912 return useslavenative;
01913 }
01914
01915 static int reset_conf(struct dahdi_pvt *p)
01916 {
01917 p->confno = -1;
01918 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01919 if (p->subs[SUB_REAL].dfd > -1) {
01920 struct dahdi_confinfo zi;
01921
01922 memset(&zi, 0, sizeof(zi));
01923 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01924 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01925 }
01926 return 0;
01927 }
01928
01929 static int update_conf(struct dahdi_pvt *p)
01930 {
01931 int needconf = 0;
01932 int x;
01933 int useslavenative;
01934 struct dahdi_pvt *slave = NULL;
01935
01936 useslavenative = isslavenative(p, &slave);
01937
01938 for (x = 0; x < 3; x++) {
01939
01940 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01941 conf_add(p, &p->subs[x], x, 0);
01942 needconf++;
01943 } else {
01944 conf_del(p, &p->subs[x], x);
01945 }
01946 }
01947
01948
01949 for (x = 0; x < MAX_SLAVES; x++) {
01950 if (p->slaves[x]) {
01951 if (useslavenative)
01952 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01953 else {
01954 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01955 needconf++;
01956 }
01957 }
01958 }
01959
01960 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01961 if (useslavenative)
01962 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01963 else {
01964 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01965 needconf++;
01966 }
01967 }
01968
01969 if (p->master) {
01970 if (isslavenative(p->master, NULL)) {
01971 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01972 } else {
01973 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01974 }
01975 }
01976 if (!needconf) {
01977
01978
01979 p->confno = -1;
01980 }
01981 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01982 return 0;
01983 }
01984
01985 static void dahdi_enable_ec(struct dahdi_pvt *p)
01986 {
01987 int x;
01988 int res;
01989 if (!p)
01990 return;
01991 if (p->echocanon) {
01992 ast_debug(1, "Echo cancellation already on\n");
01993 return;
01994 }
01995 if (p->digital) {
01996 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
01997 return;
01998 }
01999 if (p->echocancel.head.tap_length) {
02000 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02001 x = 1;
02002 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02003 if (res)
02004 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02005 }
02006 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02007 if (res) {
02008 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02009 } else {
02010 p->echocanon = 1;
02011 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02012 }
02013 } else
02014 ast_debug(1, "No echo cancellation requested\n");
02015 }
02016
02017 static void dahdi_train_ec(struct dahdi_pvt *p)
02018 {
02019 int x;
02020 int res;
02021
02022 if (p && p->echocanon && p->echotraining) {
02023 x = p->echotraining;
02024 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02025 if (res)
02026 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02027 else
02028 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02029 } else {
02030 ast_debug(1, "No echo training requested\n");
02031 }
02032 }
02033
02034 static void dahdi_disable_ec(struct dahdi_pvt *p)
02035 {
02036 int res;
02037
02038 if (p->echocanon) {
02039 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02040
02041 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02042
02043 if (res)
02044 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02045 else
02046 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02047 }
02048
02049 p->echocanon = 0;
02050 }
02051
02052 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02053 {
02054 int j;
02055 int k;
02056 float linear_gain = pow(10.0, gain / 20.0);
02057
02058 switch (law) {
02059 case DAHDI_LAW_ALAW:
02060 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02061 if (gain) {
02062 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02063 if (k > 32767) k = 32767;
02064 if (k < -32767) k = -32767;
02065 g->txgain[j] = AST_LIN2A(k);
02066 } else {
02067 g->txgain[j] = j;
02068 }
02069 }
02070 break;
02071 case DAHDI_LAW_MULAW:
02072 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02073 if (gain) {
02074 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02075 if (k > 32767) k = 32767;
02076 if (k < -32767) k = -32767;
02077 g->txgain[j] = AST_LIN2MU(k);
02078 } else {
02079 g->txgain[j] = j;
02080 }
02081 }
02082 break;
02083 }
02084 }
02085
02086 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02087 {
02088 int j;
02089 int k;
02090 float linear_gain = pow(10.0, gain / 20.0);
02091
02092 switch (law) {
02093 case DAHDI_LAW_ALAW:
02094 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02095 if (gain) {
02096 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02097 if (k > 32767) k = 32767;
02098 if (k < -32767) k = -32767;
02099 g->rxgain[j] = AST_LIN2A(k);
02100 } else {
02101 g->rxgain[j] = j;
02102 }
02103 }
02104 break;
02105 case DAHDI_LAW_MULAW:
02106 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02107 if (gain) {
02108 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02109 if (k > 32767) k = 32767;
02110 if (k < -32767) k = -32767;
02111 g->rxgain[j] = AST_LIN2MU(k);
02112 } else {
02113 g->rxgain[j] = j;
02114 }
02115 }
02116 break;
02117 }
02118 }
02119
02120 static int set_actual_txgain(int fd, int chan, float gain, int law)
02121 {
02122 struct dahdi_gains g;
02123 int res;
02124
02125 memset(&g, 0, sizeof(g));
02126 g.chan = chan;
02127 res = ioctl(fd, DAHDI_GETGAINS, &g);
02128 if (res) {
02129 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02130 return res;
02131 }
02132
02133 fill_txgain(&g, gain, law);
02134
02135 return ioctl(fd, DAHDI_SETGAINS, &g);
02136 }
02137
02138 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02139 {
02140 struct dahdi_gains g;
02141 int res;
02142
02143 memset(&g, 0, sizeof(g));
02144 g.chan = chan;
02145 res = ioctl(fd, DAHDI_GETGAINS, &g);
02146 if (res) {
02147 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02148 return res;
02149 }
02150
02151 fill_rxgain(&g, gain, law);
02152
02153 return ioctl(fd, DAHDI_SETGAINS, &g);
02154 }
02155
02156 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02157 {
02158 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02159 }
02160
02161 static int bump_gains(struct dahdi_pvt *p)
02162 {
02163 int res;
02164
02165
02166 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02167 if (res) {
02168 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02169 return -1;
02170 }
02171
02172 return 0;
02173 }
02174
02175 static int restore_gains(struct dahdi_pvt *p)
02176 {
02177 int res;
02178
02179 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02180 if (res) {
02181 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02182 return -1;
02183 }
02184
02185 return 0;
02186 }
02187
02188 static inline int dahdi_set_hook(int fd, int hs)
02189 {
02190 int x, res;
02191
02192 x = hs;
02193 res = ioctl(fd, DAHDI_HOOK, &x);
02194
02195 if (res < 0) {
02196 if (errno == EINPROGRESS)
02197 return 0;
02198 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02199
02200 }
02201
02202 return res;
02203 }
02204
02205 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02206 {
02207 int x, y, res;
02208 x = muted;
02209 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02210 y = 1;
02211 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02212 if (res)
02213 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02214 }
02215 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02216 if (res < 0)
02217 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02218 return res;
02219 }
02220
02221 static int save_conference(struct dahdi_pvt *p)
02222 {
02223 struct dahdi_confinfo c;
02224 int res;
02225 if (p->saveconf.confmode) {
02226 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02227 return -1;
02228 }
02229 p->saveconf.chan = 0;
02230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02231 if (res) {
02232 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02233 p->saveconf.confmode = 0;
02234 return -1;
02235 }
02236 memset(&c, 0, sizeof(c));
02237 c.confmode = DAHDI_CONF_NORMAL;
02238 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02239 if (res) {
02240 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02241 return -1;
02242 }
02243 ast_debug(1, "Disabled conferencing\n");
02244 return 0;
02245 }
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265 static void notify_message(char *mailbox_full, int thereornot)
02266 {
02267 char s[sizeof(mwimonitornotify) + 80];
02268 struct ast_event *event;
02269 char *mailbox, *context;
02270
02271
02272 context = mailbox = ast_strdupa(mailbox_full);
02273 strsep(&context, "@");
02274 if (ast_strlen_zero(context))
02275 context = "default";
02276
02277 if (!(event = ast_event_new(AST_EVENT_MWI,
02278 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02279 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02280 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02281 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02282 AST_EVENT_IE_END))) {
02283 return;
02284 }
02285
02286 ast_event_queue_and_cache(event,
02287 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
02288 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
02289 AST_EVENT_IE_END);
02290
02291 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02292 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02293 ast_safe_system(s);
02294 }
02295 }
02296
02297 static int restore_conference(struct dahdi_pvt *p)
02298 {
02299 int res;
02300 if (p->saveconf.confmode) {
02301 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02302 p->saveconf.confmode = 0;
02303 if (res) {
02304 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02305 return -1;
02306 }
02307 }
02308 ast_debug(1, "Restored conferencing\n");
02309 return 0;
02310 }
02311
02312 static int send_callerid(struct dahdi_pvt *p);
02313
02314 static int send_cwcidspill(struct dahdi_pvt *p)
02315 {
02316 p->callwaitcas = 0;
02317 p->cidcwexpire = 0;
02318 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02319 return -1;
02320 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02321
02322 p->cidlen += READ_SIZE * 4;
02323 p->cidpos = 0;
02324 send_callerid(p);
02325 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02326 return 0;
02327 }
02328
02329 static int has_voicemail(struct dahdi_pvt *p)
02330 {
02331 int new_msgs;
02332 struct ast_event *event;
02333 char *mailbox, *context;
02334
02335 mailbox = context = ast_strdupa(p->mailbox);
02336 strsep(&context, "@");
02337 if (ast_strlen_zero(context))
02338 context = "default";
02339
02340 event = ast_event_get_cached(AST_EVENT_MWI,
02341 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02342 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02343 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
02344 AST_EVENT_IE_END);
02345
02346 if (event) {
02347 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02348 ast_event_destroy(event);
02349 } else
02350 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02351
02352 return new_msgs;
02353 }
02354
02355 static int send_callerid(struct dahdi_pvt *p)
02356 {
02357
02358 int res;
02359
02360 if (p->subs[SUB_REAL].linear) {
02361 p->subs[SUB_REAL].linear = 0;
02362 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02363 }
02364 while (p->cidpos < p->cidlen) {
02365 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02366 if (res < 0) {
02367 if (errno == EAGAIN)
02368 return 0;
02369 else {
02370 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02371 return -1;
02372 }
02373 }
02374 if (!res)
02375 return 0;
02376 p->cidpos += res;
02377 }
02378 ast_free(p->cidspill);
02379 p->cidspill = NULL;
02380 if (p->callwaitcas) {
02381
02382 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02383 } else
02384 restore_conference(p);
02385 return 0;
02386 }
02387
02388 static int dahdi_callwait(struct ast_channel *ast)
02389 {
02390 struct dahdi_pvt *p = ast->tech_pvt;
02391 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02392 if (p->cidspill) {
02393 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02394 ast_free(p->cidspill);
02395 }
02396 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02397 return -1;
02398 save_conference(p);
02399
02400 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02401 if (!p->callwaitrings && p->callwaitingcallerid) {
02402 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02403 p->callwaitcas = 1;
02404 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02405 } else {
02406 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02407 p->callwaitcas = 0;
02408 p->cidlen = 2400 + READ_SIZE * 4;
02409 }
02410 p->cidpos = 0;
02411 send_callerid(p);
02412
02413 return 0;
02414 }
02415
02416 #ifdef HAVE_SS7
02417 static unsigned char cid_pres2ss7pres(int cid_pres)
02418 {
02419 return (cid_pres >> 5) & 0x03;
02420 }
02421
02422 static unsigned char cid_pres2ss7screen(int cid_pres)
02423 {
02424 return cid_pres & 0x03;
02425 }
02426 #endif
02427
02428 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02429 {
02430 struct dahdi_pvt *p = ast->tech_pvt;
02431 int x, res, index,mysig;
02432 char *c, *n, *l;
02433 #ifdef HAVE_PRI
02434 char *s = NULL;
02435 #endif
02436 char dest[256];
02437 ast_mutex_lock(&p->lock);
02438 ast_copy_string(dest, rdest, sizeof(dest));
02439 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02440 if ((ast->_state == AST_STATE_BUSY)) {
02441 p->subs[SUB_REAL].needbusy = 1;
02442 ast_mutex_unlock(&p->lock);
02443 return 0;
02444 }
02445 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02446 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02447 ast_mutex_unlock(&p->lock);
02448 return -1;
02449 }
02450 p->dialednone = 0;
02451 if ((p->radio || (p->oprmode < 0)))
02452 {
02453
02454 ast_setstate(ast, AST_STATE_UP);
02455 ast_mutex_unlock(&p->lock);
02456 return 0;
02457 }
02458 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02459 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02460 if (res)
02461 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02462 p->outgoing = 1;
02463
02464 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02465
02466 mysig = p->sig;
02467 if (p->outsigmod > -1)
02468 mysig = p->outsigmod;
02469
02470 switch (mysig) {
02471 case SIG_FXOLS:
02472 case SIG_FXOGS:
02473 case SIG_FXOKS:
02474 if (p->owner == ast) {
02475
02476
02477
02478 p->dialing = 1;
02479 if (p->use_callerid) {
02480
02481 if (p->cidspill) {
02482 ast_log(LOG_WARNING, "cidspill already exists??\n");
02483 ast_free(p->cidspill);
02484 }
02485 p->callwaitcas = 0;
02486 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02487 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02488 p->cidpos = 0;
02489 send_callerid(p);
02490 }
02491 }
02492
02493 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02494 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02495 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02496 p->cidrings = cidrings[p->distinctivering - 1];
02497 } else {
02498 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02499 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02500 p->cidrings = p->sendcalleridafter;
02501 }
02502
02503
02504 c = strchr(dest, '/');
02505 if (c)
02506 c++;
02507 if (c && (strlen(c) < p->stripmsd)) {
02508 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02509 c = NULL;
02510 }
02511 if (c) {
02512 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02513 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02514 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02515 } else {
02516 p->dop.dialstr[0] = '\0';
02517 }
02518 x = DAHDI_RING;
02519 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02520 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02521 ast_mutex_unlock(&p->lock);
02522 return -1;
02523 }
02524 p->dialing = 1;
02525 } else {
02526
02527 p->callwaitrings = 0;
02528 if (ast->cid.cid_num)
02529 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02530 else
02531 p->callwait_num[0] = '\0';
02532 if (ast->cid.cid_name)
02533 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02534 else
02535 p->callwait_name[0] = '\0';
02536
02537 if (dahdi_callwait(ast)) {
02538 ast_mutex_unlock(&p->lock);
02539 return -1;
02540 }
02541
02542 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02543 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02544
02545 }
02546 n = ast->cid.cid_name;
02547 l = ast->cid.cid_num;
02548 if (l)
02549 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02550 else
02551 p->lastcid_num[0] = '\0';
02552 if (n)
02553 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02554 else
02555 p->lastcid_name[0] = '\0';
02556 ast_setstate(ast, AST_STATE_RINGING);
02557 index = dahdi_get_index(ast, p, 0);
02558 if (index > -1) {
02559 p->subs[index].needringing = 1;
02560 }
02561 break;
02562 case SIG_FXSLS:
02563 case SIG_FXSGS:
02564 case SIG_FXSKS:
02565 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02566 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02567 p->polaritydelaytv = ast_tvnow();
02568 }
02569
02570 case SIG_EMWINK:
02571 case SIG_EM:
02572 case SIG_EM_E1:
02573 case SIG_FEATD:
02574 case SIG_FEATDMF:
02575 case SIG_E911:
02576 case SIG_FGC_CAMA:
02577 case SIG_FGC_CAMAMF:
02578 case SIG_FEATB:
02579 case SIG_SFWINK:
02580 case SIG_SF:
02581 case SIG_SF_FEATD:
02582 case SIG_SF_FEATDMF:
02583 case SIG_FEATDMF_TA:
02584 case SIG_SF_FEATB:
02585 c = strchr(dest, '/');
02586 if (c)
02587 c++;
02588 else
02589 c = "";
02590 if (strlen(c) < p->stripmsd) {
02591 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02592 ast_mutex_unlock(&p->lock);
02593 return -1;
02594 }
02595 #ifdef HAVE_PRI
02596
02597 if (!p->pri) {
02598 #endif
02599 x = DAHDI_START;
02600 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02601 if (res < 0) {
02602 if (errno != EINPROGRESS) {
02603 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02604 ast_mutex_unlock(&p->lock);
02605 return -1;
02606 }
02607 }
02608 #ifdef HAVE_PRI
02609 }
02610 #endif
02611 ast_debug(1, "Dialing '%s'\n", c);
02612 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02613
02614 c += p->stripmsd;
02615
02616 switch (mysig) {
02617 case SIG_FEATD:
02618 l = ast->cid.cid_num;
02619 if (l)
02620 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02621 else
02622 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02623 break;
02624 case SIG_FEATDMF:
02625 l = ast->cid.cid_num;
02626 if (l)
02627 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02628 else
02629 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02630 break;
02631 case SIG_FEATDMF_TA:
02632 {
02633 const char *cic, *ozz;
02634
02635
02636 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02637 if (!ozz)
02638 ozz = defaultozz;
02639 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02640 if (!cic)
02641 cic = defaultcic;
02642 if (!ozz || !cic) {
02643 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02644 ast_mutex_unlock(&p->lock);
02645 return -1;
02646 }
02647 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02648 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02649 p->whichwink = 0;
02650 }
02651 break;
02652 case SIG_E911:
02653 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02654 break;
02655 case SIG_FGC_CAMA:
02656 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02657 break;
02658 case SIG_FGC_CAMAMF:
02659 case SIG_FEATB:
02660 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02661 break;
02662 default:
02663 if (p->pulse)
02664 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02665 else
02666 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02667 break;
02668 }
02669
02670 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02671 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02672 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02673 p->echorest[sizeof(p->echorest) - 1] = '\0';
02674 p->echobreak = 1;
02675 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02676 } else
02677 p->echobreak = 0;
02678 if (!res) {
02679 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02680 int saveerr = errno;
02681
02682 x = DAHDI_ONHOOK;
02683 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02684 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02685 ast_mutex_unlock(&p->lock);
02686 return -1;
02687 }
02688 } else
02689 ast_debug(1, "Deferring dialing...\n");
02690
02691 p->dialing = 1;
02692 if (ast_strlen_zero(c))
02693 p->dialednone = 1;
02694 ast_setstate(ast, AST_STATE_DIALING);
02695 break;
02696 case 0:
02697
02698 ast_setstate(ast, AST_STATE_UP);
02699 break;
02700 case SIG_PRI:
02701 case SIG_BRI:
02702 case SIG_BRI_PTMP:
02703 case SIG_SS7:
02704
02705 p->dialdest[0] = '\0';
02706 p->dialing = 1;
02707 break;
02708 default:
02709 ast_debug(1, "not yet implemented\n");
02710 ast_mutex_unlock(&p->lock);
02711 return -1;
02712 }
02713 #ifdef HAVE_SS7
02714 if (p->ss7) {
02715 char ss7_called_nai;
02716 int called_nai_strip;
02717 char ss7_calling_nai;
02718 int calling_nai_strip;
02719 const char *charge_str = NULL;
02720 const char *gen_address = NULL;
02721 const char *gen_digits = NULL;
02722 const char *gen_dig_type = NULL;
02723 const char *gen_dig_scheme = NULL;
02724 const char *gen_name = NULL;
02725 const char *jip_digits = NULL;
02726 const char *lspi_ident = NULL;
02727 const char *rlt_flag = NULL;
02728 const char *call_ref_id = NULL;
02729 const char *call_ref_pc = NULL;
02730 const char *send_far = NULL;
02731
02732 c = strchr(dest, '/');
02733 if (c) {
02734 c++;
02735 } else {
02736 c = "";
02737 }
02738 if (strlen(c) < p->stripmsd) {
02739 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02740 ast_mutex_unlock(&p->lock);
02741 return -1;
02742 }
02743
02744 if (!p->hidecallerid) {
02745 l = ast->cid.cid_num;
02746 } else {
02747 l = NULL;
02748 }
02749
02750 if (ss7_grab(p, p->ss7)) {
02751 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02752 ast_mutex_unlock(&p->lock);
02753 return -1;
02754 }
02755 p->digital = IS_DIGITAL(ast->transfercapability);
02756 p->ss7call = isup_new_call(p->ss7->ss7);
02757
02758 if (!p->ss7call) {
02759 ss7_rel(p->ss7);
02760 ast_mutex_unlock(&p->lock);
02761 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02762 return -1;
02763 }
02764
02765 called_nai_strip = 0;
02766 ss7_called_nai = p->ss7->called_nai;
02767 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
02768 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02769 called_nai_strip = strlen(p->ss7->internationalprefix);
02770 ss7_called_nai = SS7_NAI_INTERNATIONAL;
02771 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02772 called_nai_strip = strlen(p->ss7->nationalprefix);
02773 ss7_called_nai = SS7_NAI_NATIONAL;
02774 } else {
02775 ss7_called_nai = SS7_NAI_SUBSCRIBER;
02776 }
02777 }
02778 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02779
02780 calling_nai_strip = 0;
02781 ss7_calling_nai = p->ss7->calling_nai;
02782 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
02783 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02784 calling_nai_strip = strlen(p->ss7->internationalprefix);
02785 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02786 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02787 calling_nai_strip = strlen(p->ss7->nationalprefix);
02788 ss7_calling_nai = SS7_NAI_NATIONAL;
02789 } else {
02790 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02791 }
02792 }
02793 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02794 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02795 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02796
02797 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02798 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02799
02800 ast_channel_lock(ast);
02801
02802 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02803 if (charge_str)
02804 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02805
02806 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02807 if (gen_address)
02808 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type);
02809
02810 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02811 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02812 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02813 if (gen_digits)
02814 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
02815
02816 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02817 if (gen_name)
02818 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02819
02820 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02821 if (jip_digits)
02822 isup_set_jip_digits(p->ss7call, jip_digits);
02823
02824 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02825 if (lspi_ident)
02826 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
02827
02828 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02829 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02830 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
02831 }
02832
02833 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02834 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02835 if (call_ref_id && call_ref_pc) {
02836 isup_set_callref(p->ss7call, atoi(call_ref_id),
02837 call_ref_pc ? atoi(call_ref_pc) : 0);
02838 }
02839
02840 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02841 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02842 (isup_far(p->ss7->ss7, p->ss7call));
02843
02844 ast_channel_unlock(ast);
02845
02846 isup_iam(p->ss7->ss7, p->ss7call);
02847 ast_setstate(ast, AST_STATE_DIALING);
02848 ss7_rel(p->ss7);
02849 }
02850 #endif
02851 #ifdef HAVE_PRI
02852 if (p->pri) {
02853 struct pri_sr *sr;
02854 #ifdef SUPPORT_USERUSER
02855 const char *useruser;
02856 #endif
02857 int pridialplan;
02858 int dp_strip;
02859 int prilocaldialplan;
02860 int ldp_strip;
02861 int exclusive;
02862 const char *rr_str;
02863 int redirect_reason;
02864
02865 c = strchr(dest, '/');
02866 if (c) {
02867 c++;
02868 } else {
02869 c = "";
02870 }
02871
02872 l = NULL;
02873 n = NULL;
02874 if (!p->hidecallerid) {
02875 l = ast->cid.cid_num;
02876 if (!p->hidecalleridname) {
02877 n = ast->cid.cid_name;
02878 }
02879 }
02880
02881 if (strlen(c) < p->stripmsd) {
02882 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02883 ast_mutex_unlock(&p->lock);
02884 return -1;
02885 }
02886 if (mysig != SIG_FXSKS) {
02887 p->dop.op = DAHDI_DIAL_OP_REPLACE;
02888 s = strchr(c + p->stripmsd, 'w');
02889 if (s) {
02890 if (strlen(s) > 1)
02891 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02892 else
02893 p->dop.dialstr[0] = '\0';
02894 *s = '\0';
02895 } else {
02896 p->dop.dialstr[0] = '\0';
02897 }
02898 }
02899 if (pri_grab(p, p->pri)) {
02900 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02901 ast_mutex_unlock(&p->lock);
02902 return -1;
02903 }
02904 if (!(p->call = pri_new_call(p->pri->pri))) {
02905 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02906 pri_rel(p->pri);
02907 ast_mutex_unlock(&p->lock);
02908 return -1;
02909 }
02910 if (!(sr = pri_sr_new())) {
02911 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02912 pri_rel(p->pri);
02913 ast_mutex_unlock(&p->lock);
02914 }
02915 if (p->bearer || (mysig == SIG_FXSKS)) {
02916 if (p->bearer) {
02917 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02918 p->bearer->call = p->call;
02919 } else
02920 ast_debug(1, "I'm being setup with no bearer right now...\n");
02921
02922 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02923 }
02924 p->digital = IS_DIGITAL(ast->transfercapability);
02925
02926
02927 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02928 exclusive = 1;
02929 } else {
02930 exclusive = 0;
02931 }
02932
02933 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02934 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
02935 (p->digital ? -1 :
02936 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02937 if (p->pri->facilityenable)
02938 pri_facility_enable(p->pri->pri);
02939
02940 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02941 dp_strip = 0;
02942 pridialplan = p->pri->dialplan - 1;
02943 if (pridialplan == -2 || pridialplan == -3) {
02944 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02945 if (pridialplan == -2) {
02946 dp_strip = strlen(p->pri->internationalprefix);
02947 }
02948 pridialplan = PRI_INTERNATIONAL_ISDN;
02949 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02950 if (pridialplan == -2) {
02951 dp_strip = strlen(p->pri->nationalprefix);
02952 }
02953 pridialplan = PRI_NATIONAL_ISDN;
02954 } else {
02955 pridialplan = PRI_LOCAL_ISDN;
02956 }
02957 }
02958 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02959 switch (c[p->stripmsd]) {
02960 case 'U':
02961 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02962 break;
02963 case 'I':
02964 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02965 break;
02966 case 'N':
02967 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02968 break;
02969 case 'L':
02970 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02971 break;
02972 case 'S':
02973 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02974 break;
02975 case 'V':
02976 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02977 break;
02978 case 'R':
02979 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
02980 break;
02981 case 'u':
02982 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
02983 break;
02984 case 'e':
02985 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
02986 break;
02987 case 'x':
02988 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
02989 break;
02990 case 'f':
02991 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
02992 break;
02993 case 'n':
02994 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
02995 break;
02996 case 'p':
02997 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
02998 break;
02999 case 'r':
03000 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03001 break;
03002 default:
03003 if (isalpha(c[p->stripmsd])) {
03004 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03005 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03006 }
03007 break;
03008 }
03009 c++;
03010 }
03011 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03012
03013 ldp_strip = 0;
03014 prilocaldialplan = p->pri->localdialplan - 1;
03015 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03016 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03017 if (prilocaldialplan == -2) {
03018 ldp_strip = strlen(p->pri->internationalprefix);
03019 }
03020 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03021 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03022 if (prilocaldialplan == -2) {
03023 ldp_strip = strlen(p->pri->nationalprefix);
03024 }
03025 prilocaldialplan = PRI_NATIONAL_ISDN;
03026 } else {
03027 prilocaldialplan = PRI_LOCAL_ISDN;
03028 }
03029 }
03030 if (l != NULL) {
03031 while (*l > '9' && *l != '*' && *l != '#') {
03032 switch (*l) {
03033 case 'U':
03034 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03035 break;
03036 case 'I':
03037 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03038 break;
03039 case 'N':
03040 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03041 break;
03042 case 'L':
03043 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03044 break;
03045 case 'S':
03046 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03047 break;
03048 case 'V':
03049 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03050 break;
03051 case 'R':
03052 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03053 break;
03054 case 'u':
03055 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03056 break;
03057 case 'e':
03058 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03059 break;
03060 case 'x':
03061 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03062 break;
03063 case 'f':
03064 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03065 break;
03066 case 'n':
03067 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03068 break;
03069 case 'p':
03070 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03071 break;
03072 case 'r':
03073 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03074 break;
03075 default:
03076 if (isalpha(*l)) {
03077 ast_log(LOG_WARNING,
03078 "Unrecognized prilocaldialplan %s modifier: %c\n",
03079 *l > 'Z' ? "NPI" : "TON", *l);
03080 }
03081 break;
03082 }
03083 l++;
03084 }
03085 }
03086 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03087 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03088 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03089 if (!strcasecmp(rr_str, "UNKNOWN"))
03090 redirect_reason = 0;
03091 else if (!strcasecmp(rr_str, "BUSY"))
03092 redirect_reason = 1;
03093 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03094
03095 redirect_reason = 2;
03096 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03097 redirect_reason = 15;
03098 else
03099 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03100 } else
03101 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03102 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03103
03104 #ifdef SUPPORT_USERUSER
03105
03106 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03107
03108 if (useruser)
03109 pri_sr_set_useruser(sr, useruser);
03110 #endif
03111
03112 if (pri_setup(p->pri->pri, p->call, sr)) {
03113 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03114 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03115 pri_rel(p->pri);
03116 ast_mutex_unlock(&p->lock);
03117 pri_sr_free(sr);
03118 return -1;
03119 }
03120 pri_sr_free(sr);
03121 ast_setstate(ast, AST_STATE_DIALING);
03122 pri_rel(p->pri);
03123 }
03124 #endif
03125 ast_mutex_unlock(&p->lock);
03126 return 0;
03127 }
03128
03129 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03130 {
03131 struct dahdi_pvt *p = *pvt;
03132
03133 if (p->prev)
03134 p->prev->next = p->next;
03135 if (p->next)
03136 p->next->prev = p->prev;
03137 if (p->use_smdi)
03138 ast_smdi_interface_unref(p->smdi_iface);
03139 if (p->mwi_event_sub)
03140 ast_event_unsubscribe(p->mwi_event_sub);
03141 if (p->vars) {
03142 ast_variables_destroy(p->vars);
03143 }
03144 ast_mutex_destroy(&p->lock);
03145 dahdi_close_sub(p, SUB_REAL);
03146 if (p->owner)
03147 p->owner->tech_pvt = NULL;
03148 free(p);
03149 *pvt = NULL;
03150 }
03151
03152 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03153 {
03154 int owned = 0;
03155 int i = 0;
03156
03157 if (!now) {
03158 if (cur->owner) {
03159 owned = 1;
03160 }
03161
03162 for (i = 0; i < 3; i++) {
03163 if (cur->subs[i].owner) {
03164 owned = 1;
03165 }
03166 }
03167 if (!owned) {
03168 if (prev) {
03169 prev->next = cur->next;
03170 if (prev->next)
03171 prev->next->prev = prev;
03172 else
03173 ifend = prev;
03174 } else {
03175 iflist = cur->next;
03176 if (iflist)
03177 iflist->prev = NULL;
03178 else
03179 ifend = NULL;
03180 }
03181 destroy_dahdi_pvt(&cur);
03182 }
03183 } else {
03184 if (prev) {
03185 prev->next = cur->next;
03186 if (prev->next)
03187 prev->next->prev = prev;
03188 else
03189 ifend = prev;
03190 } else {
03191 iflist = cur->next;
03192 if (iflist)
03193 iflist->prev = NULL;
03194 else
03195 ifend = NULL;
03196 }
03197 destroy_dahdi_pvt(&cur);
03198 }
03199 return 0;
03200 }
03201
03202 static void destroy_all_channels(void)
03203 {
03204 int x;
03205 struct dahdi_pvt *p, *pl;
03206
03207 while (num_restart_pending) {
03208 usleep(1);
03209 }
03210
03211 ast_mutex_lock(&iflock);
03212
03213 p = iflist;
03214 while (p) {
03215
03216 if (p->cidspill)
03217 ast_free(p->cidspill);
03218 pl = p;
03219 p = p->next;
03220 x = pl->channel;
03221
03222 if (pl)
03223 destroy_dahdi_pvt(&pl);
03224 if (option_verbose > 2)
03225 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03226 }
03227 iflist = NULL;
03228 ifcount = 0;
03229 ast_mutex_unlock(&iflock);
03230 }
03231
03232 #ifdef HAVE_PRI
03233 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03234
03235 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03236
03237 static char *dahdi_send_keypad_facility_descrip =
03238 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03239 " IE over the current channel.\n";
03240
03241 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03242 {
03243
03244 struct dahdi_pvt *p;
03245 char *digits = (char *) data;
03246
03247 if (ast_strlen_zero(digits)) {
03248 ast_debug(1, "No digit string sent to application!\n");
03249 return -1;
03250 }
03251
03252 p = (struct dahdi_pvt *)chan->tech_pvt;
03253
03254 if (!p) {
03255 ast_debug(1, "Unable to find technology private\n");
03256 return -1;
03257 }
03258
03259 ast_mutex_lock(&p->lock);
03260
03261 if (!p->pri || !p->call) {
03262 ast_debug(1, "Unable to find pri or call on channel!\n");
03263 ast_mutex_unlock(&p->lock);
03264 return -1;
03265 }
03266
03267 if (!pri_grab(p, p->pri)) {
03268 pri_keypad_facility(p->pri->pri, p->call, digits);
03269 pri_rel(p->pri);
03270 } else {
03271 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03272 ast_mutex_unlock(&p->lock);
03273 return -1;
03274 }
03275
03276 ast_mutex_unlock(&p->lock);
03277
03278 return 0;
03279 }
03280
03281 static int pri_is_up(struct dahdi_pri *pri)
03282 {
03283 int x;
03284 for (x = 0; x < NUM_DCHANS; x++) {
03285 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03286 return 1;
03287 }
03288 return 0;
03289 }
03290
03291 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03292 {
03293 bearer->owner = &inuse;
03294 bearer->realcall = crv;
03295 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03296 if (crv->subs[SUB_REAL].owner)
03297 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03298 crv->bearer = bearer;
03299 crv->call = bearer->call;
03300 crv->pri = pri;
03301 return 0;
03302 }
03303
03304 static char *pri_order(int level)
03305 {
03306 switch (level) {
03307 case 0:
03308 return "Primary";
03309 case 1:
03310 return "Secondary";
03311 case 2:
03312 return "Tertiary";
03313 case 3:
03314 return "Quaternary";
03315 default:
03316 return "<Unknown>";
03317 }
03318 }
03319
03320
03321 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03322 {
03323 int x = -1;
03324
03325 for (x = 0; x < NUM_DCHANS; x++) {
03326 if ((pri->dchans[x] == pri->pri))
03327 break;
03328 }
03329
03330 return pri->fds[x];
03331 }
03332
03333 static int pri_find_dchan(struct dahdi_pri *pri)
03334 {
03335 int oldslot = -1;
03336 struct pri *old;
03337 int newslot = -1;
03338 int x;
03339 old = pri->pri;
03340 for (x = 0; x < NUM_DCHANS; x++) {
03341 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03342 newslot = x;
03343 if (pri->dchans[x] == old) {
03344 oldslot = x;
03345 }
03346 }
03347 if (newslot < 0) {
03348 newslot = 0;
03349 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
03350 pri->dchannels[newslot]);
03351 }
03352 if (old && (oldslot != newslot))
03353 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03354 pri->dchannels[oldslot], pri->dchannels[newslot]);
03355 pri->pri = pri->dchans[newslot];
03356 return 0;
03357 }
03358 #endif
03359
03360 static int dahdi_hangup(struct ast_channel *ast)
03361 {
03362 int res;
03363 int index,x, law;
03364
03365 struct dahdi_pvt *p = ast->tech_pvt;
03366 struct dahdi_pvt *tmp = NULL;
03367 struct dahdi_pvt *prev = NULL;
03368 struct dahdi_params par;
03369
03370 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03371 if (!ast->tech_pvt) {
03372 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03373 return 0;
03374 }
03375
03376 ast_mutex_lock(&p->lock);
03377
03378 index = dahdi_get_index(ast, p, 1);
03379
03380 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03381 x = 1;
03382 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03383 p->cid_num[0] = '\0';
03384 p->cid_name[0] = '\0';
03385 }
03386
03387 x = 0;
03388 dahdi_confmute(p, 0);
03389 restore_gains(p);
03390 if (p->origcid_num) {
03391 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03392 ast_free(p->origcid_num);
03393 p->origcid_num = NULL;
03394 }
03395 if (p->origcid_name) {
03396 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03397 ast_free(p->origcid_name);
03398 p->origcid_name = NULL;
03399 }
03400 if (p->dsp)
03401 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03402 p->exten[0] = '\0';
03403
03404 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03405 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03406 p->ignoredtmf = 0;
03407
03408 if (index > -1) {
03409
03410 p->subs[index].owner = NULL;
03411 p->subs[index].needanswer = 0;
03412 p->subs[index].needflash = 0;
03413 p->subs[index].needringing = 0;
03414 p->subs[index].needbusy = 0;
03415 p->subs[index].needcongestion = 0;
03416 p->subs[index].linear = 0;
03417 p->subs[index].needcallerid = 0;
03418 p->polarity = POLARITY_IDLE;
03419 dahdi_setlinear(p->subs[index].dfd, 0);
03420 if (index == SUB_REAL) {
03421 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03422 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03423 if (p->subs[SUB_CALLWAIT].inthreeway) {
03424
03425 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03426
03427 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03428 unalloc_sub(p, SUB_CALLWAIT);
03429 p->owner = NULL;
03430 } else {
03431
03432 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
03433 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03434 unalloc_sub(p, SUB_THREEWAY);
03435 if (p->subs[SUB_REAL].inthreeway) {
03436
03437
03438 ast_debug(1, "Call was complete, setting owner to former third call\n");
03439 p->owner = p->subs[SUB_REAL].owner;
03440 } else {
03441
03442 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03443 p->owner = NULL;
03444 }
03445 p->subs[SUB_REAL].inthreeway = 0;
03446 }
03447 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03448
03449 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03450 unalloc_sub(p, SUB_CALLWAIT);
03451 p->owner = p->subs[SUB_REAL].owner;
03452 if (p->owner->_state != AST_STATE_UP)
03453 p->subs[SUB_REAL].needanswer = 1;
03454 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03455 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03456 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03457 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03458 unalloc_sub(p, SUB_THREEWAY);
03459 if (p->subs[SUB_REAL].inthreeway) {
03460
03461
03462 ast_debug(1, "Call was complete, setting owner to former third call\n");
03463 p->owner = p->subs[SUB_REAL].owner;
03464 } else {
03465
03466 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03467 p->owner = NULL;
03468 }
03469 p->subs[SUB_REAL].inthreeway = 0;
03470 }
03471 } else if (index == SUB_CALLWAIT) {
03472
03473 if (p->subs[SUB_CALLWAIT].inthreeway) {
03474
03475
03476 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03477 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
03478 S_OR(p->mohsuggest, NULL),
03479 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03480 }
03481 p->subs[SUB_THREEWAY].inthreeway = 0;
03482
03483 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03484 unalloc_sub(p, SUB_THREEWAY);
03485 } else
03486 unalloc_sub(p, SUB_CALLWAIT);
03487 } else if (index == SUB_THREEWAY) {
03488 if (p->subs[SUB_CALLWAIT].inthreeway) {
03489
03490
03491 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03492 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
03493 S_OR(p->mohsuggest, NULL),
03494 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03495 }
03496 p->subs[SUB_CALLWAIT].inthreeway = 0;
03497 }
03498 p->subs[SUB_REAL].inthreeway = 0;
03499
03500
03501 unalloc_sub(p, SUB_THREEWAY);
03502 } else {
03503
03504 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03505 }
03506 }
03507
03508 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03509 p->owner = NULL;
03510 p->ringt = 0;
03511 p->distinctivering = 0;
03512 p->confirmanswer = 0;
03513 p->cidrings = 1;
03514 p->outgoing = 0;
03515 p->digital = 0;
03516 p->faxhandled = 0;
03517 p->pulsedial = 0;
03518 p->onhooktime = time(NULL);
03519 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03520 p->proceeding = 0;
03521 p->dialing = 0;
03522 p->progress = 0;
03523 p->alerting = 0;
03524 p->setup_ack = 0;
03525 p->rlt = 0;
03526 #endif
03527 if (p->dsp) {
03528 ast_dsp_free(p->dsp);
03529 p->dsp = NULL;
03530 }
03531
03532 law = DAHDI_LAW_DEFAULT;
03533 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03534 if (res < 0)
03535 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03536
03537 #ifdef HAVE_SS7
03538 if (p->ss7) {
03539 if (p->ss7call) {
03540 if (!ss7_grab(p, p->ss7)) {
03541 if (!p->alreadyhungup) {
03542 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03543 int icause = ast->hangupcause ? ast->hangupcause : -1;
03544
03545 if (cause) {
03546 if (atoi(cause))
03547 icause = atoi(cause);
03548 }
03549 isup_rel(p->ss7->ss7, p->ss7call, icause);
03550 ss7_rel(p->ss7);
03551 p->alreadyhungup = 1;
03552 } else
03553 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03554 } else {
03555 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03556 res = -1;
03557 }
03558 }
03559 }
03560 #endif
03561 #ifdef HAVE_PRI
03562 if (p->pri) {
03563 #ifdef SUPPORT_USERUSER
03564 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03565 #endif
03566
03567
03568 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03569 if (!pri_grab(p, p->pri)) {
03570 if (p->alreadyhungup) {
03571 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
03572
03573 #ifdef SUPPORT_USERUSER
03574 pri_call_set_useruser(p->call, useruser);
03575 #endif
03576
03577 pri_hangup(p->pri->pri, p->call, -1);
03578 p->call = NULL;
03579 if (p->bearer)
03580 p->bearer->call = NULL;
03581 } else {
03582 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03583 int icause = ast->hangupcause ? ast->hangupcause : -1;
03584 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
03585
03586 #ifdef SUPPORT_USERUSER
03587 pri_call_set_useruser(p->call, useruser);
03588 #endif
03589
03590 p->alreadyhungup = 1;
03591 if (p->bearer)
03592 p->bearer->alreadyhungup = 1;
03593 if (cause) {
03594 if (atoi(cause))
03595 icause = atoi(cause);
03596 }
03597 pri_hangup(p->pri->pri, p->call, icause);
03598 }
03599 if (res < 0)
03600 ast_log(LOG_WARNING, "pri_disconnect failed\n");
03601 pri_rel(p->pri);
03602 } else {
03603 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03604 res = -1;
03605 }
03606 } else {
03607 if (p->bearer)
03608 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03609 p->call = NULL;
03610 res = 0;
03611 }
03612 }
03613 #endif
03614 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03615 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03616 if (res < 0) {
03617 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03618 }
03619 switch (p->sig) {
03620 case SIG_FXOGS:
03621 case SIG_FXOLS:
03622 case SIG_FXOKS:
03623 memset(&par, 0, sizeof(par));
03624 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03625 if (!res) {
03626 #if 0
03627 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03628 #endif
03629
03630 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03631 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03632 else
03633 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03634 }
03635 break;
03636 case SIG_FXSGS:
03637 case SIG_FXSLS:
03638 case SIG_FXSKS:
03639
03640
03641 if (ast->_state != AST_STATE_RESERVED) {
03642 time(&p->guardtime);
03643 p->guardtime += 2;
03644 }
03645 break;
03646 default:
03647 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03648 }
03649 if (p->cidspill)
03650 ast_free(p->cidspill);
03651 if (p->sig)
03652 dahdi_disable_ec(p);
03653 x = 0;
03654 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03655 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03656 p->didtdd = 0;
03657 p->cidspill = NULL;
03658 p->callwaitcas = 0;
03659 p->callwaiting = p->permcallwaiting;
03660 p->hidecallerid = p->permhidecallerid;
03661 p->dialing = 0;
03662 p->rdnis[0] = '\0';
03663 update_conf(p);
03664 reset_conf(p);
03665
03666 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03667 x = 0;
03668 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03669 }
03670 #ifdef HAVE_PRI
03671 if (p->bearer) {
03672 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03673
03674
03675 update_conf(p->bearer);
03676 reset_conf(p->bearer);
03677 p->bearer->owner = NULL;
03678 p->bearer->realcall = NULL;
03679 p->bearer = NULL;
03680 p->subs[SUB_REAL].dfd = -1;
03681 p->pri = NULL;
03682 }
03683 #endif
03684 if (num_restart_pending == 0)
03685 restart_monitor();
03686 }
03687
03688 p->callwaitingrepeat = 0;
03689 p->cidcwexpire = 0;
03690 p->oprmode = 0;
03691 ast->tech_pvt = NULL;
03692 ast_mutex_unlock(&p->lock);
03693 ast_module_unref(ast_module_info->self);
03694 ast_verb(3, "Hungup '%s'\n", ast->name);
03695
03696 ast_mutex_lock(&iflock);
03697
03698 if (p->restartpending) {
03699 num_restart_pending--;
03700 }
03701
03702 tmp = iflist;
03703 prev = NULL;
03704 if (p->destroy) {
03705 while (tmp) {
03706 if (tmp == p) {
03707 destroy_channel(prev, tmp, 0);
03708 break;
03709 } else {
03710 prev = tmp;
03711 tmp = tmp->next;
03712 }
03713 }
03714 }
03715 ast_mutex_unlock(&iflock);
03716 return 0;
03717 }
03718
03719 static int dahdi_answer(struct ast_channel *ast)
03720 {
03721 struct dahdi_pvt *p = ast->tech_pvt;
03722 int res = 0;
03723 int index;
03724 int oldstate = ast->_state;
03725 ast_setstate(ast, AST_STATE_UP);
03726 ast_mutex_lock(&p->lock);
03727 index = dahdi_get_index(ast, p, 0);
03728 if (index < 0)
03729 index = SUB_REAL;
03730
03731 if ((p->radio || (p->oprmode < 0))) {
03732 ast_mutex_unlock(&p->lock);
03733 return 0;
03734 }
03735 switch (p->sig) {
03736 case SIG_FXSLS:
03737 case SIG_FXSGS:
03738 case SIG_FXSKS:
03739 p->ringt = 0;
03740
03741 case SIG_EM:
03742 case SIG_EM_E1:
03743 case SIG_EMWINK:
03744 case SIG_FEATD:
03745 case SIG_FEATDMF:
03746 case SIG_FEATDMF_TA:
03747 case SIG_E911:
03748 case SIG_FGC_CAMA:
03749 case SIG_FGC_CAMAMF:
03750 case SIG_FEATB:
03751 case SIG_SF:
03752 case SIG_SFWINK:
03753 case SIG_SF_FEATD:
03754 case SIG_SF_FEATDMF:
03755 case SIG_SF_FEATB:
03756 case SIG_FXOLS:
03757 case SIG_FXOGS:
03758 case SIG_FXOKS:
03759
03760 ast_debug(1, "Took %s off hook\n", ast->name);
03761 if (p->hanguponpolarityswitch) {
03762 p->polaritydelaytv = ast_tvnow();
03763 }
03764 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03765 tone_zone_play_tone(p->subs[index].dfd, -1);
03766 p->dialing = 0;
03767 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03768 if (oldstate == AST_STATE_RINGING) {
03769 ast_debug(1, "Finally swapping real and threeway\n");
03770 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03771 swap_subs(p, SUB_THREEWAY, SUB_REAL);
03772 p->owner = p->subs[SUB_REAL].owner;
03773 }
03774 }
03775 if (p->sig & __DAHDI_SIG_FXS) {
03776 dahdi_enable_ec(p);
03777 dahdi_train_ec(p);
03778 }
03779 break;
03780 #ifdef HAVE_PRI
03781 case SIG_BRI:
03782 case SIG_BRI_PTMP:
03783 case SIG_PRI:
03784
03785 if (!pri_grab(p, p->pri)) {
03786 p->proceeding = 1;
03787 p->dialing = 0;
03788 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03789 pri_rel(p->pri);
03790 } else {
03791 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03792 res = -1;
03793 }
03794 break;
03795 #endif
03796 #ifdef HAVE_SS7
03797 case SIG_SS7:
03798 if (!ss7_grab(p, p->ss7)) {
03799 p->proceeding = 1;
03800 res = isup_anm(p->ss7->ss7, p->ss7call);
03801 ss7_rel(p->ss7);
03802 } else {
03803 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03804 res = -1;
03805 }
03806 break;
03807 #endif
03808 case 0:
03809 ast_mutex_unlock(&p->lock);
03810 return 0;
03811 default:
03812 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03813 res = -1;
03814 }
03815 ast_mutex_unlock(&p->lock);
03816 return res;
03817 }
03818
03819 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03820 {
03821 char *cp;
03822 signed char *scp;
03823 int x;
03824 int index;
03825 struct dahdi_pvt *p = chan->tech_pvt, *pp;
03826 struct oprmode *oprmode;
03827
03828
03829
03830 if (!data || (datalen < 1)) {
03831 errno = EINVAL;
03832 return -1;
03833 }
03834
03835 switch (option) {
03836 case AST_OPTION_TXGAIN:
03837 scp = (signed char *) data;
03838 index = dahdi_get_index(chan, p, 0);
03839 if (index < 0) {
03840 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03841 return -1;
03842 }
03843 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03844 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03845 case AST_OPTION_RXGAIN:
03846 scp = (signed char *) data;
03847 index = dahdi_get_index(chan, p, 0);
03848 if (index < 0) {
03849 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03850 return -1;
03851 }
03852 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03853 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03854 case AST_OPTION_TONE_VERIFY:
03855 if (!p->dsp)
03856 break;
03857 cp = (char *) data;
03858 switch (*cp) {
03859 case 1:
03860 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03861 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
03862 break;
03863 case 2:
03864 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03865 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
03866 break;
03867 default:
03868 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03869 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03870 break;
03871 }
03872 break;
03873 case AST_OPTION_TDD:
03874
03875 cp = (char *) data;
03876 p->mate = 0;
03877 if (!*cp) {
03878 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03879 if (p->tdd)
03880 tdd_free(p->tdd);
03881 p->tdd = 0;
03882 break;
03883 }
03884 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03885 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03886 dahdi_disable_ec(p);
03887
03888 if (!p->didtdd) {
03889 unsigned char mybuf[41000];
03890 unsigned char *buf;
03891 int size, res, fd, len;
03892 struct pollfd fds[1];
03893
03894 buf = mybuf;
03895 memset(buf, 0x7f, sizeof(mybuf));
03896 ast_tdd_gen_ecdisa(buf + 16000, 16000);
03897 len = 40000;
03898 index = dahdi_get_index(chan, p, 0);
03899 if (index < 0) {
03900 ast_log(LOG_WARNING, "No index in TDD?\n");
03901 return -1;
03902 }
03903 fd = p->subs[index].dfd;
03904 while (len) {
03905 if (ast_check_hangup(chan))
03906 return -1;
03907 size = len;
03908 if (size > READ_SIZE)
03909 size = READ_SIZE;
03910 fds[0].fd = fd;
03911 fds[0].events = POLLPRI | POLLOUT;
03912 fds[0].revents = 0;
03913 res = poll(fds, 1, -1);
03914 if (!res) {
03915 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03916 continue;
03917 }
03918
03919 if (fds[0].revents & POLLPRI)
03920 return -1;
03921 if (!(fds[0].revents & POLLOUT)) {
03922 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03923 continue;
03924 }
03925 res = write(fd, buf, size);
03926 if (res != size) {
03927 if (res == -1) return -1;
03928 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03929 break;
03930 }
03931 len -= size;
03932 buf += size;
03933 }
03934 p->didtdd = 1;
03935 }
03936 if (*cp == 2) {
03937 if (p->tdd)
03938 tdd_free(p->tdd);
03939 p->tdd = 0;
03940 p->mate = 1;
03941 break;
03942 }
03943 if (!p->tdd) {
03944 p->tdd = tdd_new();
03945 }
03946 break;
03947 case AST_OPTION_RELAXDTMF:
03948 if (!p->dsp)
03949 break;
03950 cp = (char *) data;
03951 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03952 *cp ? "ON" : "OFF", (int) *cp, chan->name);
03953 ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03954 break;
03955 case AST_OPTION_AUDIO_MODE:
03956 cp = (char *) data;
03957 if (!*cp) {
03958 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03959 x = 0;
03960 dahdi_disable_ec(p);
03961 } else {
03962 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03963 x = 1;
03964 }
03965 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03966 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03967 break;
03968 case AST_OPTION_OPRMODE:
03969 oprmode = (struct oprmode *) data;
03970 pp = oprmode->peer->tech_pvt;
03971 p->oprmode = pp->oprmode = 0;
03972
03973 p->oprpeer = pp;
03974 pp->oprpeer = p;
03975
03976 if (oprmode->mode)
03977 {
03978 pp->oprmode = oprmode->mode;
03979 p->oprmode = -oprmode->mode;
03980 }
03981 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
03982 oprmode->mode, chan->name,oprmode->peer->name);
03983 break;
03984 case AST_OPTION_ECHOCAN:
03985 cp = (char *) data;
03986 if (*cp) {
03987 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
03988 dahdi_enable_ec(p);
03989 } else {
03990 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
03991 dahdi_disable_ec(p);
03992 }
03993 break;
03994 }
03995 errno = 0;
03996
03997 return 0;
03998 }
03999
04000 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04001 {
04002 struct dahdi_pvt *p = chan->tech_pvt;
04003
04004 if (!strcasecmp(data, "rxgain")) {
04005 ast_mutex_lock(&p->lock);
04006 snprintf(buf, len, "%f", p->rxgain);
04007 ast_mutex_unlock(&p->lock);
04008 } else if (!strcasecmp(data, "txgain")) {
04009 ast_mutex_lock(&p->lock);
04010 snprintf(buf, len, "%f", p->txgain);
04011 ast_mutex_unlock(&p->lock);
04012 } else {
04013 ast_copy_string(buf, "", len);
04014 }
04015 return 0;
04016 }
04017
04018
04019 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04020 {
04021
04022 int x;
04023 int hasslaves;
04024 if (!master)
04025 return;
04026 if (needlock) {
04027 ast_mutex_lock(&master->lock);
04028 if (slave) {
04029 while (ast_mutex_trylock(&slave->lock)) {
04030 DEADLOCK_AVOIDANCE(&master->lock);
04031 }
04032 }
04033 }
04034 hasslaves = 0;
04035 for (x = 0; x < MAX_SLAVES; x++) {
04036 if (master->slaves[x]) {
04037 if (!slave || (master->slaves[x] == slave)) {
04038
04039 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04040 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04041 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04042 master->slaves[x]->master = NULL;
04043 master->slaves[x] = NULL;
04044 } else
04045 hasslaves = 1;
04046 }
04047 if (!hasslaves)
04048 master->inconference = 0;
04049 }
04050 if (!slave) {
04051 if (master->master) {
04052
04053 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04054 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04055 hasslaves = 0;
04056 for (x = 0; x < MAX_SLAVES; x++) {
04057 if (master->master->slaves[x] == master)
04058 master->master->slaves[x] = NULL;
04059 else if (master->master->slaves[x])
04060 hasslaves = 1;
04061 }
04062 if (!hasslaves)
04063 master->master->inconference = 0;
04064 }
04065 master->master = NULL;
04066 }
04067 update_conf(master);
04068 if (needlock) {
04069 if (slave)
04070 ast_mutex_unlock(&slave->lock);
04071 ast_mutex_unlock(&master->lock);
04072 }
04073 }
04074
04075 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04076 int x;
04077 if (!slave || !master) {
04078 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04079 return;
04080 }
04081 for (x = 0; x < MAX_SLAVES; x++) {
04082 if (!master->slaves[x]) {
04083 master->slaves[x] = slave;
04084 break;
04085 }
04086 }
04087 if (x >= MAX_SLAVES) {
04088 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04089 master->slaves[MAX_SLAVES - 1] = slave;
04090 }
04091 if (slave->master)
04092 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04093 slave->master = master;
04094
04095 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04096 }
04097
04098 static void disable_dtmf_detect(struct dahdi_pvt *p)
04099 {
04100 int val;
04101
04102 p->ignoredtmf = 1;
04103
04104 val = 0;
04105 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04106
04107 if (!p->hardwaredtmf && p->dsp) {
04108 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04109 ast_dsp_set_features(p->dsp, p->dsp_features);
04110 }
04111 }
04112
04113 static void enable_dtmf_detect(struct dahdi_pvt *p)
04114 {
04115 int val;
04116
04117 if (p->channel == CHAN_PSEUDO)
04118 return;
04119
04120 p->ignoredtmf = 0;
04121
04122 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04123 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04124
04125 if (!p->hardwaredtmf && p->dsp) {
04126 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04127 ast_dsp_set_features(p->dsp, p->dsp_features);
04128 }
04129 }
04130
04131 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)
04132 {
04133 struct ast_channel *who;
04134 struct dahdi_pvt *p0, *p1, *op0, *op1;
04135 struct dahdi_pvt *master = NULL, *slave = NULL;
04136 struct ast_frame *f;
04137 int inconf = 0;
04138 int nothingok = 1;
04139 int ofd0, ofd1;
04140 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04141 int os0 = -1, os1 = -1;
04142 int priority = 0;
04143 struct ast_channel *oc0, *oc1;
04144 enum ast_bridge_result res;
04145
04146 #ifdef PRI_2BCT
04147 int triedtopribridge = 0;
04148 q931_call *q931c0 = NULL, *q931c1 = NULL;
04149 #endif
04150
04151
04152
04153
04154
04155
04156 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04157 return AST_BRIDGE_FAILED_NOWARN;
04158
04159 ast_channel_lock(c0);
04160 while (ast_channel_trylock(c1)) {
04161 ast_channel_unlock(c0);
04162 usleep(1);
04163 ast_channel_lock(c0);
04164 }
04165
04166 p0 = c0->tech_pvt;
04167 p1 = c1->tech_pvt;
04168
04169 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04170 ast_channel_unlock(c0);
04171 ast_channel_unlock(c1);
04172 return AST_BRIDGE_FAILED_NOWARN;
04173 }
04174
04175 oi0 = dahdi_get_index(c0, p0, 0);
04176 oi1 = dahdi_get_index(c1, p1, 0);
04177 if ((oi0 < 0) || (oi1 < 0)) {
04178 ast_channel_unlock(c0);
04179 ast_channel_unlock(c1);
04180 return AST_BRIDGE_FAILED;
04181 }
04182
04183 op0 = p0 = c0->tech_pvt;
04184 op1 = p1 = c1->tech_pvt;
04185 ofd0 = c0->fds[0];
04186 ofd1 = c1->fds[0];
04187 oc0 = p0->owner;
04188 oc1 = p1->owner;
04189
04190 if (ast_mutex_trylock(&p0->lock)) {
04191
04192 ast_channel_unlock(c0);
04193 ast_channel_unlock(c1);
04194 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04195 return AST_BRIDGE_RETRY;
04196 }
04197 if (ast_mutex_trylock(&p1->lock)) {
04198
04199 ast_mutex_unlock(&p0->lock);
04200 ast_channel_unlock(c0);
04201 ast_channel_unlock(c1);
04202 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04203 return AST_BRIDGE_RETRY;
04204 }
04205
04206 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04207 if (p0->owner && p1->owner) {
04208
04209 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04210 master = p0;
04211 slave = p1;
04212 inconf = 1;
04213 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04214 master = p1;
04215 slave = p0;
04216 inconf = 1;
04217 } else {
04218 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
04219 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04220 p0->channel,
04221 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04222 p0->subs[SUB_REAL].inthreeway, p0->channel,
04223 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04224 p1->subs[SUB_REAL].inthreeway);
04225 }
04226 nothingok = 0;
04227 }
04228 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04229 if (p1->subs[SUB_THREEWAY].inthreeway) {
04230 master = p1;
04231 slave = p0;
04232 nothingok = 0;
04233 }
04234 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04235 if (p0->subs[SUB_THREEWAY].inthreeway) {
04236 master = p0;
04237 slave = p1;
04238 nothingok = 0;
04239 }
04240 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04241
04242
04243 if (p1->subs[SUB_CALLWAIT].inthreeway) {
04244 master = p1;
04245 slave = p0;
04246 nothingok = 0;
04247 }
04248 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04249
04250 if (p0->subs[SUB_CALLWAIT].inthreeway) {
04251 master = p0;
04252 slave = p1;
04253 nothingok = 0;
04254 }
04255 }
04256 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04257 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04258 if (master && slave) {
04259
04260
04261
04262 if ((oi1 == SUB_THREEWAY) &&
04263 p1->subs[SUB_THREEWAY].inthreeway &&
04264 p1->subs[SUB_REAL].owner &&
04265 p1->subs[SUB_REAL].inthreeway &&
04266 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04267 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04268 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04269 os1 = p1->subs[SUB_REAL].owner->_state;
04270 } else {
04271 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04272 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04273 }
04274 if ((oi0 == SUB_THREEWAY) &&
04275 p0->subs[SUB_THREEWAY].inthreeway &&
04276 p0->subs[SUB_REAL].owner &&
04277 p0->subs[SUB_REAL].inthreeway &&
04278 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04279 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04280 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04281 os0 = p0->subs[SUB_REAL].owner->_state;
04282 } else {
04283 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04284 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04285 }
04286 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04287 if (!p0->echocanbridged || !p1->echocanbridged) {
04288
04289 dahdi_disable_ec(p0);
04290 dahdi_disable_ec(p1);
04291 }
04292 }
04293 dahdi_link(slave, master);
04294 master->inconference = inconf;
04295 } else if (!nothingok)
04296 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04297
04298 update_conf(p0);
04299 update_conf(p1);
04300 t0 = p0->subs[SUB_REAL].inthreeway;
04301 t1 = p1->subs[SUB_REAL].inthreeway;
04302
04303 ast_mutex_unlock(&p0->lock);
04304 ast_mutex_unlock(&p1->lock);
04305
04306 ast_channel_unlock(c0);
04307 ast_channel_unlock(c1);
04308
04309
04310 if ((!master || !slave) && !nothingok) {
04311 dahdi_enable_ec(p0);
04312 dahdi_enable_ec(p1);
04313 return AST_BRIDGE_FAILED;
04314 }
04315
04316 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04317
04318 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04319 disable_dtmf_detect(op0);
04320
04321 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04322 disable_dtmf_detect(op1);
04323
04324 for (;;) {
04325 struct ast_channel *c0_priority[2] = {c0, c1};
04326 struct ast_channel *c1_priority[2] = {c1, c0};
04327
04328
04329
04330
04331 ast_channel_lock(c0);
04332 while (ast_channel_trylock(c1)) {
04333 ast_channel_unlock(c0);
04334 usleep(1);
04335 ast_channel_lock(c0);
04336 }
04337
04338 p0 = c0->tech_pvt;
04339 p1 = c1->tech_pvt;
04340
04341 if (op0 == p0)
04342 i0 = dahdi_get_index(c0, p0, 1);
04343 if (op1 == p1)
04344 i1 = dahdi_get_index(c1, p1, 1);
04345
04346 ast_channel_unlock(c0);
04347 ast_channel_unlock(c1);
04348
04349 if (!timeoutms ||
04350 (op0 != p0) ||
04351 (op1 != p1) ||
04352 (ofd0 != c0->fds[0]) ||
04353 (ofd1 != c1->fds[0]) ||
04354 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
04355 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
04356 (oc0 != p0->owner) ||
04357 (oc1 != p1->owner) ||
04358 (t0 != p0->subs[SUB_REAL].inthreeway) ||
04359 (t1 != p1->subs[SUB_REAL].inthreeway) ||
04360 (oi0 != i0) ||
04361 (oi1 != i1)) {
04362 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04363 op0->channel, oi0, op1->channel, oi1);
04364 res = AST_BRIDGE_RETRY;
04365 goto return_from_bridge;
04366 }
04367
04368 #ifdef PRI_2BCT
04369 q931c0 = p0->call;
04370 q931c1 = p1->call;
04371 if (p0->transfer && p1->transfer
04372 && q931c0 && q931c1
04373 && !triedtopribridge) {
04374 pri_channel_bridge(q931c0, q931c1);
04375 triedtopribridge = 1;
04376 }
04377 #endif
04378
04379 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04380 if (!who) {
04381 ast_debug(1, "Ooh, empty read...\n");
04382 continue;
04383 }
04384 f = ast_read(who);
04385 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04386 *fo = f;
04387 *rc = who;
04388 res = AST_BRIDGE_COMPLETE;
04389 goto return_from_bridge;
04390 }
04391 if (f->frametype == AST_FRAME_DTMF) {
04392 if ((who == c0) && p0->pulsedial) {
04393 ast_write(c1, f);
04394 } else if ((who == c1) && p1->pulsedial) {
04395 ast_write(c0, f);
04396 } else {
04397 *fo = f;
04398 *rc = who;
04399 res = AST_BRIDGE_COMPLETE;
04400 goto return_from_bridge;
04401 }
04402 }
04403 ast_frfree(f);
04404
04405
04406 priority = !priority;
04407 }
04408
04409 return_from_bridge:
04410 if (op0 == p0)
04411 dahdi_enable_ec(p0);
04412
04413 if (op1 == p1)
04414 dahdi_enable_ec(p1);
04415
04416 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04417 enable_dtmf_detect(op0);
04418
04419 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04420 enable_dtmf_detect(op1);
04421
04422 dahdi_unlink(slave, master, 1);
04423
04424 return res;
04425 }
04426
04427 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04428 {
04429 struct dahdi_pvt *p = newchan->tech_pvt;
04430 int x;
04431 ast_mutex_lock(&p->lock);
04432 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04433 if (p->owner == oldchan) {
04434 p->owner = newchan;
04435 }
04436 for (x = 0; x < 3; x++)
04437 if (p->subs[x].owner == oldchan) {
04438 if (!x)
04439 dahdi_unlink(NULL, p, 0);
04440 p->subs[x].owner = newchan;
04441 }
04442 if (newchan->_state == AST_STATE_RINGING)
04443 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04444 update_conf(p);
04445 ast_mutex_unlock(&p->lock);
04446 return 0;
04447 }
04448
04449 static int dahdi_ring_phone(struct dahdi_pvt *p)
04450 {
04451 int x;
04452 int res;
04453
04454 x = 0;
04455 x = DAHDI_ONHOOK;
04456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04457 do {
04458 x = DAHDI_RING;
04459 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04460 if (res) {
04461 switch (errno) {
04462 case EBUSY:
04463 case EINTR:
04464
04465 usleep(10000);
04466 continue;
04467 case EINPROGRESS:
04468 res = 0;
04469 break;
04470 default:
04471 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04472 res = 0;
04473 }
04474 }
04475 } while (res);
04476 return res;
04477 }
04478
04479 static void *ss_thread(void *data);
04480
04481 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04482
04483 static int attempt_transfer(struct dahdi_pvt *p)
04484 {
04485
04486
04487
04488 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04489
04490
04491 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04492 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04493 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04494 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04495 }
04496 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04497 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04498 }
04499 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04500 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04501 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04502 return -1;
04503 }
04504
04505 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04506 unalloc_sub(p, SUB_THREEWAY);
04507 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04508 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04509 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04510 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04511 }
04512 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04513 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04514 }
04515 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04516 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04517 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04518 return -1;
04519 }
04520
04521 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04522 ast_channel_unlock(p->subs[SUB_REAL].owner);
04523 unalloc_sub(p, SUB_THREEWAY);
04524
04525 return 1;
04526 } else {
04527 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04528 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04529 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04530 return -1;
04531 }
04532 return 0;
04533 }
04534
04535 static int check_for_conference(struct dahdi_pvt *p)
04536 {
04537 struct dahdi_confinfo ci;
04538
04539 if (p->master || (p->confno > -1))
04540 return 0;
04541 memset(&ci, 0, sizeof(ci));
04542 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04543 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04544 return 0;
04545 }
04546
04547
04548
04549 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04550 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04551 return 1;
04552 }
04553 return 0;
04554 }
04555
04556
04557
04558
04559
04560
04561 static int get_alarms(struct dahdi_pvt *p)
04562 {
04563 int res;
04564 struct dahdi_spaninfo zi;
04565 struct dahdi_params params;
04566
04567 memset(&zi, 0, sizeof(zi));
04568 zi.spanno = p->span;
04569
04570 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04571 if (zi.alarms != DAHDI_ALARM_NONE)
04572 return zi.alarms;
04573 } else {
04574 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04575 return 0;
04576 }
04577
04578
04579 memset(¶ms, 0, sizeof(params));
04580 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
04581 return params.chan_alarms;
04582
04583 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04584
04585 return DAHDI_ALARM_NONE;
04586 }
04587
04588 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04589 {
04590 struct dahdi_pvt *p = ast->tech_pvt;
04591 struct ast_frame *f = *dest;
04592
04593 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04594
04595 if (p->confirmanswer) {
04596 ast_debug(1, "Confirm answer on %s!\n", ast->name);
04597
04598
04599 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04600 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04601 *dest = &p->subs[index].f;
04602
04603 p->confirmanswer = 0;
04604 } else if (p->callwaitcas) {
04605 if ((f->subclass == 'A') || (f->subclass == 'D')) {
04606 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04607 if (p->cidspill)
04608 ast_free(p->cidspill);
04609 send_cwcidspill(p);
04610 }
04611 if ((f->subclass != 'm') && (f->subclass != 'u'))
04612 p->callwaitcas = 0;
04613 p->subs[index].f.frametype = AST_FRAME_NULL;
04614 p->subs[index].f.subclass = 0;
04615 *dest = &p->subs[index].f;
04616 } else if (f->subclass == 'f') {
04617
04618 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04619 p->faxhandled = 1;
04620 if (strcmp(ast->exten, "fax")) {
04621 const char *target_context = S_OR(ast->macrocontext, ast->context);
04622
04623
04624
04625
04626
04627 ast_mutex_unlock(&p->lock);
04628 ast_channel_unlock(ast);
04629 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04630 ast_channel_lock(ast);
04631 ast_mutex_lock(&p->lock);
04632 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04633
04634 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04635 if (ast_async_goto(ast, target_context, "fax", 1))
04636 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04637 } else {
04638 ast_channel_lock(ast);
04639 ast_mutex_lock(&p->lock);
04640 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04641 }
04642 } else {
04643 ast_debug(1, "Already in a fax extension, not redirecting\n");
04644 }
04645 } else {
04646 ast_debug(1, "Fax already handled\n");
04647 }
04648 dahdi_confmute(p, 0);
04649 p->subs[index].f.frametype = AST_FRAME_NULL;
04650 p->subs[index].f.subclass = 0;
04651 *dest = &p->subs[index].f;
04652 } else if (f->subclass == 'm') {
04653
04654 dahdi_confmute(p, 1);
04655 p->subs[index].f.frametype = AST_FRAME_NULL;
04656 p->subs[index].f.subclass = 0;
04657 *dest = &p->subs[index].f;
04658 } else if (f->subclass == 'u') {
04659
04660 dahdi_confmute(p, 0);
04661 p->subs[index].f.frametype = AST_FRAME_NULL;
04662 p->subs[index].f.subclass = 0;
04663 *dest = &p->subs[index].f;
04664 } else
04665 dahdi_confmute(p, 0);
04666 }
04667
04668 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04669 {
04670 const char *alarm_str = alarm2str(alarms);
04671
04672 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04673 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04674 "Alarm: %s\r\n"
04675 "Channel: %d\r\n",
04676 alarm_str, p->channel);
04677 }
04678
04679 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04680 {
04681 int res, x;
04682 int index, mysig;
04683 char *c;
04684 struct dahdi_pvt *p = ast->tech_pvt;
04685 pthread_t threadid;
04686 struct ast_channel *chan;
04687 struct ast_frame *f;
04688
04689 index = dahdi_get_index(ast, p, 0);
04690 mysig = p->sig;
04691 if (p->outsigmod > -1)
04692 mysig = p->outsigmod;
04693 p->subs[index].f.frametype = AST_FRAME_NULL;
04694 p->subs[index].f.subclass = 0;
04695 p->subs[index].f.datalen = 0;
04696 p->subs[index].f.samples = 0;
04697 p->subs[index].f.mallocd = 0;
04698 p->subs[index].f.offset = 0;
04699 p->subs[index].f.src = "dahdi_handle_event";
04700 p->subs[index].f.data = NULL;
04701 f = &p->subs[index].f;
04702
04703 if (index < 0)
04704 return &p->subs[index].f;
04705 if (p->fake_event) {
04706 res = p->fake_event;
04707 p->fake_event = 0;
04708 } else
04709 res = dahdi_get_event(p->subs[index].dfd);
04710
04711 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04712
04713 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04714 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04715 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04716 #ifdef HAVE_PRI
04717 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04718
04719 } else {
04720 #endif
04721 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04722 p->subs[index].f.subclass = res & 0xff;
04723 #ifdef HAVE_PRI
04724 }
04725 #endif
04726 dahdi_handle_dtmfup(ast, index, &f);
04727 return f;
04728 }
04729
04730 if (res & DAHDI_EVENT_DTMFDOWN) {
04731 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04732
04733 dahdi_confmute(p, 1);
04734 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04735 p->subs[index].f.subclass = res & 0xff;
04736 return &p->subs[index].f;
04737 }
04738
04739 switch (res) {
04740 case DAHDI_EVENT_EC_DISABLED:
04741 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04742 p->echocanon = 0;
04743 break;
04744 case DAHDI_EVENT_BITSCHANGED:
04745 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04746 case DAHDI_EVENT_PULSE_START:
04747
04748 if (!ast->pbx)
04749 tone_zone_play_tone(p->subs[index].dfd, -1);
04750 break;
04751 case DAHDI_EVENT_DIALCOMPLETE:
04752 if (p->inalarm) break;
04753 if ((p->radio || (p->oprmode < 0))) break;
04754 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04755 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04756 return NULL;
04757 }
04758 if (!x) {
04759 dahdi_enable_ec(p);
04760 if (p->echobreak) {
04761 dahdi_train_ec(p);
04762 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04763 p->dop.op = DAHDI_DIAL_OP_REPLACE;
04764 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04765 p->echobreak = 0;
04766 } else {
04767 p->dialing = 0;
04768 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04769
04770 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04771 ast_setstate(ast, AST_STATE_UP);
04772 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04773 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04774 break;
04775 } else {
04776
04777 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04778 }
04779 }
04780 if (ast->_state == AST_STATE_DIALING) {
04781 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04782 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04783 } 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)))) {
04784 ast_setstate(ast, AST_STATE_RINGING);
04785 } else if (!p->answeronpolarityswitch) {
04786 ast_setstate(ast, AST_STATE_UP);
04787 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04788 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04789
04790 p->polarity = POLARITY_REV;
04791 } else {
04792
04793 p->polarity = POLARITY_IDLE;
04794 }
04795 }
04796 }
04797 }
04798 break;
04799 case DAHDI_EVENT_ALARM:
04800 #ifdef HAVE_PRI
04801 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04802 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04803
04804 if (p->call) {
04805 if (p->pri && p->pri->pri) {
04806 if (!pri_grab(p, p->pri)) {
04807 pri_hangup(p->pri->pri, p->call, -1);
04808 pri_destroycall(p->pri->pri, p->call);
04809 p->call = NULL;
04810 pri_rel(p->pri);
04811 } else
04812 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04813 } else
04814 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04815 }
04816 if (p->owner)
04817 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04818 }
04819 }
04820 if (p->bearer)
04821 p->bearer->inalarm = 1;
04822 else
04823 #endif
04824 p->inalarm = 1;
04825 res = get_alarms(p);
04826 handle_alarms(p, res);
04827 #ifdef HAVE_PRI
04828 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04829
04830 } else {
04831 break;
04832 }
04833 #endif
04834 #ifdef HAVE_SS7
04835 if (p->sig == SIG_SS7)
04836 break;
04837 #endif
04838 case DAHDI_EVENT_ONHOOK:
04839 if (p->radio) {
04840 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04841 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04842 break;
04843 }
04844 if (p->oprmode < 0)
04845 {
04846 if (p->oprmode != -1) break;
04847 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04848 {
04849
04850 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04851 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04852 save_conference(p->oprpeer);
04853 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04854 }
04855 break;
04856 }
04857 switch (p->sig) {
04858 case SIG_FXOLS:
04859 case SIG_FXOGS:
04860 case SIG_FXOKS:
04861 p->onhooktime = time(NULL);
04862 p->msgstate = -1;
04863
04864 if (index == SUB_REAL) {
04865
04866 if (p->subs[SUB_CALLWAIT].owner) {
04867
04868 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04869 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04870 unalloc_sub(p, SUB_CALLWAIT);
04871 #if 0
04872 p->subs[index].needanswer = 0;
04873 p->subs[index].needringing = 0;
04874 #endif
04875 p->callwaitingrepeat = 0;
04876 p->cidcwexpire = 0;
04877 p->owner = NULL;
04878
04879 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04880 p->dialing = 1;
04881 dahdi_ring_phone(p);
04882 } else if (p->subs[SUB_THREEWAY].owner) {
04883 unsigned int mssinceflash;
04884
04885
04886 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04887
04888 ast_mutex_unlock(&p->lock);
04889 ast_channel_unlock(ast);
04890 usleep(1);
04891
04892
04893
04894 ast_channel_lock(ast);
04895 ast_mutex_lock(&p->lock);
04896 if (p->owner != ast) {
04897 ast_log(LOG_WARNING, "This isn't good...\n");
04898 return NULL;
04899 }
04900 }
04901 if (!p->subs[SUB_THREEWAY].owner) {
04902 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04903 return NULL;
04904 }
04905 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04906 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04907 if (mssinceflash < MIN_MS_SINCE_FLASH) {
04908
04909
04910 if (p->subs[SUB_THREEWAY].owner)
04911 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04912 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04913 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04914 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04915 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04916 if (p->transfer) {
04917
04918 p->subs[SUB_REAL].inthreeway = 0;
04919 p->subs[SUB_THREEWAY].inthreeway = 0;
04920
04921 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04922 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04923
04924 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04925 p->owner = NULL;
04926
04927 dahdi_ring_phone(p);
04928 } else {
04929 if ((res = attempt_transfer(p)) < 0) {
04930 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04931 if (p->subs[SUB_THREEWAY].owner)
04932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04933 } else if (res) {
04934
04935 if (p->subs[SUB_THREEWAY].owner)
04936 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04937 break;
04938 }
04939 }
04940 } else {
04941 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04942 if (p->subs[SUB_THREEWAY].owner)
04943 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04944 }
04945 } else {
04946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04947
04948 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04949 p->owner = NULL;
04950
04951 dahdi_ring_phone(p);
04952 }
04953 }
04954 } else {
04955 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04956 }
04957
04958 default:
04959 dahdi_disable_ec(p);
04960 return NULL;
04961 }
04962 break;
04963 case DAHDI_EVENT_RINGOFFHOOK:
04964 if (p->inalarm) break;
04965 if (p->oprmode < 0)
04966 {
04967 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04968 {
04969
04970 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04971 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04972 restore_conference(p->oprpeer);
04973 }
04974 break;
04975 }
04976 if (p->radio)
04977 {
04978 p->subs[index].f.frametype = AST_FRAME_CONTROL;
04979 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04980 break;
04981 }
04982
04983
04984 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04985 c = strchr(p->dialdest, '/');
04986 if (c)
04987 c++;
04988 else
04989 c = p->dialdest;
04990 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04991 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04992 if (strlen(p->dop.dialstr) > 4) {
04993 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04994 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04995 p->echorest[sizeof(p->echorest) - 1] = '\0';
04996 p->echobreak = 1;
04997 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04998 } else
04999 p->echobreak = 0;
05000 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05001 int saveerr = errno;
05002
05003 x = DAHDI_ONHOOK;
05004 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05005 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05006 return NULL;
05007 }
05008 p->dialing = 1;
05009 return &p->subs[index].f;
05010 }
05011 switch (p->sig) {
05012 case SIG_FXOLS:
05013 case SIG_FXOGS:
05014 case SIG_FXOKS:
05015 switch (ast->_state) {
05016 case AST_STATE_RINGING:
05017 dahdi_enable_ec(p);
05018 dahdi_train_ec(p);
05019 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05020 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05021
05022 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05023 ast_debug(1, "channel %d answered\n", p->channel);
05024 if (p->cidspill) {
05025
05026 ast_free(p->cidspill);
05027 p->cidspill = NULL;
05028 }
05029 p->dialing = 0;
05030 p->callwaitcas = 0;
05031 if (p->confirmanswer) {
05032
05033 p->subs[index].f.frametype = AST_FRAME_NULL;
05034 p->subs[index].f.subclass = 0;
05035 } else if (!ast_strlen_zero(p->dop.dialstr)) {
05036
05037 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05038 if (res < 0) {
05039 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05040 p->dop.dialstr[0] = '\0';
05041 return NULL;
05042 } else {
05043 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05044 p->subs[index].f.frametype = AST_FRAME_NULL;
05045 p->subs[index].f.subclass = 0;
05046 p->dialing = 1;
05047 }
05048 p->dop.dialstr[0] = '\0';
05049 ast_setstate(ast, AST_STATE_DIALING);
05050 } else
05051 ast_setstate(ast, AST_STATE_UP);
05052 return &p->subs[index].f;
05053 case AST_STATE_DOWN:
05054 ast_setstate(ast, AST_STATE_RING);
05055 ast->rings = 1;
05056 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05057 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05058 ast_debug(1, "channel %d picked up\n", p->channel);
05059 return &p->subs[index].f;
05060 case AST_STATE_UP:
05061
05062 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05063
05064 if (ast_bridged_channel(p->owner))
05065 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05066 p->subs[index].needunhold = 1;
05067 break;
05068 case AST_STATE_RESERVED:
05069
05070 if (has_voicemail(p))
05071 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05072 else
05073 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05074 break;
05075 default:
05076 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05077 }
05078 break;
05079 case SIG_FXSLS:
05080 case SIG_FXSGS:
05081 case SIG_FXSKS:
05082 if (ast->_state == AST_STATE_RING) {
05083 p->ringt = p->ringt_base;
05084 }
05085
05086
05087
05088 ast_debug(1, "Setting IDLE polarity due "
05089 "to ring. Old polarity was %d\n",
05090 p->polarity);
05091 p->polarity = POLARITY_IDLE;
05092
05093
05094 case SIG_EM:
05095 case SIG_EM_E1:
05096 case SIG_EMWINK:
05097 case SIG_FEATD:
05098 case SIG_FEATDMF:
05099 case SIG_FEATDMF_TA:
05100 case SIG_E911:
05101 case SIG_FGC_CAMA:
05102 case SIG_FGC_CAMAMF:
05103 case SIG_FEATB:
05104 case SIG_SF:
05105 case SIG_SFWINK:
05106 case SIG_SF_FEATD:
05107 case SIG_SF_FEATDMF:
05108 case SIG_SF_FEATB:
05109 if (ast->_state == AST_STATE_PRERING)
05110 ast_setstate(ast, AST_STATE_RING);
05111 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05112 ast_debug(1, "Ring detected\n");
05113 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05114 p->subs[index].f.subclass = AST_CONTROL_RING;
05115 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05116 ast_debug(1, "Line answered\n");
05117 if (p->confirmanswer) {
05118 p->subs[index].f.frametype = AST_FRAME_NULL;
05119 p->subs[index].f.subclass = 0;
05120 } else {
05121 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05122 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05123 ast_setstate(ast, AST_STATE_UP);
05124 }
05125 } else if (ast->_state != AST_STATE_RING)
05126 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05127 break;
05128 default:
05129 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05130 }
05131 break;
05132 case DAHDI_EVENT_RINGBEGIN:
05133 switch (p->sig) {
05134 case SIG_FXSLS:
05135 case SIG_FXSGS:
05136 case SIG_FXSKS:
05137 if (ast->_state == AST_STATE_RING) {
05138 p->ringt = p->ringt_base;
05139 }
05140 break;
05141 }
05142 break;
05143 case DAHDI_EVENT_RINGEROFF:
05144 if (p->inalarm) break;
05145 if ((p->radio || (p->oprmode < 0))) break;
05146 ast->rings++;
05147 if ((ast->rings > p->cidrings) && (p->cidspill)) {
05148 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
05149 ast_free(p->cidspill);
05150 p->cidspill = NULL;
05151 p->callwaitcas = 0;
05152 }
05153 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05154 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05155 break;
05156 case DAHDI_EVENT_RINGERON:
05157 break;
05158 case DAHDI_EVENT_NOALARM:
05159 p->inalarm = 0;
05160 #ifdef HAVE_PRI
05161
05162 if (p->bearer)
05163 p->bearer->inalarm = 0;
05164 #endif
05165 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05166 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05167 "Channel: %d\r\n", p->channel);
05168 break;
05169 case DAHDI_EVENT_WINKFLASH:
05170 if (p->inalarm) break;
05171 if (p->radio) break;
05172 if (p->oprmode < 0) break;
05173 if (p->oprmode > 1)
05174 {
05175 struct dahdi_params par;
05176
05177 memset(&par, 0, sizeof(par));
05178 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05179 {
05180 if (!par.rxisoffhook)
05181 {
05182
05183 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05184 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05185 save_conference(p);
05186 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05187 }
05188 }
05189 break;
05190 }
05191
05192 p->flashtime = ast_tvnow();
05193 switch (mysig) {
05194 case SIG_FXOLS:
05195 case SIG_FXOGS:
05196 case SIG_FXOKS:
05197 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05198 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05199 p->callwaitcas = 0;
05200
05201 if (index != SUB_REAL) {
05202 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05203 goto winkflashdone;
05204 }
05205
05206 if (p->subs[SUB_CALLWAIT].owner) {
05207
05208 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05209 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05210 p->owner = p->subs[SUB_REAL].owner;
05211 ast_debug(1, "Making %s the new owner\n", p->owner->name);
05212 if (p->owner->_state == AST_STATE_RINGING) {
05213 ast_setstate(p->owner, AST_STATE_UP);
05214 p->subs[SUB_REAL].needanswer = 1;
05215 }
05216 p->callwaitingrepeat = 0;
05217 p->cidcwexpire = 0;
05218
05219 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05220 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05221 S_OR(p->mohsuggest, NULL),
05222 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05223 }
05224 p->subs[SUB_CALLWAIT].needhold = 1;
05225 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05226 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05227 S_OR(p->mohsuggest, NULL),
05228 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05229 }
05230 p->subs[SUB_REAL].needunhold = 1;
05231 } else if (!p->subs[SUB_THREEWAY].owner) {
05232 if (!p->threewaycalling) {
05233
05234 p->subs[SUB_REAL].needflash = 1;
05235 goto winkflashdone;
05236 } else if (!check_for_conference(p)) {
05237 char cid_num[256];
05238 char cid_name[256];
05239
05240 cid_num[0] = 0;
05241 cid_name[0] = 0;
05242 if (p->dahditrcallerid && p->owner) {
05243 if (p->owner->cid.cid_num)
05244 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05245 if (p->owner->cid.cid_name)
05246 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05247 }
05248
05249
05250 if (!((ast->pbx) ||
05251 (ast->_state == AST_STATE_UP) ||
05252 (ast->_state == AST_STATE_RING))) {
05253 ast_debug(1, "Flash when call not up or ringing\n");
05254 goto winkflashdone;
05255 }
05256 if (alloc_sub(p, SUB_THREEWAY)) {
05257 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05258 goto winkflashdone;
05259 }
05260
05261 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05262 if (p->dahditrcallerid) {
05263 if (!p->origcid_num)
05264 p->origcid_num = ast_strdup(p->cid_num);
05265 if (!p->origcid_name)
05266 p->origcid_name = ast_strdup(p->cid_name);
05267 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05268 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05269 }
05270
05271 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05272
05273 dahdi_disable_ec(p);
05274 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05275 if (res)
05276 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05277 p->owner = chan;
05278 if (!chan) {
05279 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05280 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05281 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05282 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05283 dahdi_enable_ec(p);
05284 ast_hangup(chan);
05285 } else {
05286 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05287 int way3bridge = 0, cdr3way = 0;
05288
05289 if (!other) {
05290 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05291 } else
05292 way3bridge = 1;
05293
05294 if (p->subs[SUB_THREEWAY].owner->cdr)
05295 cdr3way = 1;
05296
05297 ast_verb(3, "Started three way call on channel %d\n", p->channel);
05298
05299
05300 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05301 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05302 S_OR(p->mohsuggest, NULL),
05303 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05304 }
05305 p->subs[SUB_THREEWAY].needhold = 1;
05306 }
05307 }
05308 } else {
05309
05310 if (p->subs[SUB_THREEWAY].inthreeway) {
05311
05312 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05313
05314 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05315
05316 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05317 p->owner = p->subs[SUB_REAL].owner;
05318 }
05319
05320 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05321 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05322 p->subs[SUB_REAL].inthreeway = 0;
05323 p->subs[SUB_THREEWAY].inthreeway = 0;
05324 } else {
05325
05326 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
05327 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05328 int otherindex = SUB_THREEWAY;
05329 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05330 int way3bridge = 0, cdr3way = 0;
05331
05332 if (!other) {
05333 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05334 } else
05335 way3bridge = 1;
05336
05337 if (p->subs[SUB_THREEWAY].owner->cdr)
05338 cdr3way = 1;
05339
05340 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05341
05342 p->subs[SUB_THREEWAY].inthreeway = 1;
05343 p->subs[SUB_REAL].inthreeway = 1;
05344 if (ast->_state == AST_STATE_UP) {
05345 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05346 otherindex = SUB_REAL;
05347 }
05348 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05349 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05350 p->subs[otherindex].needunhold = 1;
05351 p->owner = p->subs[SUB_REAL].owner;
05352 if (ast->_state == AST_STATE_RINGING) {
05353 ast_debug(1, "Enabling ringtone on real and threeway\n");
05354 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05355 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05356 }
05357 } else {
05358 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05359 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05360 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05361 p->owner = p->subs[SUB_REAL].owner;
05362 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05363 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05364 p->subs[SUB_REAL].needunhold = 1;
05365 dahdi_enable_ec(p);
05366 }
05367
05368 }
05369 }
05370 winkflashdone:
05371 update_conf(p);
05372 break;
05373 case SIG_EM:
05374 case SIG_EM_E1:
05375 case SIG_FEATD:
05376 case SIG_SF:
05377 case SIG_SFWINK:
05378 case SIG_SF_FEATD:
05379 case SIG_FXSLS:
05380 case SIG_FXSGS:
05381 if (option_debug) {
05382 if (p->dialing)
05383 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05384 else
05385 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05386 }
05387 break;
05388 case SIG_FEATDMF_TA:
05389 switch (p->whichwink) {
05390 case 0:
05391 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05392 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05393 break;
05394 case 1:
05395 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05396 break;
05397 case 2:
05398 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05399 return NULL;
05400 }
05401 p->whichwink++;
05402
05403 case SIG_FEATDMF:
05404 case SIG_E911:
05405 case SIG_FGC_CAMAMF:
05406 case SIG_FGC_CAMA:
05407 case SIG_FEATB:
05408 case SIG_SF_FEATDMF:
05409 case SIG_SF_FEATB:
05410 case SIG_EMWINK:
05411
05412 if (!ast_strlen_zero(p->dop.dialstr)) {
05413 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05414 if (res < 0) {
05415 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05416 p->dop.dialstr[0] = '\0';
05417 return NULL;
05418 } else
05419 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05420 }
05421 p->dop.dialstr[0] = '\0';
05422 break;
05423 default:
05424 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05425 }
05426 break;
05427 case DAHDI_EVENT_HOOKCOMPLETE:
05428 if (p->inalarm) break;
05429 if ((p->radio || (p->oprmode < 0))) break;
05430 switch (mysig) {
05431 case SIG_FXSLS:
05432 case SIG_FXSGS:
05433 case SIG_FXSKS:
05434 case SIG_EM:
05435 case SIG_EM_E1:
05436 case SIG_EMWINK:
05437 case SIG_FEATD:
05438 case SIG_SF:
05439 case SIG_SFWINK:
05440 case SIG_SF_FEATD:
05441 if (!ast_strlen_zero(p->dop.dialstr)) {
05442 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05443 if (res < 0) {
05444 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05445 p->dop.dialstr[0] = '\0';
05446 return NULL;
05447 } else
05448 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05449 }
05450 p->dop.dialstr[0] = '\0';
05451 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05452 break;
05453 case SIG_FEATDMF:
05454 case SIG_FEATDMF_TA:
05455 case SIG_E911:
05456 case SIG_FGC_CAMA:
05457 case SIG_FGC_CAMAMF:
05458 case SIG_FEATB:
05459 case SIG_SF_FEATDMF:
05460 case SIG_SF_FEATB:
05461 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05462 break;
05463 default:
05464 break;
05465 }
05466 break;
05467 case DAHDI_EVENT_POLARITY:
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477 if (p->polarityonanswerdelay > 0) {
05478
05479 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05480 switch (ast->_state) {
05481 case AST_STATE_DIALING:
05482 case AST_STATE_RINGING:
05483 if (p->answeronpolarityswitch) {
05484 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05485 ast_setstate(p->owner, AST_STATE_UP);
05486 p->polarity = POLARITY_REV;
05487 if (p->hanguponpolarityswitch) {
05488 p->polaritydelaytv = ast_tvnow();
05489 }
05490 } else {
05491 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05492 }
05493 break;
05494 case AST_STATE_UP:
05495 case AST_STATE_RING:
05496 if (p->hanguponpolarityswitch) {
05497 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05498 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05499 p->polarity = POLARITY_IDLE;
05500 } else {
05501 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05502 }
05503 break;
05504
05505 case AST_STATE_DOWN:
05506 case AST_STATE_RESERVED:
05507 case AST_STATE_OFFHOOK:
05508 case AST_STATE_BUSY:
05509 case AST_STATE_DIALING_OFFHOOK:
05510 case AST_STATE_PRERING:
05511 default:
05512 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05513 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05514 }
05515
05516 }
05517
05518 } else {
05519
05520 switch (ast->_state) {
05521 case AST_STATE_DIALING:
05522 case AST_STATE_RINGING:
05523 if (p->answeronpolarityswitch) {
05524 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05525 }
05526 break;
05527
05528 case AST_STATE_UP:
05529 case AST_STATE_RING:
05530 if (p->hanguponpolarityswitch) {
05531 ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
05532 }
05533 break;
05534
05535 default:
05536 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05537 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05538 }
05539 }
05540 }
05541 }
05542
05543 ast_debug(1, "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) );
05544 break;
05545 default:
05546 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05547 }
05548 return &p->subs[index].f;
05549 }
05550
05551 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05552 {
05553 struct dahdi_pvt *p = ast->tech_pvt;
05554 int res;
05555 int usedindex=-1;
05556 int index;
05557 struct ast_frame *f;
05558
05559
05560 index = dahdi_get_index(ast, p, 1);
05561
05562 p->subs[index].f.frametype = AST_FRAME_NULL;
05563 p->subs[index].f.datalen = 0;
05564 p->subs[index].f.samples = 0;
05565 p->subs[index].f.mallocd = 0;
05566 p->subs[index].f.offset = 0;
05567 p->subs[index].f.subclass = 0;
05568 p->subs[index].f.delivery = ast_tv(0,0);
05569 p->subs[index].f.src = "dahdi_exception";
05570 p->subs[index].f.data = NULL;
05571
05572
05573 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05574
05575
05576
05577
05578
05579 if (p->fake_event) {
05580 res = p->fake_event;
05581 p->fake_event = 0;
05582 } else
05583 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05584
05585 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05586 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05587 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05588 p->owner = p->subs[SUB_REAL].owner;
05589 if (p->owner && ast_bridged_channel(p->owner))
05590 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05591 p->subs[SUB_REAL].needunhold = 1;
05592 }
05593 switch (res) {
05594 case DAHDI_EVENT_ONHOOK:
05595 dahdi_disable_ec(p);
05596 if (p->owner) {
05597 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05598 dahdi_ring_phone(p);
05599 p->callwaitingrepeat = 0;
05600 p->cidcwexpire = 0;
05601 } else
05602 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05603 update_conf(p);
05604 break;
05605 case DAHDI_EVENT_RINGOFFHOOK:
05606 dahdi_enable_ec(p);
05607 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05608 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05609 p->subs[SUB_REAL].needanswer = 1;
05610 p->dialing = 0;
05611 }
05612 break;
05613 case DAHDI_EVENT_HOOKCOMPLETE:
05614 case DAHDI_EVENT_RINGERON:
05615 case DAHDI_EVENT_RINGEROFF:
05616
05617 break;
05618 case DAHDI_EVENT_WINKFLASH:
05619 p->flashtime = ast_tvnow();
05620 if (p->owner) {
05621 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05622 if (p->owner->_state != AST_STATE_UP) {
05623
05624 usedindex = dahdi_get_index(p->owner, p, 0);
05625 if (usedindex > -1) {
05626 p->subs[usedindex].needanswer = 1;
05627 }
05628 ast_setstate(p->owner, AST_STATE_UP);
05629 }
05630 p->callwaitingrepeat = 0;
05631 p->cidcwexpire = 0;
05632 if (ast_bridged_channel(p->owner))
05633 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05634 p->subs[SUB_REAL].needunhold = 1;
05635 } else
05636 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05637 update_conf(p);
05638 break;
05639 default:
05640 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05641 }
05642 f = &p->subs[index].f;
05643 return f;
05644 }
05645 if (!(p->radio || (p->oprmode < 0)))
05646 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05647
05648 if (ast != p->owner) {
05649 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05650 f = &p->subs[index].f;
05651 return f;
05652 }
05653 f = dahdi_handle_event(ast);
05654 return f;
05655 }
05656
05657 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05658 {
05659 struct dahdi_pvt *p = ast->tech_pvt;
05660 struct ast_frame *f;
05661 ast_mutex_lock(&p->lock);
05662 f = __dahdi_exception(ast);
05663 ast_mutex_unlock(&p->lock);
05664 return f;
05665 }
05666
05667 static struct ast_frame *dahdi_read(struct ast_channel *ast)
05668 {
05669 struct dahdi_pvt *p = ast->tech_pvt;
05670 int res;
05671 int index;
05672 void *readbuf;
05673 struct ast_frame *f;
05674
05675 while (ast_mutex_trylock(&p->lock)) {
05676 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05677 }
05678
05679 index = dahdi_get_index(ast, p, 0);
05680
05681
05682 if (index < 0) {
05683 ast_log(LOG_WARNING, "We dont exist?\n");
05684 ast_mutex_unlock(&p->lock);
05685 return NULL;
05686 }
05687
05688 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05689 ast_mutex_unlock(&p->lock);
05690 return NULL;
05691 }
05692
05693 p->subs[index].f.frametype = AST_FRAME_NULL;
05694 p->subs[index].f.datalen = 0;
05695 p->subs[index].f.samples = 0;
05696 p->subs[index].f.mallocd = 0;
05697 p->subs[index].f.offset = 0;
05698 p->subs[index].f.subclass = 0;
05699 p->subs[index].f.delivery = ast_tv(0,0);
05700 p->subs[index].f.src = "dahdi_read";
05701 p->subs[index].f.data = NULL;
05702
05703
05704 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05705 {
05706 struct dahdi_params ps;
05707
05708 memset(&ps, 0, sizeof(ps));
05709 ps.channo = p->channel;
05710 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05711 ast_mutex_unlock(&p->lock);
05712 return NULL;
05713 }
05714 p->firstradio = 1;
05715 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05716 if (ps.rxisoffhook)
05717 {
05718 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05719 }
05720 else
05721 {
05722 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05723 }
05724 ast_mutex_unlock(&p->lock);
05725 return &p->subs[index].f;
05726 }
05727 if (p->ringt == 1) {
05728 ast_mutex_unlock(&p->lock);
05729 return NULL;
05730 }
05731 else if (p->ringt > 0)
05732 p->ringt--;
05733
05734 if (p->subs[index].needringing) {
05735
05736 p->subs[index].needringing = 0;
05737 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05738 p->subs[index].f.subclass = AST_CONTROL_RINGING;
05739 ast_setstate(ast, AST_STATE_RINGING);
05740 ast_mutex_unlock(&p->lock);
05741 return &p->subs[index].f;
05742 }
05743
05744 if (p->subs[index].needbusy) {
05745
05746 p->subs[index].needbusy = 0;
05747 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05748 p->subs[index].f.subclass = AST_CONTROL_BUSY;
05749 ast_mutex_unlock(&p->lock);
05750 return &p->subs[index].f;
05751 }
05752
05753 if (p->subs[index].needcongestion) {
05754
05755 p->subs[index].needcongestion = 0;
05756 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05757 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05758 ast_mutex_unlock(&p->lock);
05759 return &p->subs[index].f;
05760 }
05761
05762 if (p->subs[index].needcallerid) {
05763 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05764 S_OR(p->lastcid_name, NULL),
05765 S_OR(p->lastcid_num, NULL)
05766 );
05767 p->subs[index].needcallerid = 0;
05768 }
05769
05770 if (p->subs[index].needanswer) {
05771
05772 p->subs[index].needanswer = 0;
05773 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05774 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05775 ast_mutex_unlock(&p->lock);
05776 return &p->subs[index].f;
05777 }
05778
05779 if (p->subs[index].needflash) {
05780
05781 p->subs[index].needflash = 0;
05782 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05783 p->subs[index].f.subclass = AST_CONTROL_FLASH;
05784 ast_mutex_unlock(&p->lock);
05785 return &p->subs[index].f;
05786 }
05787
05788 if (p->subs[index].needhold) {
05789
05790 p->subs[index].needhold = 0;
05791 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05792 p->subs[index].f.subclass = AST_CONTROL_HOLD;
05793 ast_mutex_unlock(&p->lock);
05794 ast_debug(1, "Sending hold on '%s'\n", ast->name);
05795 return &p->subs[index].f;
05796 }
05797
05798 if (p->subs[index].needunhold) {
05799
05800 p->subs[index].needunhold = 0;
05801 p->subs[index].f.frametype = AST_FRAME_CONTROL;
05802 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05803 ast_mutex_unlock(&p->lock);
05804 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05805 return &p->subs[index].f;
05806 }
05807
05808 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05809 if (!p->subs[index].linear) {
05810 p->subs[index].linear = 1;
05811 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05812 if (res)
05813 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05814 }
05815 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05816 (ast->rawreadformat == AST_FORMAT_ALAW)) {
05817 if (p->subs[index].linear) {
05818 p->subs[index].linear = 0;
05819 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05820 if (res)
05821 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05822 }
05823 } else {
05824 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05825 ast_mutex_unlock(&p->lock);
05826 return NULL;
05827 }
05828 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05829 CHECK_BLOCKING(ast);
05830 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05831 ast_clear_flag(ast, AST_FLAG_BLOCKING);
05832
05833 if (res < 0) {
05834 f = NULL;
05835 if (res == -1) {
05836 if (errno == EAGAIN) {
05837
05838 ast_mutex_unlock(&p->lock);
05839 return &p->subs[index].f;
05840 } else if (errno == ELAST) {
05841 f = __dahdi_exception(ast);
05842 } else
05843 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05844 }
05845 ast_mutex_unlock(&p->lock);
05846 return f;
05847 }
05848 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05849 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05850 f = __dahdi_exception(ast);
05851 ast_mutex_unlock(&p->lock);
05852 return f;
05853 }
05854 if (p->tdd) {
05855 int c;
05856
05857 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05858 if (c < 0) {
05859 ast_debug(1,"tdd_feed failed\n");
05860 ast_mutex_unlock(&p->lock);
05861 return NULL;
05862 }
05863 if (c) {
05864 p->subs[index].f.subclass = 0;
05865 p->subs[index].f.frametype = AST_FRAME_TEXT;
05866 p->subs[index].f.mallocd = 0;
05867 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05868 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05869 p->subs[index].f.datalen = 1;
05870 *((char *) p->subs[index].f.data) = c;
05871 ast_mutex_unlock(&p->lock);
05872 return &p->subs[index].f;
05873 }
05874 }
05875
05876 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05877 p->callwaitingrepeat--;
05878 }
05879 if (p->cidcwexpire)
05880 p->cidcwexpire--;
05881
05882 if (p->callwaitingrepeat == 1) {
05883 p->callwaitrings++;
05884 dahdi_callwait(ast);
05885 }
05886
05887 if (p->cidcwexpire == 1) {
05888 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05889 restore_conference(p);
05890 }
05891 if (p->subs[index].linear) {
05892 p->subs[index].f.datalen = READ_SIZE * 2;
05893 } else
05894 p->subs[index].f.datalen = READ_SIZE;
05895
05896
05897 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05898 send_callerid(p);
05899 }
05900
05901 p->subs[index].f.frametype = AST_FRAME_VOICE;
05902 p->subs[index].f.subclass = ast->rawreadformat;
05903 p->subs[index].f.samples = READ_SIZE;
05904 p->subs[index].f.mallocd = 0;
05905 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05906 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05907 #if 0
05908 ast_debug(1, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05909 #endif
05910 if (p->dialing ||
05911 (index && (ast->_state != AST_STATE_UP)) ||
05912 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
05913 ) {
05914
05915
05916 p->subs[index].f.frametype = AST_FRAME_NULL;
05917 p->subs[index].f.subclass = 0;
05918 p->subs[index].f.samples = 0;
05919 p->subs[index].f.mallocd = 0;
05920 p->subs[index].f.offset = 0;
05921 p->subs[index].f.data = NULL;
05922 p->subs[index].f.datalen= 0;
05923 }
05924 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
05925
05926 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05927 if (f) {
05928 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05929 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05930
05931
05932 f = NULL;
05933 }
05934 } else if (f->frametype == AST_FRAME_DTMF) {
05935 #ifdef HAVE_PRI
05936 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
05937 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05938 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05939
05940 f->frametype = AST_FRAME_NULL;
05941 f->subclass = 0;
05942 }
05943 #endif
05944
05945 p->pulsedial = 0;
05946 }
05947 }
05948 } else
05949 f = &p->subs[index].f;
05950
05951 if (f && (f->frametype == AST_FRAME_DTMF))
05952 dahdi_handle_dtmfup(ast, index, &f);
05953
05954
05955 if (p->fake_event)
05956 ast_set_flag(ast, AST_FLAG_EXCEPTION);
05957
05958 ast_mutex_unlock(&p->lock);
05959 return f;
05960 }
05961
05962 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05963 {
05964 int sent=0;
05965 int size;
05966 int res;
05967 int fd;
05968 fd = p->subs[index].dfd;
05969 while (len) {
05970 size = len;
05971 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05972 size = (linear ? READ_SIZE * 2 : READ_SIZE);
05973 res = write(fd, buf, size);
05974 if (res != size) {
05975 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05976 return sent;
05977 }
05978 len -= size;
05979 buf += size;
05980 }
05981 return sent;
05982 }
05983
05984 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05985 {
05986 struct dahdi_pvt *p = ast->tech_pvt;
05987 int res;
05988 int index;
05989 index = dahdi_get_index(ast, p, 0);
05990 if (index < 0) {
05991 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05992 return -1;
05993 }
05994
05995 #if 0
05996 #ifdef HAVE_PRI
05997 ast_mutex_lock(&p->lock);
05998 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05999 if (p->pri->pri) {
06000 if (!pri_grab(p, p->pri)) {
06001 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06002 pri_rel(p->pri);
06003 } else
06004 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06005 }
06006 p->proceeding=1;
06007 }
06008 ast_mutex_unlock(&p->lock);
06009 #endif
06010 #endif
06011
06012 if (frame->frametype != AST_FRAME_VOICE) {
06013 if (frame->frametype != AST_FRAME_IMAGE)
06014 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06015 return 0;
06016 }
06017 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
06018 (frame->subclass != AST_FORMAT_ULAW) &&
06019 (frame->subclass != AST_FORMAT_ALAW)) {
06020 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06021 return -1;
06022 }
06023 if (p->dialing) {
06024 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06025 return 0;
06026 }
06027 if (!p->owner) {
06028 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06029 return 0;
06030 }
06031 if (p->cidspill) {
06032 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06033 return 0;
06034 }
06035
06036 if (!frame->data || !frame->datalen)
06037 return 0;
06038
06039 if (frame->subclass == AST_FORMAT_SLINEAR) {
06040 if (!p->subs[index].linear) {
06041 p->subs[index].linear = 1;
06042 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06043 if (res)
06044 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06045 }
06046 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06047 } else {
06048
06049 if (p->subs[index].linear) {
06050 p->subs[index].linear = 0;
06051 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06052 if (res)
06053 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06054 }
06055 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06056 }
06057 if (res < 0) {
06058 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06059 return -1;
06060 }
06061 return 0;
06062 }
06063
06064 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06065 {
06066 struct dahdi_pvt *p = chan->tech_pvt;
06067 int res=-1;
06068 int index;
06069 int func = DAHDI_FLASH;
06070 ast_mutex_lock(&p->lock);
06071 index = dahdi_get_index(chan, p, 0);
06072 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06073 if (index == SUB_REAL) {
06074 switch (condition) {
06075 case AST_CONTROL_BUSY:
06076 #ifdef HAVE_PRI
06077 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06078 chan->hangupcause = AST_CAUSE_USER_BUSY;
06079 chan->_softhangup |= AST_SOFTHANGUP_DEV;
06080 res = 0;
06081 } else if (!p->progress &&
06082 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06083 && p->pri && !p->outgoing) {
06084 if (p->pri->pri) {
06085 if (!pri_grab(p, p->pri)) {
06086 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06087 pri_rel(p->pri);
06088 }
06089 else
06090 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06091 }
06092 p->progress = 1;
06093 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06094 } else
06095 #endif
06096 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06097 break;
06098 case AST_CONTROL_RINGING:
06099 #ifdef HAVE_PRI
06100 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06101 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06102 if (p->pri->pri) {
06103 if (!pri_grab(p, p->pri)) {
06104 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06105 pri_rel(p->pri);
06106 }
06107 else
06108 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06109 }
06110 p->alerting = 1;
06111 }
06112
06113 #endif
06114 #ifdef HAVE_SS7
06115 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06116 if (p->ss7->ss7) {
06117 ss7_grab(p, p->ss7);
06118
06119 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06120 p->rlt = 1;
06121 if (p->rlt != 1)
06122 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06123 p->alerting = 1;
06124 ss7_rel(p->ss7);
06125 }
06126 }
06127 #endif
06128
06129 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06130
06131 if (chan->_state != AST_STATE_UP) {
06132 if ((chan->_state != AST_STATE_RING) ||
06133 ((p->sig != SIG_FXSKS) &&
06134 (p->sig != SIG_FXSLS) &&
06135 (p->sig != SIG_FXSGS)))
06136 ast_setstate(chan, AST_STATE_RINGING);
06137 }
06138 break;
06139 case AST_CONTROL_PROCEEDING:
06140 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06141 #ifdef HAVE_PRI
06142 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->