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