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
00049
00050
00051
00052
00053
00054
00055
00056 #include "asterisk.h"
00057
00058 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374166 $")
00059
00060 #if defined(__NetBSD__) || defined(__FreeBSD__)
00061 #include <pthread.h>
00062 #include <signal.h>
00063 #else
00064 #include <sys/signal.h>
00065 #endif
00066 #include <sys/ioctl.h>
00067 #include <sys/stat.h>
00068 #include <math.h>
00069 #include <ctype.h>
00070
00071 #include <dahdi/user.h>
00072 #include <dahdi/tonezone.h>
00073 #include "sig_analog.h"
00074
00075
00076
00077
00078
00079
00080 #if defined(HAVE_PRI)
00081 #include "sig_pri.h"
00082 #ifndef PRI_RESTART
00083 #error "Upgrade your libpri"
00084 #endif
00085 #endif
00086
00087 #if defined(HAVE_SS7)
00088 #include "sig_ss7.h"
00089 #if defined(LIBSS7_ABI_COMPATIBILITY)
00090 #error "Your installed libss7 is not compatible"
00091 #endif
00092 #endif
00093
00094 #ifdef HAVE_OPENR2
00095
00096 #define SIG_MFCR2_MAX_CHANNELS 672
00097 #include <openr2.h>
00098 #endif
00099
00100 #include "asterisk/lock.h"
00101 #include "asterisk/channel.h"
00102 #include "asterisk/config.h"
00103 #include "asterisk/module.h"
00104 #include "asterisk/pbx.h"
00105 #include "asterisk/file.h"
00106 #include "asterisk/ulaw.h"
00107 #include "asterisk/alaw.h"
00108 #include "asterisk/callerid.h"
00109 #include "asterisk/adsi.h"
00110 #include "asterisk/cli.h"
00111 #include "asterisk/cdr.h"
00112 #include "asterisk/cel.h"
00113 #include "asterisk/features.h"
00114 #include "asterisk/musiconhold.h"
00115 #include "asterisk/say.h"
00116 #include "asterisk/tdd.h"
00117 #include "asterisk/app.h"
00118 #include "asterisk/dsp.h"
00119 #include "asterisk/astdb.h"
00120 #include "asterisk/manager.h"
00121 #include "asterisk/causes.h"
00122 #include "asterisk/term.h"
00123 #include "asterisk/utils.h"
00124 #include "asterisk/transcap.h"
00125 #include "asterisk/stringfields.h"
00126 #include "asterisk/abstract_jb.h"
00127 #include "asterisk/smdi.h"
00128 #include "asterisk/astobj.h"
00129 #include "asterisk/event.h"
00130 #include "asterisk/devicestate.h"
00131 #include "asterisk/paths.h"
00132 #include "asterisk/ccss.h"
00133 #include "asterisk/data.h"
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 #define SMDI_MD_WAIT_TIMEOUT 1500
00302
00303 static const char * const lbostr[] = {
00304 "0 db (CSU)/0-133 feet (DSX-1)",
00305 "133-266 feet (DSX-1)",
00306 "266-399 feet (DSX-1)",
00307 "399-533 feet (DSX-1)",
00308 "533-655 feet (DSX-1)",
00309 "-7.5db (CSU)",
00310 "-15db (CSU)",
00311 "-22.5db (CSU)"
00312 };
00313
00314
00315
00316 static struct ast_jb_conf default_jbconf =
00317 {
00318 .flags = 0,
00319 .max_size = 200,
00320 .resync_threshold = 1000,
00321 .impl = "fixed",
00322 .target_extra = 40,
00323 };
00324 static struct ast_jb_conf global_jbconf;
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 #define DEFAULT_CIDRINGS 1
00339
00340 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00341
00342
00343
00344 #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))
00345
00346 static const char tdesc[] = "DAHDI Telephony Driver"
00347 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00348 " w/"
00349 #if defined(HAVE_PRI)
00350 "PRI"
00351 #endif
00352 #if defined(HAVE_SS7)
00353 #if defined(HAVE_PRI)
00354 " & "
00355 #endif
00356 "SS7"
00357 #endif
00358 #if defined(HAVE_OPENR2)
00359 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00360 " & "
00361 #endif
00362 "MFC/R2"
00363 #endif
00364 #endif
00365 ;
00366
00367 static const char config[] = "chan_dahdi.conf";
00368
00369 #define SIG_EM DAHDI_SIG_EM
00370 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00371 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00372 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00373 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00374 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00375 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00376 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00377 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00378 #define SIG_FXSLS DAHDI_SIG_FXSLS
00379 #define SIG_FXSGS DAHDI_SIG_FXSGS
00380 #define SIG_FXSKS DAHDI_SIG_FXSKS
00381 #define SIG_FXOLS DAHDI_SIG_FXOLS
00382 #define SIG_FXOGS DAHDI_SIG_FXOGS
00383 #define SIG_FXOKS DAHDI_SIG_FXOKS
00384 #define SIG_PRI DAHDI_SIG_CLEAR
00385 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00386 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00387 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00388 #define SIG_MFCR2 DAHDI_SIG_CAS
00389 #define SIG_SF DAHDI_SIG_SF
00390 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00391 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00392 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00393 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00394 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00395
00396 #ifdef LOTS_OF_SPANS
00397 #define NUM_SPANS DAHDI_MAX_SPANS
00398 #else
00399 #define NUM_SPANS 32
00400 #endif
00401
00402 #define CHAN_PSEUDO -2
00403
00404 #define CALLPROGRESS_PROGRESS 1
00405 #define CALLPROGRESS_FAX_OUTGOING 2
00406 #define CALLPROGRESS_FAX_INCOMING 4
00407 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00408
00409 #define NUM_CADENCE_MAX 25
00410 static int num_cadence = 4;
00411 static int user_has_defined_cadences = 0;
00412
00413 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00414 { { 125, 125, 2000, 4000 } },
00415 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00416 { { 125, 125, 125, 125, 125, 4000 } },
00417 { { 1000, 500, 2500, 5000 } },
00418 };
00419
00420
00421
00422
00423
00424 static int cidrings[NUM_CADENCE_MAX] = {
00425 2,
00426 4,
00427 3,
00428 2,
00429 };
00430
00431
00432 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00433
00434 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00435 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00436
00437 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00438 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00439
00440 static char defaultcic[64] = "";
00441 static char defaultozz[64] = "";
00442
00443
00444 static char mwimonitornotify[PATH_MAX] = "";
00445 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00446 static int mwisend_rpas = 0;
00447 #endif
00448
00449 static char progzone[10] = "";
00450
00451 static int usedistinctiveringdetection = 0;
00452 static int distinctiveringaftercid = 0;
00453
00454 static int numbufs = 4;
00455
00456 static int mwilevel = 512;
00457 static int dtmfcid_level = 256;
00458
00459 #define REPORT_CHANNEL_ALARMS 1
00460 #define REPORT_SPAN_ALARMS 2
00461 static int report_alarms = REPORT_CHANNEL_ALARMS;
00462
00463 #ifdef HAVE_PRI
00464 static int pridebugfd = -1;
00465 static char pridebugfilename[1024] = "";
00466 #endif
00467
00468
00469 static int firstdigittimeout = 16000;
00470
00471
00472 static int gendigittimeout = 8000;
00473
00474
00475 static int matchdigittimeout = 3000;
00476
00477
00478 AST_MUTEX_DEFINE_STATIC(iflock);
00479
00480
00481 static int ifcount = 0;
00482
00483 #ifdef HAVE_PRI
00484 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00485 #endif
00486
00487
00488
00489 AST_MUTEX_DEFINE_STATIC(monlock);
00490
00491
00492
00493 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00494 static ast_cond_t ss_thread_complete;
00495 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00496 AST_MUTEX_DEFINE_STATIC(restart_lock);
00497 static int ss_thread_count = 0;
00498 static int num_restart_pending = 0;
00499
00500 static int restart_monitor(void);
00501
00502 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);
00503
00504 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00505
00506 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00507 {
00508
00509
00510
00511
00512 }
00513
00514
00515 static inline int dahdi_get_event(int fd)
00516 {
00517 int j;
00518 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00519 return -1;
00520 return j;
00521 }
00522
00523
00524 static inline int dahdi_wait_event(int fd)
00525 {
00526 int i, j = 0;
00527 i = DAHDI_IOMUX_SIGEVENT;
00528 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00529 return -1;
00530 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00531 return -1;
00532 return j;
00533 }
00534
00535
00536 #define READ_SIZE 160
00537
00538 #define MASK_AVAIL (1 << 0)
00539 #define MASK_INUSE (1 << 1)
00540
00541 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00542 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00543 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00544 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00545 #define MIN_MS_SINCE_FLASH ((2000) )
00546 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00547 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE)
00548
00549 struct dahdi_pvt;
00550
00551
00552
00553
00554
00555 static int ringt_base = DEFAULT_RINGT;
00556
00557 #if defined(HAVE_SS7)
00558
00559 struct dahdi_ss7 {
00560 struct sig_ss7_linkset ss7;
00561 };
00562
00563 static struct dahdi_ss7 linksets[NUM_SPANS];
00564
00565 static int cur_ss7type = -1;
00566 static int cur_linkset = -1;
00567 static int cur_pointcode = -1;
00568 static int cur_cicbeginswith = -1;
00569 static int cur_adjpointcode = -1;
00570 static int cur_networkindicator = -1;
00571 static int cur_defaultdpc = -1;
00572 #endif
00573
00574 #ifdef HAVE_OPENR2
00575 struct dahdi_mfcr2 {
00576 pthread_t r2master;
00577 openr2_context_t *protocol_context;
00578 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00579 int numchans;
00580 int monitored_count;
00581 };
00582
00583 struct dahdi_mfcr2_conf {
00584 openr2_variant_t variant;
00585 int mfback_timeout;
00586 int metering_pulse_timeout;
00587 int max_ani;
00588 int max_dnis;
00589 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00590 int dtmf_time_on;
00591 int dtmf_time_off;
00592 #endif
00593 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00594 int dtmf_end_timeout;
00595 #endif
00596 signed int get_ani_first:2;
00597 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00598 signed int skip_category_request:2;
00599 #endif
00600 unsigned int call_files:1;
00601 unsigned int allow_collect_calls:1;
00602 unsigned int charge_calls:1;
00603 unsigned int accept_on_offer:1;
00604 unsigned int forced_release:1;
00605 unsigned int double_answer:1;
00606 signed int immediate_accept:2;
00607 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00608 signed int dtmf_dialing:2;
00609 signed int dtmf_detection:2;
00610 #endif
00611 char logdir[OR2_MAX_PATH];
00612 char r2proto_file[OR2_MAX_PATH];
00613 openr2_log_level_t loglevel;
00614 openr2_calling_party_category_t category;
00615 };
00616
00617
00618 static struct dahdi_mfcr2 **r2links;
00619
00620 static int r2links_count = 0;
00621
00622 #endif
00623
00624 #ifdef HAVE_PRI
00625
00626 struct dahdi_pri {
00627 int dchannels[SIG_PRI_NUM_DCHANS];
00628 int mastertrunkgroup;
00629 int prilogicalspan;
00630 struct sig_pri_span pri;
00631 };
00632
00633 static struct dahdi_pri pris[NUM_SPANS];
00634
00635 #if defined(HAVE_PRI_CCSS)
00636
00637 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00638 #endif
00639
00640 #else
00641
00642 struct dahdi_pri;
00643 #endif
00644
00645 #define SUB_REAL 0
00646 #define SUB_CALLWAIT 1
00647 #define SUB_THREEWAY 2
00648
00649
00650 #define POLARITY_IDLE 0
00651 #define POLARITY_REV 1
00652
00653
00654 struct distRingData {
00655 int ring[3];
00656 int range;
00657 };
00658 struct ringContextData {
00659 char contextData[AST_MAX_CONTEXT];
00660 };
00661 struct dahdi_distRings {
00662 struct distRingData ringnum[3];
00663 struct ringContextData ringContext[3];
00664 };
00665
00666 static const char * const subnames[] = {
00667 "Real",
00668 "Callwait",
00669 "Threeway"
00670 };
00671
00672 struct dahdi_subchannel {
00673 int dfd;
00674 struct ast_channel *owner;
00675 int chan;
00676 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00677 struct ast_frame f;
00678 unsigned int needringing:1;
00679 unsigned int needbusy:1;
00680 unsigned int needcongestion:1;
00681 unsigned int needanswer:1;
00682 unsigned int needflash:1;
00683 unsigned int needhold:1;
00684 unsigned int needunhold:1;
00685 unsigned int linear:1;
00686 unsigned int inthreeway:1;
00687 struct dahdi_confinfo curconf;
00688 };
00689
00690 #define CONF_USER_REAL (1 << 0)
00691 #define CONF_USER_THIRDCALL (1 << 1)
00692
00693 #define MAX_SLAVES 4
00694
00695
00696
00697
00698 typedef enum {
00699 MWI_SEND_NULL = 0,
00700 MWI_SEND_SA,
00701 MWI_SEND_SA_WAIT,
00702 MWI_SEND_PAUSE,
00703 MWI_SEND_SPILL,
00704 MWI_SEND_CLEANUP,
00705 MWI_SEND_DONE,
00706 } mwisend_states;
00707
00708 struct mwisend_info {
00709 struct timeval pause;
00710 mwisend_states mwisend_current;
00711 };
00712
00713
00714 enum DAHDI_IFLIST {
00715 DAHDI_IFLIST_NONE,
00716 DAHDI_IFLIST_MAIN,
00717 #if defined(HAVE_PRI)
00718 DAHDI_IFLIST_NO_B_CHAN,
00719 #endif
00720 };
00721
00722 struct dahdi_pvt {
00723 ast_mutex_t lock;
00724 struct callerid_state *cs;
00725 struct ast_channel *owner;
00726
00727
00728 struct dahdi_subchannel sub_unused;
00729 struct dahdi_subchannel subs[3];
00730 struct dahdi_confinfo saveconf;
00731
00732 struct dahdi_pvt *slaves[MAX_SLAVES];
00733 struct dahdi_pvt *master;
00734 int inconference;
00735
00736 int bufsize;
00737 int buf_no;
00738 int buf_policy;
00739 int faxbuf_no;
00740 int faxbuf_policy;
00741 int sig;
00742
00743
00744
00745
00746 int radio;
00747 int outsigmod;
00748 int oprmode;
00749 struct dahdi_pvt *oprpeer;
00750
00751 float cid_rxgain;
00752
00753 float rxgain;
00754
00755 float txgain;
00756
00757 float txdrc;
00758 float rxdrc;
00759
00760 int tonezone;
00761 enum DAHDI_IFLIST which_iflist;
00762 struct dahdi_pvt *next;
00763 struct dahdi_pvt *prev;
00764
00765
00766
00767
00768
00769
00770
00771 unsigned int adsi:1;
00772
00773
00774
00775
00776
00777 unsigned int answeronpolarityswitch:1;
00778
00779
00780
00781
00782
00783 unsigned int busydetect:1;
00784
00785
00786
00787
00788
00789 unsigned int callreturn:1;
00790
00791
00792
00793
00794
00795
00796 unsigned int callwaiting:1;
00797
00798
00799
00800
00801 unsigned int callwaitingcallerid:1;
00802
00803
00804
00805
00806
00807
00808 unsigned int cancallforward:1;
00809
00810
00811
00812
00813 unsigned int canpark:1;
00814
00815 unsigned int confirmanswer:1;
00816
00817
00818
00819
00820 unsigned int destroy:1;
00821 unsigned int didtdd:1;
00822
00823 unsigned int dialednone:1;
00824
00825
00826
00827
00828 unsigned int dialing:1;
00829
00830 unsigned int digital:1;
00831
00832 unsigned int dnd:1;
00833
00834 unsigned int echobreak:1;
00835
00836
00837
00838
00839
00840 unsigned int echocanbridged:1;
00841
00842 unsigned int echocanon:1;
00843
00844 unsigned int faxhandled:1;
00845
00846 unsigned int usefaxbuffers:1;
00847
00848 unsigned int bufferoverrideinuse:1;
00849
00850 unsigned int firstradio:1;
00851
00852
00853
00854
00855 unsigned int hanguponpolarityswitch:1;
00856
00857 unsigned int hardwaredtmf:1;
00858
00859
00860
00861
00862
00863
00864 unsigned int hidecallerid:1;
00865
00866
00867
00868
00869
00870 unsigned int hidecalleridname:1;
00871
00872 unsigned int ignoredtmf:1;
00873
00874
00875
00876
00877
00878 unsigned int immediate:1;
00879
00880 unsigned int inalarm:1;
00881
00882 unsigned int mate:1;
00883
00884 unsigned int outgoing:1;
00885
00886
00887
00888
00889
00890
00891 unsigned int permcallwaiting:1;
00892
00893
00894
00895
00896 unsigned int permhidecallerid:1;
00897
00898
00899
00900
00901 unsigned int priindication_oob:1;
00902
00903
00904
00905
00906 unsigned int priexclusive:1;
00907
00908
00909
00910
00911 unsigned int pulse:1;
00912
00913 unsigned int pulsedial:1;
00914 unsigned int restartpending:1;
00915
00916
00917
00918
00919
00920 unsigned int restrictcid:1;
00921
00922
00923
00924
00925 unsigned int threewaycalling:1;
00926
00927
00928
00929
00930
00931
00932
00933
00934 unsigned int transfer:1;
00935
00936
00937
00938
00939
00940
00941
00942 unsigned int use_callerid:1;
00943
00944
00945
00946
00947
00948
00949 unsigned int use_callingpres:1;
00950
00951
00952
00953
00954
00955 unsigned int usedistinctiveringdetection:1;
00956
00957
00958
00959
00960 unsigned int dahditrcallerid:1;
00961
00962
00963
00964
00965 unsigned int transfertobusy:1;
00966
00967
00968
00969
00970 unsigned int mwimonitor_neon:1;
00971
00972
00973
00974
00975 unsigned int mwimonitor_fsk:1;
00976
00977
00978
00979
00980
00981 unsigned int mwimonitor_rpas:1;
00982
00983 unsigned int mwimonitoractive:1;
00984
00985 unsigned int mwisendactive:1;
00986
00987
00988
00989
00990 unsigned int inservice:1;
00991
00992
00993
00994
00995 unsigned int locallyblocked:1;
00996
00997
00998
00999
01000 unsigned int remotelyblocked:1;
01001
01002
01003
01004
01005 unsigned int manages_span_alarms:1;
01006
01007 #if defined(HAVE_PRI)
01008 struct sig_pri_span *pri;
01009 int logicalspan;
01010 #endif
01011
01012
01013
01014
01015 unsigned int use_smdi:1;
01016 struct mwisend_info mwisend_data;
01017
01018 struct ast_smdi_interface *smdi_iface;
01019
01020
01021 struct dahdi_distRings drings;
01022
01023
01024
01025
01026
01027 char context[AST_MAX_CONTEXT];
01028
01029
01030
01031
01032 char description[32];
01033
01034
01035
01036 char defcontext[AST_MAX_CONTEXT];
01037
01038 char exten[AST_MAX_EXTENSION];
01039
01040
01041
01042
01043 char language[MAX_LANGUAGE];
01044
01045
01046
01047
01048 char mohinterpret[MAX_MUSICCLASS];
01049
01050
01051
01052
01053 char mohsuggest[MAX_MUSICCLASS];
01054 char parkinglot[AST_MAX_EXTENSION];
01055 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01056
01057 char cid_ani[AST_MAX_EXTENSION];
01058 #endif
01059
01060 int cid_ani2;
01061
01062 char cid_num[AST_MAX_EXTENSION];
01063
01064
01065
01066
01067 char cid_tag[AST_MAX_EXTENSION];
01068
01069 int cid_ton;
01070
01071 char cid_name[AST_MAX_EXTENSION];
01072
01073 char cid_subaddr[AST_MAX_EXTENSION];
01074 char *origcid_num;
01075 char *origcid_name;
01076
01077 char callwait_num[AST_MAX_EXTENSION];
01078
01079 char callwait_name[AST_MAX_EXTENSION];
01080
01081 char rdnis[AST_MAX_EXTENSION];
01082
01083 char dnid[AST_MAX_EXTENSION];
01084
01085
01086
01087
01088 ast_group_t group;
01089
01090 int law_default;
01091
01092 int law;
01093 int confno;
01094 int confusers;
01095 int propconfno;
01096
01097
01098
01099
01100 ast_group_t callgroup;
01101
01102
01103
01104
01105 ast_group_t pickupgroup;
01106
01107
01108
01109
01110 struct ast_namedgroups *named_callgroups;
01111
01112
01113
01114
01115 struct ast_namedgroups *named_pickupgroups;
01116
01117
01118
01119
01120 struct ast_variable *vars;
01121 int channel;
01122 int span;
01123 time_t guardtime;
01124 int cid_signalling;
01125 int cid_start;
01126 int dtmfcid_holdoff_state;
01127 struct timeval dtmfcid_delay;
01128 int callingpres;
01129 int callwaitingrepeat;
01130 int cidcwexpire;
01131 int cid_suppress_expire;
01132
01133 unsigned char *cidspill;
01134
01135 int cidpos;
01136
01137 int cidlen;
01138
01139 int ringt;
01140
01141
01142
01143
01144 int ringt_base;
01145
01146
01147
01148
01149
01150
01151 int stripmsd;
01152
01153
01154
01155
01156
01157
01158 int callwaitcas;
01159
01160 int callwaitrings;
01161
01162 struct {
01163 struct dahdi_echocanparams head;
01164 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01165 } echocancel;
01166
01167
01168
01169
01170 int echotraining;
01171
01172 char echorest[20];
01173
01174
01175
01176
01177 int busycount;
01178
01179
01180
01181
01182 struct ast_dsp_busy_pattern busy_cadence;
01183
01184
01185
01186
01187 int callprogress;
01188
01189
01190
01191
01192 int waitfordialtone;
01193
01194
01195
01196
01197 int dialtone_detect;
01198 int dialtone_scanning_time_elapsed;
01199 struct timeval waitingfordt;
01200 struct timeval flashtime;
01201
01202 struct ast_dsp *dsp;
01203
01204 struct dahdi_dialoperation dop;
01205 int whichwink;
01206
01207 char finaldial[64];
01208 char accountcode[AST_MAX_ACCOUNT_CODE];
01209 int amaflags;
01210 struct tdd_state *tdd;
01211
01212 char call_forward[AST_MAX_EXTENSION];
01213
01214
01215
01216
01217 char mailbox[AST_MAX_EXTENSION];
01218
01219 struct ast_event_sub *mwi_event_sub;
01220
01221 char dialdest[256];
01222 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01223 struct dahdi_vmwi_info mwisend_setting;
01224 unsigned int mwisend_fsk: 1;
01225 unsigned int mwisend_rpas:1;
01226 #endif
01227 int distinctivering;
01228 int dtmfrelax;
01229
01230 int fake_event;
01231
01232
01233
01234
01235 int polarityonanswerdelay;
01236
01237 struct timeval polaritydelaytv;
01238
01239
01240
01241
01242 int sendcalleridafter;
01243
01244 int polarity;
01245
01246 int dsp_features;
01247 #if defined(HAVE_SS7)
01248
01249 struct sig_ss7_linkset *ss7;
01250 #endif
01251 #ifdef HAVE_OPENR2
01252 struct dahdi_mfcr2 *mfcr2;
01253 openr2_chan_t *r2chan;
01254 openr2_calling_party_category_t mfcr2_recvd_category;
01255 openr2_calling_party_category_t mfcr2_category;
01256 int mfcr2_dnis_index;
01257 int mfcr2_ani_index;
01258 int mfcr2call:1;
01259 int mfcr2_answer_pending:1;
01260 int mfcr2_charge_calls:1;
01261 int mfcr2_allow_collect_calls:1;
01262 int mfcr2_forced_release:1;
01263 int mfcr2_dnis_matched:1;
01264 int mfcr2_call_accepted:1;
01265 int mfcr2_accept_on_offer:1;
01266 int mfcr2_progress_sent:1;
01267 #endif
01268
01269 char begindigit;
01270
01271 int muting;
01272 void *sig_pvt;
01273 struct ast_cc_config_params *cc_params;
01274
01275
01276
01277
01278
01279
01280 char dialstring[AST_CHANNEL_NAME];
01281 };
01282
01283 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01284 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01285 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01286 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01287 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01288 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01289 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01306 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01307 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01308 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01309 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01310 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01311 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01312 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01313 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01314 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01315 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01316 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01317 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01318 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01319 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01320 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01321 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01322 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01323 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01324 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01325 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01326 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01327 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01328 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01329 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01330 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01331 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01332 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01333 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01334 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01335 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01336 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01337 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01338 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01339 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01340 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01341 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01342 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01343 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01344 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01345 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01346 MEMBER(dahdi_pvt, description, AST_DATA_STRING) \
01347 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01348 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01349 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01350 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01351 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01352
01353 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01354
01355 static struct dahdi_pvt *iflist = NULL;
01356 static struct dahdi_pvt *ifend = NULL;
01357
01358 #if defined(HAVE_PRI)
01359 static struct dahdi_parms_pseudo {
01360 int buf_no;
01361 int buf_policy;
01362 int faxbuf_no;
01363 int faxbuf_policy;
01364 } dahdi_pseudo_parms;
01365 #endif
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 struct dahdi_chan_conf {
01378 struct dahdi_pvt chan;
01379 #ifdef HAVE_PRI
01380 struct dahdi_pri pri;
01381 #endif
01382
01383 #if defined(HAVE_SS7)
01384 struct dahdi_ss7 ss7;
01385 #endif
01386
01387 #ifdef HAVE_OPENR2
01388 struct dahdi_mfcr2_conf mfcr2;
01389 #endif
01390 struct dahdi_params timing;
01391 int is_sig_auto;
01392
01393 int ignore_failed_channels;
01394
01395
01396
01397
01398
01399 char smdi_port[SMDI_MAX_FILENAME_LEN];
01400 };
01401
01402
01403 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01404 {
01405
01406
01407
01408 struct dahdi_chan_conf conf = {
01409 #ifdef HAVE_PRI
01410 .pri.pri = {
01411 .nsf = PRI_NSF_NONE,
01412 .switchtype = PRI_SWITCH_NI2,
01413 .dialplan = PRI_UNKNOWN + 1,
01414 .localdialplan = PRI_NATIONAL_ISDN + 1,
01415 .nodetype = PRI_CPE,
01416 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01417
01418 #if defined(HAVE_PRI_CCSS)
01419 .cc_ptmp_recall_mode = 1,
01420 .cc_qsig_signaling_link_req = 1,
01421 .cc_qsig_signaling_link_rsp = 1,
01422 #endif
01423
01424 .minunused = 2,
01425 .idleext = "",
01426 .idledial = "",
01427 .internationalprefix = "",
01428 .nationalprefix = "",
01429 .localprefix = "",
01430 .privateprefix = "",
01431 .unknownprefix = "",
01432 .colp_send = SIG_PRI_COLP_UPDATE,
01433 .resetinterval = -1,
01434 },
01435 #endif
01436 #if defined(HAVE_SS7)
01437 .ss7.ss7 = {
01438 .called_nai = SS7_NAI_NATIONAL,
01439 .calling_nai = SS7_NAI_NATIONAL,
01440 .internationalprefix = "",
01441 .nationalprefix = "",
01442 .subscriberprefix = "",
01443 .unknownprefix = ""
01444 },
01445 #endif
01446 #ifdef HAVE_OPENR2
01447 .mfcr2 = {
01448 .variant = OR2_VAR_ITU,
01449 .mfback_timeout = -1,
01450 .metering_pulse_timeout = -1,
01451 .max_ani = 10,
01452 .max_dnis = 4,
01453 .get_ani_first = -1,
01454 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01455 .skip_category_request = -1,
01456 #endif
01457 .call_files = 0,
01458 .allow_collect_calls = 0,
01459 .charge_calls = 1,
01460 .accept_on_offer = 1,
01461 .forced_release = 0,
01462 .double_answer = 0,
01463 .immediate_accept = -1,
01464 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01465 .dtmf_dialing = -1,
01466 .dtmf_detection = -1,
01467 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01468 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01469 #endif
01470 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01471 .dtmf_end_timeout = -1,
01472 #endif
01473 .logdir = "",
01474 .r2proto_file = "",
01475 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01476 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01477 },
01478 #endif
01479 .chan = {
01480 .context = "default",
01481 .cid_num = "",
01482 .cid_name = "",
01483 .cid_tag = "",
01484 .mohinterpret = "default",
01485 .mohsuggest = "",
01486 .parkinglot = "",
01487 .transfertobusy = 1,
01488
01489 .cid_signalling = CID_SIG_BELL,
01490 .cid_start = CID_START_RING,
01491 .dahditrcallerid = 0,
01492 .use_callerid = 1,
01493 .sig = -1,
01494 .outsigmod = -1,
01495
01496 .cid_rxgain = +5.0,
01497
01498 .tonezone = -1,
01499
01500 .echocancel.head.tap_length = 1,
01501
01502 .busycount = 3,
01503
01504 .accountcode = "",
01505
01506 .mailbox = "",
01507
01508 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01509 .mwisend_fsk = 1,
01510 #endif
01511 .polarityonanswerdelay = 600,
01512
01513 .sendcalleridafter = DEFAULT_CIDRINGS,
01514
01515 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01516 .buf_no = numbufs,
01517 .usefaxbuffers = 0,
01518 .cc_params = ast_cc_config_params_init(),
01519 },
01520 .timing = {
01521 .prewinktime = -1,
01522 .preflashtime = -1,
01523 .winktime = -1,
01524 .flashtime = -1,
01525 .starttime = -1,
01526 .rxwinktime = -1,
01527 .rxflashtime = -1,
01528 .debouncetime = -1
01529 },
01530 .is_sig_auto = 1,
01531 .smdi_port = "/dev/ttyS0",
01532 };
01533
01534 return conf;
01535 }
01536
01537
01538 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01539 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01540 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01541 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01542 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01543 static int dahdi_hangup(struct ast_channel *ast);
01544 static int dahdi_answer(struct ast_channel *ast);
01545 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01546 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01547 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01548 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01549 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01550 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01551 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01552 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01553 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01554 static int dahdi_devicestate(const char *data);
01555 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01556
01557 static struct ast_channel_tech dahdi_tech = {
01558 .type = "DAHDI",
01559 .description = tdesc,
01560 .requester = dahdi_request,
01561 .send_digit_begin = dahdi_digit_begin,
01562 .send_digit_end = dahdi_digit_end,
01563 .send_text = dahdi_sendtext,
01564 .call = dahdi_call,
01565 .hangup = dahdi_hangup,
01566 .answer = dahdi_answer,
01567 .read = dahdi_read,
01568 .write = dahdi_write,
01569 .bridge = dahdi_bridge,
01570 .exception = dahdi_exception,
01571 .indicate = dahdi_indicate,
01572 .fixup = dahdi_fixup,
01573 .setoption = dahdi_setoption,
01574 .queryoption = dahdi_queryoption,
01575 .func_channel_read = dahdi_func_read,
01576 .func_channel_write = dahdi_func_write,
01577 .devicestate = dahdi_devicestate,
01578 .cc_callback = dahdi_cc_callback,
01579 };
01580
01581 #define GET_CHANNEL(p) ((p)->channel)
01582
01583 #define SIG_PRI_LIB_HANDLE_CASES \
01584 SIG_PRI: \
01585 case SIG_BRI: \
01586 case SIG_BRI_PTMP
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 static inline int dahdi_sig_pri_lib_handles(int signaling)
01598 {
01599 int handles;
01600
01601 switch (signaling) {
01602 case SIG_PRI_LIB_HANDLE_CASES:
01603 handles = 1;
01604 break;
01605 default:
01606 handles = 0;
01607 break;
01608 }
01609
01610 return handles;
01611 }
01612
01613 static int analog_lib_handles(int signalling, int radio, int oprmode)
01614 {
01615 switch (signalling) {
01616 case SIG_FXOLS:
01617 case SIG_FXOGS:
01618 case SIG_FXOKS:
01619 case SIG_FXSLS:
01620 case SIG_FXSGS:
01621 case SIG_FXSKS:
01622 case SIG_EMWINK:
01623 case SIG_EM:
01624 case SIG_EM_E1:
01625 case SIG_FEATD:
01626 case SIG_FEATDMF:
01627 case SIG_E911:
01628 case SIG_FGC_CAMA:
01629 case SIG_FGC_CAMAMF:
01630 case SIG_FEATB:
01631 case SIG_SFWINK:
01632 case SIG_SF:
01633 case SIG_SF_FEATD:
01634 case SIG_SF_FEATDMF:
01635 case SIG_FEATDMF_TA:
01636 case SIG_SF_FEATB:
01637 break;
01638 default:
01639
01640 return 0;
01641 }
01642
01643 if (radio) {
01644 return 0;
01645 }
01646
01647 if (oprmode) {
01648 return 0;
01649 }
01650
01651 return 1;
01652 }
01653
01654 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01655 {
01656 switch (sig) {
01657 case SIG_FXOLS:
01658 return ANALOG_SIG_FXOLS;
01659 case SIG_FXOGS:
01660 return ANALOG_SIG_FXOGS;
01661 case SIG_FXOKS:
01662 return ANALOG_SIG_FXOKS;
01663 case SIG_FXSLS:
01664 return ANALOG_SIG_FXSLS;
01665 case SIG_FXSGS:
01666 return ANALOG_SIG_FXSGS;
01667 case SIG_FXSKS:
01668 return ANALOG_SIG_FXSKS;
01669 case SIG_EMWINK:
01670 return ANALOG_SIG_EMWINK;
01671 case SIG_EM:
01672 return ANALOG_SIG_EM;
01673 case SIG_EM_E1:
01674 return ANALOG_SIG_EM_E1;
01675 case SIG_FEATD:
01676 return ANALOG_SIG_FEATD;
01677 case SIG_FEATDMF:
01678 return ANALOG_SIG_FEATDMF;
01679 case SIG_E911:
01680 return SIG_E911;
01681 case SIG_FGC_CAMA:
01682 return ANALOG_SIG_FGC_CAMA;
01683 case SIG_FGC_CAMAMF:
01684 return ANALOG_SIG_FGC_CAMAMF;
01685 case SIG_FEATB:
01686 return ANALOG_SIG_FEATB;
01687 case SIG_SFWINK:
01688 return ANALOG_SIG_SFWINK;
01689 case SIG_SF:
01690 return ANALOG_SIG_SF;
01691 case SIG_SF_FEATD:
01692 return ANALOG_SIG_SF_FEATD;
01693 case SIG_SF_FEATDMF:
01694 return ANALOG_SIG_SF_FEATDMF;
01695 case SIG_FEATDMF_TA:
01696 return ANALOG_SIG_FEATDMF_TA;
01697 case SIG_SF_FEATB:
01698 return ANALOG_SIG_FEATB;
01699 default:
01700 return -1;
01701 }
01702 }
01703
01704
01705 static int analog_tone_to_dahditone(enum analog_tone tone)
01706 {
01707 switch (tone) {
01708 case ANALOG_TONE_RINGTONE:
01709 return DAHDI_TONE_RINGTONE;
01710 case ANALOG_TONE_STUTTER:
01711 return DAHDI_TONE_STUTTER;
01712 case ANALOG_TONE_CONGESTION:
01713 return DAHDI_TONE_CONGESTION;
01714 case ANALOG_TONE_DIALTONE:
01715 return DAHDI_TONE_DIALTONE;
01716 case ANALOG_TONE_DIALRECALL:
01717 return DAHDI_TONE_DIALRECALL;
01718 case ANALOG_TONE_INFO:
01719 return DAHDI_TONE_INFO;
01720 default:
01721 return -1;
01722 }
01723 }
01724
01725 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01726 {
01727 int index;
01728
01729 switch (analogsub) {
01730 case ANALOG_SUB_REAL:
01731 index = SUB_REAL;
01732 break;
01733 case ANALOG_SUB_CALLWAIT:
01734 index = SUB_CALLWAIT;
01735 break;
01736 case ANALOG_SUB_THREEWAY:
01737 index = SUB_THREEWAY;
01738 break;
01739 default:
01740 ast_log(LOG_ERROR, "Unidentified sub!\n");
01741 index = SUB_REAL;
01742 }
01743
01744 return index;
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
01760 {
01761 int res;
01762 int offset;
01763 const char *pos;
01764 struct dahdi_dialoperation zo = {
01765 .op = operation,
01766 };
01767
01768
01769 pos = dial_str;
01770 for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
01771 if (!*pos) {
01772 break;
01773 }
01774 if (*pos == 'W') {
01775
01776 ++pos;
01777 if (offset >= sizeof(zo.dialstr) - 3) {
01778
01779 break;
01780 }
01781 zo.dialstr[offset] = 'w';
01782 ++offset;
01783 zo.dialstr[offset] = 'w';
01784 continue;
01785 }
01786 zo.dialstr[offset] = *pos++;
01787 }
01788
01789
01790 ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
01791 pvt->channel, dial_str, zo.dialstr);
01792 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
01793 if (res) {
01794 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
01795 pvt->channel, dial_str, strerror(errno));
01796 }
01797
01798 return res;
01799 }
01800
01801 static enum analog_event dahdievent_to_analogevent(int event);
01802 static int bump_gains(struct dahdi_pvt *p);
01803 static int dahdi_setlinear(int dfd, int linear);
01804
01805 static int my_start_cid_detect(void *pvt, int cid_signalling)
01806 {
01807 struct dahdi_pvt *p = pvt;
01808 int index = SUB_REAL;
01809 p->cs = callerid_new(cid_signalling);
01810 if (!p->cs) {
01811 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01812 return -1;
01813 }
01814 bump_gains(p);
01815 dahdi_setlinear(p->subs[index].dfd, 0);
01816
01817 return 0;
01818 }
01819
01820 static int my_stop_cid_detect(void *pvt)
01821 {
01822 struct dahdi_pvt *p = pvt;
01823 int index = SUB_REAL;
01824 if (p->cs)
01825 callerid_free(p->cs);
01826 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01827 return 0;
01828 }
01829
01830 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01831 {
01832 struct dahdi_pvt *p = pvt;
01833 struct analog_pvt *analog_p = p->sig_pvt;
01834 struct pollfd poller;
01835 char *name, *num;
01836 int index = SUB_REAL;
01837 int res;
01838 unsigned char buf[256];
01839 int flags;
01840 struct ast_format tmpfmt;
01841
01842 poller.fd = p->subs[SUB_REAL].dfd;
01843 poller.events = POLLPRI | POLLIN;
01844 poller.revents = 0;
01845
01846 res = poll(&poller, 1, timeout);
01847
01848 if (poller.revents & POLLPRI) {
01849 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01850 return 1;
01851 }
01852
01853 if (poller.revents & POLLIN) {
01854
01855
01856
01857
01858
01859 res = read(p->subs[index].dfd, buf, sizeof(buf));
01860 if (res < 0) {
01861 if (errno != ELAST) {
01862 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01863 callerid_free(p->cs);
01864 return -1;
01865 }
01866 }
01867
01868 if (analog_p->ringt > 0) {
01869 if (!(--analog_p->ringt)) {
01870
01871 return -1;
01872 }
01873 }
01874
01875 if (p->cid_signalling == CID_SIG_V23_JP) {
01876 res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01877 } else {
01878 res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01879 }
01880 if (res < 0) {
01881
01882
01883
01884
01885 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01886 return -1;
01887 }
01888
01889 if (res == 1) {
01890 callerid_get(p->cs, &name, &num, &flags);
01891 if (name)
01892 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01893 if (num)
01894 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01895
01896 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01897 return 0;
01898 }
01899 }
01900
01901 *ev = ANALOG_EVENT_NONE;
01902 return 2;
01903 }
01904
01905 static const char *event2str(int event);
01906 static int restore_gains(struct dahdi_pvt *p);
01907
01908 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01909 {
01910 unsigned char buf[256];
01911 int distMatches;
01912 int curRingData[RING_PATTERNS];
01913 int receivedRingT;
01914 int counter1;
01915 int counter;
01916 int i;
01917 int res;
01918 int checkaftercid = 0;
01919
01920 struct dahdi_pvt *p = pvt;
01921 struct analog_pvt *analog_p = p->sig_pvt;
01922
01923 if (ringdata == NULL) {
01924 ringdata = curRingData;
01925 } else {
01926 checkaftercid = 1;
01927 }
01928
01929
01930
01931 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01932
01933 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01934 ringdata[receivedRingT] = 0;
01935 receivedRingT = 0;
01936 if (checkaftercid && distinctiveringaftercid)
01937 ast_verb(3, "Detecting post-CID distinctive ring\n");
01938
01939 else if (strcmp(p->context,p->defcontext) != 0) {
01940 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01941 ast_channel_context_set(chan, p->defcontext);
01942 }
01943
01944 for (;;) {
01945 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01946 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01947 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01948 ast_hangup(chan);
01949 return 1;
01950 }
01951 if (i & DAHDI_IOMUX_SIGEVENT) {
01952 res = dahdi_get_event(p->subs[idx].dfd);
01953 if (res == DAHDI_EVENT_NOALARM) {
01954 p->inalarm = 0;
01955 analog_p->inalarm = 0;
01956 }
01957 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01958 res = 0;
01959
01960
01961 ringdata[receivedRingT] = analog_p->ringt;
01962
01963 if (analog_p->ringt < analog_p->ringt_base/2)
01964 break;
01965
01966
01967 if (++receivedRingT == RING_PATTERNS)
01968 break;
01969 } else if (i & DAHDI_IOMUX_READ) {
01970 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01971 if (res < 0) {
01972 if (errno != ELAST) {
01973 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01974 ast_hangup(chan);
01975 return 1;
01976 }
01977 break;
01978 }
01979 if (analog_p->ringt > 0) {
01980 if (!(--analog_p->ringt)) {
01981 res = -1;
01982 break;
01983 }
01984 }
01985 }
01986 }
01987 }
01988 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01989
01990 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01991 for (counter = 0; counter < 3; counter++) {
01992
01993 distMatches = 0;
01994
01995 ast_verb(3, "Checking %d,%d,%d\n",
01996 p->drings.ringnum[counter].ring[0],
01997 p->drings.ringnum[counter].ring[1],
01998 p->drings.ringnum[counter].ring[2]);
01999 for (counter1 = 0; counter1 < 3; counter1++) {
02000 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
02001 if (p->drings.ringnum[counter].ring[counter1] == -1) {
02002 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
02003 ringdata[counter1]);
02004 distMatches++;
02005 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
02006 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
02007 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
02008 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
02009 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
02010 distMatches++;
02011 }
02012 }
02013
02014 if (distMatches == 3) {
02015
02016 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
02017 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
02018 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
02019 break;
02020 }
02021 }
02022 }
02023
02024 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
02025 restore_gains(p);
02026
02027 return 0;
02028 }
02029
02030 static int my_stop_callwait(void *pvt)
02031 {
02032 struct dahdi_pvt *p = pvt;
02033 p->callwaitingrepeat = 0;
02034 p->cidcwexpire = 0;
02035 p->cid_suppress_expire = 0;
02036
02037 return 0;
02038 }
02039
02040 static int send_callerid(struct dahdi_pvt *p);
02041 static int save_conference(struct dahdi_pvt *p);
02042 static int restore_conference(struct dahdi_pvt *p);
02043
02044 static int my_callwait(void *pvt)
02045 {
02046 struct dahdi_pvt *p = pvt;
02047 struct ast_format tmpfmt;
02048 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02049 if (p->cidspill) {
02050 ast_log(LOG_WARNING, "Spill already exists?!?\n");
02051 ast_free(p->cidspill);
02052 }
02053
02054
02055
02056
02057
02058 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
02059 return -1;
02060 save_conference(p);
02061
02062 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02063 if (!p->callwaitrings && p->callwaitingcallerid) {
02064 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02065 p->callwaitcas = 1;
02066 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02067 } else {
02068 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02069 p->callwaitcas = 0;
02070 p->cidlen = 2400 + READ_SIZE * 4;
02071 }
02072 p->cidpos = 0;
02073 send_callerid(p);
02074
02075 return 0;
02076 }
02077
02078 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
02079 {
02080 struct dahdi_pvt *p = pvt;
02081 struct ast_format tmpfmt;
02082
02083 ast_debug(2, "Starting cid spill\n");
02084
02085 if (p->cidspill) {
02086 ast_log(LOG_WARNING, "cidspill already exists??\n");
02087 ast_free(p->cidspill);
02088 }
02089
02090 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02091 if (cwcid == 0) {
02092 p->cidlen = ast_callerid_generate(p->cidspill,
02093 caller->id.name.str,
02094 caller->id.number.str,
02095 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02096 } else {
02097 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
02098 caller->id.name.str, caller->id.number.str);
02099 p->callwaitcas = 0;
02100 p->cidcwexpire = 0;
02101 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02102 caller->id.name.str,
02103 caller->id.number.str,
02104 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02105 p->cidlen += READ_SIZE * 4;
02106 }
02107 p->cidpos = 0;
02108 p->cid_suppress_expire = 0;
02109 send_callerid(p);
02110 }
02111 return 0;
02112 }
02113
02114 static int my_dsp_reset_and_flush_digits(void *pvt)
02115 {
02116 struct dahdi_pvt *p = pvt;
02117 if (p->dsp)
02118 ast_dsp_digitreset(p->dsp);
02119
02120 return 0;
02121 }
02122
02123 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02124 {
02125 struct dahdi_pvt *p = pvt;
02126
02127 if (p->channel == CHAN_PSEUDO)
02128 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02129
02130 if (mode == ANALOG_DIGITMODE_DTMF) {
02131
02132 if (p->hardwaredtmf) {
02133 if (p->dsp) {
02134 ast_dsp_free(p->dsp);
02135 p->dsp = NULL;
02136 }
02137 return 0;
02138 }
02139
02140 if (!p->dsp) {
02141 p->dsp = ast_dsp_new();
02142 if (!p->dsp) {
02143 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02144 return -1;
02145 }
02146 }
02147
02148 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02149 } else if (mode == ANALOG_DIGITMODE_MF) {
02150 if (!p->dsp) {
02151 p->dsp = ast_dsp_new();
02152 if (!p->dsp) {
02153 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02154 return -1;
02155 }
02156 }
02157 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02158 }
02159 return 0;
02160 }
02161
02162 static int dahdi_wink(struct dahdi_pvt *p, int index);
02163
02164 static int my_wink(void *pvt, enum analog_sub sub)
02165 {
02166 struct dahdi_pvt *p = pvt;
02167 int index = analogsub_to_dahdisub(sub);
02168 if (index != SUB_REAL) {
02169 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02170 }
02171 return dahdi_wink(p, index);
02172 }
02173
02174 static void wakeup_sub(struct dahdi_pvt *p, int a);
02175
02176 static int reset_conf(struct dahdi_pvt *p);
02177
02178 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02179
02180 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02181 {
02182 struct ast_frame *f = *dest;
02183 struct dahdi_pvt *p = pvt;
02184 int idx = analogsub_to_dahdisub(analog_index);
02185
02186 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02187 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02188 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02189
02190 if (f->subclass.integer == 'f') {
02191 if (f->frametype == AST_FRAME_DTMF_END) {
02192
02193 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02194
02195 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02196 struct dahdi_bufferinfo bi = {
02197 .txbufpolicy = p->faxbuf_policy,
02198 .bufsize = p->bufsize,
02199 .numbufs = p->faxbuf_no
02200 };
02201 int res;
02202
02203 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02204 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02205 } else {
02206 p->bufferoverrideinuse = 1;
02207 }
02208 }
02209 p->faxhandled = 1;
02210 if (p->dsp) {
02211 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02212 ast_dsp_set_features(p->dsp, p->dsp_features);
02213 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02214 }
02215 if (strcmp(ast_channel_exten(ast), "fax")) {
02216 const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
02217
02218
02219
02220
02221
02222 ast_mutex_unlock(&p->lock);
02223 ast_channel_unlock(ast);
02224 if (ast_exists_extension(ast, target_context, "fax", 1,
02225 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
02226 ast_channel_lock(ast);
02227 ast_mutex_lock(&p->lock);
02228 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02229
02230 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
02231 if (ast_async_goto(ast, target_context, "fax", 1))
02232 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02233 } else {
02234 ast_channel_lock(ast);
02235 ast_mutex_lock(&p->lock);
02236 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02237 }
02238 } else {
02239 ast_debug(1, "Already in a fax extension, not redirecting\n");
02240 }
02241 } else {
02242 ast_debug(1, "Fax already handled\n");
02243 }
02244 dahdi_confmute(p, 0);
02245 }
02246 p->subs[idx].f.frametype = AST_FRAME_NULL;
02247 p->subs[idx].f.subclass.integer = 0;
02248 *dest = &p->subs[idx].f;
02249 }
02250 }
02251
02252 static void my_lock_private(void *pvt)
02253 {
02254 struct dahdi_pvt *p = pvt;
02255 ast_mutex_lock(&p->lock);
02256 }
02257
02258 static void my_unlock_private(void *pvt)
02259 {
02260 struct dahdi_pvt *p = pvt;
02261 ast_mutex_unlock(&p->lock);
02262 }
02263
02264 static void my_deadlock_avoidance_private(void *pvt)
02265 {
02266 struct dahdi_pvt *p = pvt;
02267
02268 DEADLOCK_AVOIDANCE(&p->lock);
02269 }
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02282 {
02283 char ch_name[20];
02284
02285 if (p->channel < CHAN_PSEUDO) {
02286
02287 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02288 } else if (p->channel == CHAN_PSEUDO) {
02289
02290 strcpy(ch_name, "pseudo");
02291 } else {
02292
02293 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02294 }
02295
02296
02297
02298
02299
02300 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02301 "Channel: %s\r\n"
02302 "Uniqueid: %s\r\n"
02303 "DAHDISpan: %d\r\n"
02304 "DAHDIChannel: %s\r\n",
02305 ast_channel_name(chan),
02306 ast_channel_uniqueid(chan),
02307 p->span,
02308 ch_name);
02309 }
02310
02311 #ifdef HAVE_PRI
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02323 {
02324 struct dahdi_pvt *p = pvt;
02325
02326 dahdi_ami_channel_event(p, chan);
02327 }
02328 #endif
02329
02330
02331
02332
02333 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02334 {
02335 struct dahdi_pvt *p = pvt;
02336 int oldval;
02337 int idx = analogsub_to_dahdisub(sub);
02338
02339 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02340 oldval = p->subs[idx].linear;
02341 p->subs[idx].linear = linear_mode ? 1 : 0;
02342 return oldval;
02343 }
02344
02345 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02346 {
02347 struct dahdi_pvt *p = pvt;
02348 int idx = analogsub_to_dahdisub(sub);
02349
02350 p->subs[idx].inthreeway = inthreeway;
02351 }
02352
02353 static int get_alarms(struct dahdi_pvt *p);
02354 static void handle_alarms(struct dahdi_pvt *p, int alms);
02355 static void my_get_and_handle_alarms(void *pvt)
02356 {
02357 int res;
02358 struct dahdi_pvt *p = pvt;
02359
02360 res = get_alarms(p);
02361 handle_alarms(p, res);
02362 }
02363
02364 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02365 {
02366 struct ast_channel *bridged = ast_bridged_channel(chan);
02367
02368 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
02369 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
02370
02371 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02372 return p->sig_pvt;
02373 }
02374 }
02375 return NULL;
02376 }
02377
02378 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02379 {
02380 struct dahdi_pvt *p = pvt;
02381 int dahdi_sub = analogsub_to_dahdisub(sub);
02382 return p->subs[dahdi_sub].dfd;
02383 }
02384
02385 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02386 {
02387 struct dahdi_pvt *p = pvt;
02388
02389
02390 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02391 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02392 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02393 *cid_rings = cidrings[p->distinctivering - 1];
02394 } else {
02395 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02396 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02397 *cid_rings = p->sendcalleridafter;
02398 }
02399 }
02400
02401 static void my_set_alarm(void *pvt, int in_alarm)
02402 {
02403 struct dahdi_pvt *p = pvt;
02404
02405 p->inalarm = in_alarm;
02406 }
02407
02408 static void my_set_dialing(void *pvt, int is_dialing)
02409 {
02410 struct dahdi_pvt *p = pvt;
02411
02412 p->dialing = is_dialing;
02413 }
02414
02415 static void my_set_outgoing(void *pvt, int is_outgoing)
02416 {
02417 struct dahdi_pvt *p = pvt;
02418
02419 p->outgoing = is_outgoing;
02420 }
02421
02422 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02423 static void my_set_digital(void *pvt, int is_digital)
02424 {
02425 struct dahdi_pvt *p = pvt;
02426
02427 p->digital = is_digital;
02428 }
02429 #endif
02430
02431 #if defined(HAVE_SS7)
02432 static void my_set_inservice(void *pvt, int is_inservice)
02433 {
02434 struct dahdi_pvt *p = pvt;
02435
02436 p->inservice = is_inservice;
02437 }
02438 #endif
02439
02440 #if defined(HAVE_SS7)
02441 static void my_set_locallyblocked(void *pvt, int is_blocked)
02442 {
02443 struct dahdi_pvt *p = pvt;
02444
02445 p->locallyblocked = is_blocked;
02446 }
02447 #endif
02448
02449 #if defined(HAVE_SS7)
02450 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02451 {
02452 struct dahdi_pvt *p = pvt;
02453
02454 p->remotelyblocked = is_blocked;
02455 }
02456 #endif
02457
02458 static void my_set_ringtimeout(void *pvt, int ringt)
02459 {
02460 struct dahdi_pvt *p = pvt;
02461 p->ringt = ringt;
02462 }
02463
02464 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02465 {
02466 struct dahdi_pvt *p = pvt;
02467
02468 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02469 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02470 gettimeofday(&p->waitingfordt, NULL);
02471 ast_setstate(ast, AST_STATE_OFFHOOK);
02472 }
02473 }
02474
02475 static int my_check_waitingfordt(void *pvt)
02476 {
02477 struct dahdi_pvt *p = pvt;
02478
02479 if (p->waitingfordt.tv_usec) {
02480 return 1;
02481 }
02482
02483 return 0;
02484 }
02485
02486 static void my_set_confirmanswer(void *pvt, int flag)
02487 {
02488 struct dahdi_pvt *p = pvt;
02489 p->confirmanswer = flag;
02490 }
02491
02492 static int my_check_confirmanswer(void *pvt)
02493 {
02494 struct dahdi_pvt *p = pvt;
02495 if (p->confirmanswer) {
02496 return 1;
02497 }
02498
02499 return 0;
02500 }
02501
02502 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02503 {
02504 struct dahdi_pvt *p = pvt;
02505
02506 p->callwaiting = callwaiting_enable;
02507 }
02508
02509 static void my_cancel_cidspill(void *pvt)
02510 {
02511 struct dahdi_pvt *p = pvt;
02512
02513 ast_free(p->cidspill);
02514 p->cidspill = NULL;
02515 restore_conference(p);
02516 }
02517
02518 static int my_confmute(void *pvt, int mute)
02519 {
02520 struct dahdi_pvt *p = pvt;
02521 return dahdi_confmute(p, mute);
02522 }
02523
02524 static void my_set_pulsedial(void *pvt, int flag)
02525 {
02526 struct dahdi_pvt *p = pvt;
02527 p->pulsedial = flag;
02528 }
02529
02530 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02531 {
02532 struct dahdi_pvt *p = pvt;
02533
02534 p->owner = new_owner;
02535 }
02536
02537 static const char *my_get_orig_dialstring(void *pvt)
02538 {
02539 struct dahdi_pvt *p = pvt;
02540
02541 return p->dialstring;
02542 }
02543
02544 static void my_increase_ss_count(void)
02545 {
02546 ast_mutex_lock(&ss_thread_lock);
02547 ss_thread_count++;
02548 ast_mutex_unlock(&ss_thread_lock);
02549 }
02550
02551 static void my_decrease_ss_count(void)
02552 {
02553 ast_mutex_lock(&ss_thread_lock);
02554 ss_thread_count--;
02555 ast_cond_signal(&ss_thread_complete);
02556 ast_mutex_unlock(&ss_thread_lock);
02557 }
02558
02559 static void my_all_subchannels_hungup(void *pvt)
02560 {
02561 struct dahdi_pvt *p = pvt;
02562 int res, law;
02563
02564 p->faxhandled = 0;
02565 p->didtdd = 0;
02566
02567 if (p->dsp) {
02568 ast_dsp_free(p->dsp);
02569 p->dsp = NULL;
02570 }
02571
02572 p->law = p->law_default;
02573 law = p->law_default;
02574 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02575 if (res < 0)
02576 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02577
02578 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02579
02580 #if 1
02581 {
02582 int i;
02583 p->owner = NULL;
02584
02585 for (i = 0; i < 3; i++) {
02586 p->subs[i].owner = NULL;
02587 }
02588 }
02589 #endif
02590
02591 reset_conf(p);
02592 if (num_restart_pending == 0) {
02593 restart_monitor();
02594 }
02595 }
02596
02597 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02598
02599 static int my_conf_del(void *pvt, enum analog_sub sub)
02600 {
02601 struct dahdi_pvt *p = pvt;
02602 int x = analogsub_to_dahdisub(sub);
02603
02604 return conf_del(p, &p->subs[x], x);
02605 }
02606
02607 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02608
02609 static int my_conf_add(void *pvt, enum analog_sub sub)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 int x = analogsub_to_dahdisub(sub);
02613
02614 return conf_add(p, &p->subs[x], x, 0);
02615 }
02616
02617 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02618
02619 static int my_complete_conference_update(void *pvt, int needconference)
02620 {
02621 struct dahdi_pvt *p = pvt;
02622 int needconf = needconference;
02623 int x;
02624 int useslavenative;
02625 struct dahdi_pvt *slave = NULL;
02626
02627 useslavenative = isslavenative(p, &slave);
02628
02629
02630
02631 for (x = 0; x < MAX_SLAVES; x++) {
02632 if (p->slaves[x]) {
02633 if (useslavenative)
02634 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02635 else {
02636 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02637 needconf++;
02638 }
02639 }
02640 }
02641
02642 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02643 if (useslavenative)
02644 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02645 else {
02646 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02647 needconf++;
02648 }
02649 }
02650
02651 if (p->master) {
02652 if (isslavenative(p->master, NULL)) {
02653 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02654 } else {
02655 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02656 }
02657 }
02658 if (!needconf) {
02659
02660
02661 p->confno = -1;
02662 }
02663
02664 return 0;
02665 }
02666
02667 static int check_for_conference(struct dahdi_pvt *p);
02668
02669 static int my_check_for_conference(void *pvt)
02670 {
02671 struct dahdi_pvt *p = pvt;
02672 return check_for_conference(p);
02673 }
02674
02675 static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
02676 {
02677 struct dahdi_pvt *p = pvt;
02678 int da, db;
02679 int tchan;
02680 int tinthreeway;
02681
02682 da = analogsub_to_dahdisub(a);
02683 db = analogsub_to_dahdisub(b);
02684
02685 tchan = p->subs[da].chan;
02686 p->subs[da].chan = p->subs[db].chan;
02687 p->subs[db].chan = tchan;
02688
02689 tinthreeway = p->subs[da].inthreeway;
02690 p->subs[da].inthreeway = p->subs[db].inthreeway;
02691 p->subs[db].inthreeway = tinthreeway;
02692
02693 p->subs[da].owner = ast_a;
02694 p->subs[db].owner = ast_b;
02695
02696 if (ast_a)
02697 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02698 if (ast_b)
02699 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02700
02701 wakeup_sub(p, a);
02702 wakeup_sub(p, b);
02703
02704 return;
02705 }
02706
02707
02708
02709
02710
02711
02712
02713
02714 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linked, struct ast_callid *callid, int callid_created);
02715
02716 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid);
02717
02718 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02719 {
02720 struct ast_callid *callid = NULL;
02721 int callid_created = ast_callid_threadstorage_auto(&callid);
02722 struct dahdi_pvt *p = pvt;
02723 int dsub = analogsub_to_dahdisub(sub);
02724
02725 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02726 }
02727
02728 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02729 static int dahdi_setlaw(int dfd, int law)
02730 {
02731 int res;
02732 res = ioctl(dfd, DAHDI_SETLAW, &law);
02733 if (res)
02734 return res;
02735 return 0;
02736 }
02737 #endif
02738
02739 #if defined(HAVE_PRI)
02740 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
02741 {
02742 struct dahdi_pvt *p = pvt;
02743 int audio;
02744 int newlaw = -1;
02745 struct ast_callid *callid = NULL;
02746 int callid_created = ast_callid_threadstorage_auto(&callid);
02747
02748 switch (p->sig) {
02749 case SIG_PRI_LIB_HANDLE_CASES:
02750 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02751
02752 break;
02753 }
02754
02755 default:
02756
02757 audio = 1;
02758 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02759 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02760 p->channel, audio, strerror(errno));
02761 }
02762 break;
02763 }
02764
02765 if (law != SIG_PRI_DEFLAW) {
02766 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02767 }
02768
02769 ast_copy_string(p->exten, exten, sizeof(p->exten));
02770
02771 switch (law) {
02772 case SIG_PRI_DEFLAW:
02773 newlaw = 0;
02774 break;
02775 case SIG_PRI_ALAW:
02776 newlaw = DAHDI_LAW_ALAW;
02777 break;
02778 case SIG_PRI_ULAW:
02779 newlaw = DAHDI_LAW_MULAW;
02780 break;
02781 }
02782
02783 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02784 }
02785 #endif
02786
02787 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02788
02789 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799 static void my_pri_ss7_open_media(void *p)
02800 {
02801 struct dahdi_pvt *pvt = p;
02802 int res;
02803 int dfd;
02804 int set_val;
02805
02806 dfd = pvt->subs[SUB_REAL].dfd;
02807
02808
02809 set_val = 1;
02810 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02811 if (res < 0) {
02812 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02813 pvt->channel, strerror(errno));
02814 }
02815
02816
02817 res = dahdi_setlaw(dfd, pvt->law);
02818 if (res < 0) {
02819 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02820 }
02821
02822
02823 if (pvt->digital) {
02824 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02825 } else {
02826 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02827 pvt->law);
02828 }
02829 if (res < 0) {
02830 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02831 }
02832
02833 if (pvt->dsp_features && pvt->dsp) {
02834 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02835 pvt->dsp_features = 0;
02836 }
02837 }
02838 #endif
02839
02840 #if defined(HAVE_PRI)
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853 static void my_pri_dial_digits(void *p, const char *dial_string)
02854 {
02855 char dial_str[DAHDI_MAX_DTMF_BUF];
02856 struct dahdi_pvt *pvt = p;
02857 int res;
02858
02859 snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
02860 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
02861 if (!res) {
02862 pvt->dialing = 1;
02863 }
02864 }
02865 #endif
02866
02867 static int unalloc_sub(struct dahdi_pvt *p, int x);
02868
02869 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02870 {
02871 struct dahdi_pvt *p = pvt;
02872
02873 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02874 }
02875
02876 static int alloc_sub(struct dahdi_pvt *p, int x);
02877
02878 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02879 {
02880 struct dahdi_pvt *p = pvt;
02881
02882 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02883 }
02884
02885 static int has_voicemail(struct dahdi_pvt *p);
02886
02887 static int my_has_voicemail(void *pvt)
02888 {
02889 struct dahdi_pvt *p = pvt;
02890
02891 return has_voicemail(p);
02892 }
02893
02894 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02895 {
02896 struct dahdi_pvt *p = pvt;
02897 int index;
02898
02899 index = analogsub_to_dahdisub(sub);
02900
02901 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02902 }
02903
02904 static enum analog_event dahdievent_to_analogevent(int event)
02905 {
02906 enum analog_event res;
02907
02908 switch (event) {
02909 case DAHDI_EVENT_ONHOOK:
02910 res = ANALOG_EVENT_ONHOOK;
02911 break;
02912 case DAHDI_EVENT_RINGOFFHOOK:
02913 res = ANALOG_EVENT_RINGOFFHOOK;
02914 break;
02915 case DAHDI_EVENT_WINKFLASH:
02916 res = ANALOG_EVENT_WINKFLASH;
02917 break;
02918 case DAHDI_EVENT_ALARM:
02919 res = ANALOG_EVENT_ALARM;
02920 break;
02921 case DAHDI_EVENT_NOALARM:
02922 res = ANALOG_EVENT_NOALARM;
02923 break;
02924 case DAHDI_EVENT_DIALCOMPLETE:
02925 res = ANALOG_EVENT_DIALCOMPLETE;
02926 break;
02927 case DAHDI_EVENT_RINGERON:
02928 res = ANALOG_EVENT_RINGERON;
02929 break;
02930 case DAHDI_EVENT_RINGEROFF:
02931 res = ANALOG_EVENT_RINGEROFF;
02932 break;
02933 case DAHDI_EVENT_HOOKCOMPLETE:
02934 res = ANALOG_EVENT_HOOKCOMPLETE;
02935 break;
02936 case DAHDI_EVENT_PULSE_START:
02937 res = ANALOG_EVENT_PULSE_START;
02938 break;
02939 case DAHDI_EVENT_POLARITY:
02940 res = ANALOG_EVENT_POLARITY;
02941 break;
02942 case DAHDI_EVENT_RINGBEGIN:
02943 res = ANALOG_EVENT_RINGBEGIN;
02944 break;
02945 case DAHDI_EVENT_EC_DISABLED:
02946 res = ANALOG_EVENT_EC_DISABLED;
02947 break;
02948 case DAHDI_EVENT_REMOVED:
02949 res = ANALOG_EVENT_REMOVED;
02950 break;
02951 case DAHDI_EVENT_NEONMWI_ACTIVE:
02952 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02953 break;
02954 case DAHDI_EVENT_NEONMWI_INACTIVE:
02955 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02956 break;
02957 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02958 case DAHDI_EVENT_TX_CED_DETECTED:
02959 res = ANALOG_EVENT_TX_CED_DETECTED;
02960 break;
02961 case DAHDI_EVENT_RX_CED_DETECTED:
02962 res = ANALOG_EVENT_RX_CED_DETECTED;
02963 break;
02964 case DAHDI_EVENT_EC_NLP_DISABLED:
02965 res = ANALOG_EVENT_EC_NLP_DISABLED;
02966 break;
02967 case DAHDI_EVENT_EC_NLP_ENABLED:
02968 res = ANALOG_EVENT_EC_NLP_ENABLED;
02969 break;
02970 #endif
02971 case DAHDI_EVENT_PULSEDIGIT:
02972 res = ANALOG_EVENT_PULSEDIGIT;
02973 break;
02974 case DAHDI_EVENT_DTMFDOWN:
02975 res = ANALOG_EVENT_DTMFDOWN;
02976 break;
02977 case DAHDI_EVENT_DTMFUP:
02978 res = ANALOG_EVENT_DTMFUP;
02979 break;
02980 default:
02981 switch(event & 0xFFFF0000) {
02982 case DAHDI_EVENT_PULSEDIGIT:
02983 case DAHDI_EVENT_DTMFDOWN:
02984 case DAHDI_EVENT_DTMFUP:
02985
02986
02987
02988
02989 return event;
02990 }
02991
02992 res = ANALOG_EVENT_ERROR;
02993 break;
02994 }
02995
02996 return res;
02997 }
02998
02999 static inline int dahdi_wait_event(int fd);
03000
03001 static int my_wait_event(void *pvt)
03002 {
03003 struct dahdi_pvt *p = pvt;
03004
03005 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
03006 }
03007
03008 static int my_get_event(void *pvt)
03009 {
03010 struct dahdi_pvt *p = pvt;
03011 int res;
03012
03013 if (p->fake_event) {
03014 res = p->fake_event;
03015 p->fake_event = 0;
03016 } else
03017 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
03018
03019 return dahdievent_to_analogevent(res);
03020 }
03021
03022 static int my_is_off_hook(void *pvt)
03023 {
03024 struct dahdi_pvt *p = pvt;
03025 int res;
03026 struct dahdi_params par;
03027
03028 memset(&par, 0, sizeof(par));
03029
03030 if (p->subs[SUB_REAL].dfd > -1)
03031 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03032 else {
03033
03034 res = 0;
03035 par.rxisoffhook = 0;
03036 }
03037 if (res) {
03038 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
03039 }
03040
03041 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
03042
03043
03044
03045 return (par.rxbits > -1) || par.rxisoffhook;
03046 }
03047
03048 return par.rxisoffhook;
03049 }
03050
03051 static void dahdi_enable_ec(struct dahdi_pvt *p);
03052 static void dahdi_disable_ec(struct dahdi_pvt *p);
03053
03054 static int my_set_echocanceller(void *pvt, int enable)
03055 {
03056 struct dahdi_pvt *p = pvt;
03057
03058 if (enable)
03059 dahdi_enable_ec(p);
03060 else
03061 dahdi_disable_ec(p);
03062
03063 return 0;
03064 }
03065
03066 static int dahdi_ring_phone(struct dahdi_pvt *p);
03067
03068 static int my_ring(void *pvt)
03069 {
03070 struct dahdi_pvt *p = pvt;
03071
03072 return dahdi_ring_phone(p);
03073 }
03074
03075 static int my_flash(void *pvt)
03076 {
03077 struct dahdi_pvt *p = pvt;
03078 int func = DAHDI_FLASH;
03079 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
03080 }
03081
03082 static inline int dahdi_set_hook(int fd, int hs);
03083
03084 static int my_off_hook(void *pvt)
03085 {
03086 struct dahdi_pvt *p = pvt;
03087 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03088 }
03089
03090 static void my_set_needringing(void *pvt, int value)
03091 {
03092 struct dahdi_pvt *p = pvt;
03093 p->subs[SUB_REAL].needringing = value;
03094 }
03095
03096 static void my_set_polarity(void *pvt, int value)
03097 {
03098 struct dahdi_pvt *p = pvt;
03099
03100 if (p->channel == CHAN_PSEUDO) {
03101 return;
03102 }
03103 p->polarity = value;
03104 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
03105 }
03106
03107 static void my_start_polarityswitch(void *pvt)
03108 {
03109 struct dahdi_pvt *p = pvt;
03110
03111 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03112 my_set_polarity(pvt, 0);
03113 }
03114 }
03115
03116 static void my_answer_polarityswitch(void *pvt)
03117 {
03118 struct dahdi_pvt *p = pvt;
03119
03120 if (!p->answeronpolarityswitch) {
03121 return;
03122 }
03123
03124 my_set_polarity(pvt, 1);
03125 }
03126
03127 static void my_hangup_polarityswitch(void *pvt)
03128 {
03129 struct dahdi_pvt *p = pvt;
03130
03131 if (!p->hanguponpolarityswitch) {
03132 return;
03133 }
03134
03135 if (p->answeronpolarityswitch) {
03136 my_set_polarity(pvt, 0);
03137 } else {
03138 my_set_polarity(pvt, 1);
03139 }
03140 }
03141
03142 static int my_start(void *pvt)
03143 {
03144 struct dahdi_pvt *p = pvt;
03145 int x = DAHDI_START;
03146
03147 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03148 }
03149
03150 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03151 {
03152 struct dahdi_pvt *p = pvt;
03153
03154 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03155 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03156 return -1;
03157 }
03158
03159 if (sub != ANALOG_SUB_REAL) {
03160 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03161 dop->dialstr, p->channel, sub);
03162 return -1;
03163 }
03164
03165 return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
03166 }
03167
03168 static void dahdi_train_ec(struct dahdi_pvt *p);
03169
03170 static int my_train_echocanceller(void *pvt)
03171 {
03172 struct dahdi_pvt *p = pvt;
03173
03174 dahdi_train_ec(p);
03175
03176 return 0;
03177 }
03178
03179 static int my_is_dialing(void *pvt, enum analog_sub sub)
03180 {
03181 struct dahdi_pvt *p = pvt;
03182 int index;
03183 int x;
03184
03185 index = analogsub_to_dahdisub(sub);
03186
03187 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03188 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03189 return -1;
03190 }
03191
03192 return x;
03193 }
03194
03195 static int my_on_hook(void *pvt)
03196 {
03197 struct dahdi_pvt *p = pvt;
03198 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03199 }
03200
03201 #if defined(HAVE_PRI)
03202 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03203 {
03204 struct dahdi_pvt *old_chan = chan_old;
03205 struct dahdi_pvt *new_chan = chan_new;
03206
03207 new_chan->owner = old_chan->owner;
03208 old_chan->owner = NULL;
03209 if (new_chan->owner) {
03210 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
03211 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
03212 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03213 old_chan->subs[SUB_REAL].owner = NULL;
03214 }
03215
03216 new_chan->dsp = old_chan->dsp;
03217 new_chan->dsp_features = old_chan->dsp_features;
03218 old_chan->dsp = NULL;
03219 old_chan->dsp_features = 0;
03220
03221
03222 new_chan->dialing = old_chan->dialing;
03223 new_chan->digital = old_chan->digital;
03224 new_chan->outgoing = old_chan->outgoing;
03225 old_chan->dialing = 0;
03226 old_chan->digital = 0;
03227 old_chan->outgoing = 0;
03228
03229
03230 new_chan->law = old_chan->law;
03231 strcpy(new_chan->dialstring, old_chan->dialstring);
03232 }
03233 #endif
03234
03235 #if defined(HAVE_PRI)
03236 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03237 {
03238 switch (tone) {
03239 case SIG_PRI_TONE_RINGTONE:
03240 return DAHDI_TONE_RINGTONE;
03241 case SIG_PRI_TONE_STUTTER:
03242 return DAHDI_TONE_STUTTER;
03243 case SIG_PRI_TONE_CONGESTION:
03244 return DAHDI_TONE_CONGESTION;
03245 case SIG_PRI_TONE_DIALTONE:
03246 return DAHDI_TONE_DIALTONE;
03247 case SIG_PRI_TONE_DIALRECALL:
03248 return DAHDI_TONE_DIALRECALL;
03249 case SIG_PRI_TONE_INFO:
03250 return DAHDI_TONE_INFO;
03251 case SIG_PRI_TONE_BUSY:
03252 return DAHDI_TONE_BUSY;
03253 default:
03254 return -1;
03255 }
03256 }
03257 #endif
03258
03259 #if defined(HAVE_PRI)
03260 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03261 {
03262 int x;
03263
03264 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03265 switch (x) {
03266 case DAHDI_EVENT_NONE:
03267 break;
03268 case DAHDI_EVENT_ALARM:
03269 case DAHDI_EVENT_NOALARM:
03270 if (sig_pri_is_alarm_ignored(pri)) {
03271 break;
03272 }
03273
03274 default:
03275 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03276 event2str(x), x, pri->span);
03277 break;
03278 }
03279
03280 switch (x) {
03281 case DAHDI_EVENT_ALARM:
03282 pri_event_alarm(pri, index, 0);
03283 break;
03284 case DAHDI_EVENT_NOALARM:
03285 pri_event_noalarm(pri, index, 0);
03286 break;
03287 default:
03288 break;
03289 }
03290 }
03291 #endif
03292
03293 #if defined(HAVE_PRI)
03294 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03295 {
03296 struct dahdi_pvt *p = pvt;
03297
03298 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03299 }
03300 #endif
03301
03302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03314 {
03315 struct dahdi_pvt *p = pvt;
03316
03317 ast_copy_string(p->cid_num,
03318 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03319 sizeof(p->cid_num));
03320 ast_copy_string(p->cid_name,
03321 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03322 sizeof(p->cid_name));
03323 ast_copy_string(p->cid_subaddr,
03324 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03325 sizeof(p->cid_subaddr));
03326 p->cid_ton = caller->id.number.plan;
03327 p->callingpres = ast_party_id_presentation(&caller->id);
03328 if (caller->id.tag) {
03329 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03330 }
03331 ast_copy_string(p->cid_ani,
03332 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03333 sizeof(p->cid_ani));
03334 p->cid_ani2 = caller->ani2;
03335 }
03336 #endif
03337
03338 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349 static void my_set_dnid(void *pvt, const char *dnid)
03350 {
03351 struct dahdi_pvt *p = pvt;
03352
03353 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03354 }
03355 #endif
03356
03357 #if defined(HAVE_PRI)
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368 static void my_set_rdnis(void *pvt, const char *rdnis)
03369 {
03370 struct dahdi_pvt *p = pvt;
03371
03372 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03373 }
03374 #endif
03375
03376 #if defined(HAVE_PRI)
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03402 {
03403 char *dial;
03404 struct dahdi_pvt *pvt;
03405 AST_DECLARE_APP_ARGS(args,
03406 AST_APP_ARG(tech);
03407 AST_APP_ARG(group);
03408
03409
03410
03411 );
03412
03413 pvt = priv;
03414 dial = ast_strdupa(pvt->dialstring);
03415 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03416 if (!args.tech) {
03417 ast_copy_string(buf, pvt->dialstring, buf_size);
03418 return;
03419 }
03420 if (!args.group) {
03421
03422 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03423 return;
03424 }
03425 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03426
03427
03428 ast_copy_string(buf, pvt->dialstring, buf_size);
03429 return;
03430 }
03431
03432 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03433 }
03434 #endif
03435
03436 #if defined(HAVE_PRI)
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03449 {
03450 unsigned idx;
03451 unsigned num_b_chans;
03452 unsigned in_use;
03453 unsigned in_alarm;
03454 enum ast_device_state new_state;
03455
03456
03457 num_b_chans = 0;
03458 in_use = 0;
03459 in_alarm = 1;
03460 for (idx = pri->numchans; idx--;) {
03461 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03462
03463 ++num_b_chans;
03464 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03465 ++in_use;
03466 }
03467 if (!pri->pvts[idx]->inalarm) {
03468
03469 in_alarm = 0;
03470 }
03471 }
03472 }
03473
03474
03475 if (in_alarm) {
03476 new_state = AST_DEVICE_UNAVAILABLE;
03477 } else {
03478 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03479 }
03480 if (pri->congestion_devstate != new_state) {
03481 pri->congestion_devstate = new_state;
03482 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03483 }
03484 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03485
03486 if (in_alarm) {
03487 new_state = AST_DEVICE_UNAVAILABLE;
03488 } else if (!in_use) {
03489 new_state = AST_DEVICE_NOT_INUSE;
03490 } else if (!pri->user_busy_threshold) {
03491 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03492 } else {
03493 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03494 : AST_DEVICE_BUSY;
03495 }
03496 if (pri->threshold_devstate != new_state) {
03497 pri->threshold_devstate = new_state;
03498 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03499 }
03500 #endif
03501 }
03502 #endif
03503
03504 #if defined(HAVE_PRI)
03505
03506
03507
03508
03509
03510
03511
03512 static void my_module_ref(void)
03513 {
03514 ast_module_ref(ast_module_info->self);
03515 }
03516 #endif
03517
03518 #if defined(HAVE_PRI)
03519
03520
03521
03522
03523
03524
03525
03526 static void my_module_unref(void)
03527 {
03528 ast_module_unref(ast_module_info->self);
03529 }
03530 #endif
03531
03532 #if defined(HAVE_PRI)
03533 #if defined(HAVE_PRI_CALL_WAITING)
03534 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03535 #endif
03536 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03537
03538 struct sig_pri_callback sig_pri_callbacks =
03539 {
03540 .handle_dchan_exception = my_handle_dchan_exception,
03541 .play_tone = my_pri_play_tone,
03542 .set_echocanceller = my_set_echocanceller,
03543 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03544 .lock_private = my_lock_private,
03545 .unlock_private = my_unlock_private,
03546 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03547 .new_ast_channel = my_new_pri_ast_channel,
03548 .fixup_chans = my_pri_fixup_chans,
03549 .set_alarm = my_set_alarm,
03550 .set_dialing = my_set_dialing,
03551 .set_outgoing = my_set_outgoing,
03552 .set_digital = my_set_digital,
03553 .set_callerid = my_set_callerid,
03554 .set_dnid = my_set_dnid,
03555 .set_rdnis = my_set_rdnis,
03556 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03557 #if defined(HAVE_PRI_CALL_WAITING)
03558 .init_config = my_pri_init_config,
03559 #endif
03560 .get_orig_dialstring = my_get_orig_dialstring,
03561 .make_cc_dialstring = my_pri_make_cc_dialstring,
03562 .update_span_devstate = dahdi_pri_update_span_devstate,
03563 .module_ref = my_module_ref,
03564 .module_unref = my_module_unref,
03565 .dial_digits = my_pri_dial_digits,
03566 .open_media = my_pri_ss7_open_media,
03567 .ami_channel_event = my_ami_channel_event,
03568 };
03569 #endif
03570
03571 #if defined(HAVE_SS7)
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03583 {
03584 int event;
03585
03586 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03587 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03588 linkset->span, which);
03589 return;
03590 }
03591 switch (event) {
03592 case DAHDI_EVENT_NONE:
03593 break;
03594 case DAHDI_EVENT_ALARM:
03595 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03596 event2str(event), event, linkset->span, which);
03597 sig_ss7_link_alarm(linkset, which);
03598 break;
03599 case DAHDI_EVENT_NOALARM:
03600 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03601 event2str(event), event, linkset->span, which);
03602 sig_ss7_link_noalarm(linkset, which);
03603 break;
03604 default:
03605 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03606 event2str(event), event, linkset->span, which);
03607 break;
03608 }
03609 }
03610 #endif
03611
03612 #if defined(HAVE_SS7)
03613 static void my_ss7_set_loopback(void *pvt, int enable)
03614 {
03615 struct dahdi_pvt *p = pvt;
03616
03617 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03618 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03619 strerror(errno));
03620 }
03621 }
03622 #endif
03623
03624 #if defined(HAVE_SS7)
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
03640 {
03641 struct dahdi_pvt *p = pvt;
03642 int audio;
03643 int newlaw;
03644 struct ast_callid *callid = NULL;
03645 int callid_created = ast_callid_threadstorage_auto(&callid);
03646
03647
03648 audio = 1;
03649 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03650 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03651 p->channel, audio, strerror(errno));
03652
03653 if (law != SIG_SS7_DEFLAW) {
03654 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03655 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03656 }
03657
03658 ast_copy_string(p->exten, exten, sizeof(p->exten));
03659
03660 newlaw = -1;
03661 switch (law) {
03662 case SIG_SS7_DEFLAW:
03663 newlaw = 0;
03664 break;
03665 case SIG_SS7_ALAW:
03666 newlaw = DAHDI_LAW_ALAW;
03667 break;
03668 case SIG_SS7_ULAW:
03669 newlaw = DAHDI_LAW_MULAW;
03670 break;
03671 }
03672 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
03673 }
03674 #endif
03675
03676 #if defined(HAVE_SS7)
03677 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03678 {
03679 switch (tone) {
03680 case SIG_SS7_TONE_RINGTONE:
03681 return DAHDI_TONE_RINGTONE;
03682 case SIG_SS7_TONE_STUTTER:
03683 return DAHDI_TONE_STUTTER;
03684 case SIG_SS7_TONE_CONGESTION:
03685 return DAHDI_TONE_CONGESTION;
03686 case SIG_SS7_TONE_DIALTONE:
03687 return DAHDI_TONE_DIALTONE;
03688 case SIG_SS7_TONE_DIALRECALL:
03689 return DAHDI_TONE_DIALRECALL;
03690 case SIG_SS7_TONE_INFO:
03691 return DAHDI_TONE_INFO;
03692 case SIG_SS7_TONE_BUSY:
03693 return DAHDI_TONE_BUSY;
03694 default:
03695 return -1;
03696 }
03697 }
03698 #endif
03699
03700 #if defined(HAVE_SS7)
03701 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03702 {
03703 struct dahdi_pvt *p = pvt;
03704
03705 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03706 }
03707 #endif
03708
03709 #if defined(HAVE_SS7)
03710 struct sig_ss7_callback sig_ss7_callbacks =
03711 {
03712 .lock_private = my_lock_private,
03713 .unlock_private = my_unlock_private,
03714 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03715
03716 .set_echocanceller = my_set_echocanceller,
03717 .set_loopback = my_ss7_set_loopback,
03718
03719 .new_ast_channel = my_new_ss7_ast_channel,
03720 .play_tone = my_ss7_play_tone,
03721
03722 .handle_link_exception = my_handle_link_exception,
03723 .set_alarm = my_set_alarm,
03724 .set_dialing = my_set_dialing,
03725 .set_outgoing = my_set_outgoing,
03726 .set_digital = my_set_digital,
03727 .set_inservice = my_set_inservice,
03728 .set_locallyblocked = my_set_locallyblocked,
03729 .set_remotelyblocked = my_set_remotelyblocked,
03730 .set_callerid = my_set_callerid,
03731 .set_dnid = my_set_dnid,
03732 .open_media = my_pri_ss7_open_media,
03733 };
03734 #endif
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754 static void notify_message(char *mailbox_full, int thereornot)
03755 {
03756 char s[sizeof(mwimonitornotify) + 80];
03757 struct ast_event *event;
03758 char *mailbox, *context;
03759
03760
03761 context = mailbox = ast_strdupa(mailbox_full);
03762 strsep(&context, "@");
03763 if (ast_strlen_zero(context))
03764 context = "default";
03765
03766 if (!(event = ast_event_new(AST_EVENT_MWI,
03767 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03768 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03769 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03770 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03771 AST_EVENT_IE_END))) {
03772 return;
03773 }
03774
03775 ast_event_queue_and_cache(event);
03776
03777 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03778 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03779 ast_safe_system(s);
03780 }
03781 }
03782
03783 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03784 {
03785 struct dahdi_pvt *p = pvt;
03786
03787 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03788 return;
03789
03790 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03791 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03792 notify_message(p->mailbox, 1);
03793 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03794 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03795 notify_message(p->mailbox, 0);
03796 }
03797
03798
03799 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03800 ast_hangup(chan);
03801 return;
03802 }
03803 }
03804
03805 static int my_have_progressdetect(void *pvt)
03806 {
03807 struct dahdi_pvt *p = pvt;
03808
03809 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03810 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03811 return 1;
03812 } else {
03813
03814 return 0;
03815 }
03816 }
03817
03818 struct analog_callback analog_callbacks =
03819 {
03820 .play_tone = my_play_tone,
03821 .get_event = my_get_event,
03822 .wait_event = my_wait_event,
03823 .is_off_hook = my_is_off_hook,
03824 .set_echocanceller = my_set_echocanceller,
03825 .ring = my_ring,
03826 .flash = my_flash,
03827 .off_hook = my_off_hook,
03828 .dial_digits = my_dial_digits,
03829 .train_echocanceller = my_train_echocanceller,
03830 .on_hook = my_on_hook,
03831 .is_dialing = my_is_dialing,
03832 .allocate_sub = my_allocate_sub,
03833 .unallocate_sub = my_unallocate_sub,
03834 .swap_subs = my_swap_subchannels,
03835 .has_voicemail = my_has_voicemail,
03836 .check_for_conference = my_check_for_conference,
03837 .conf_add = my_conf_add,
03838 .conf_del = my_conf_del,
03839 .complete_conference_update = my_complete_conference_update,
03840 .start = my_start,
03841 .all_subchannels_hungup = my_all_subchannels_hungup,
03842 .lock_private = my_lock_private,
03843 .unlock_private = my_unlock_private,
03844 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03845 .handle_dtmf = my_handle_dtmf,
03846 .wink = my_wink,
03847 .new_ast_channel = my_new_analog_ast_channel,
03848 .dsp_set_digitmode = my_dsp_set_digitmode,
03849 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03850 .send_callerid = my_send_callerid,
03851 .callwait = my_callwait,
03852 .stop_callwait = my_stop_callwait,
03853 .get_callerid = my_get_callerid,
03854 .start_cid_detect = my_start_cid_detect,
03855 .stop_cid_detect = my_stop_cid_detect,
03856 .handle_notify_message = my_handle_notify_message,
03857 .increase_ss_count = my_increase_ss_count,
03858 .decrease_ss_count = my_decrease_ss_count,
03859 .distinctive_ring = my_distinctive_ring,
03860 .set_linear_mode = my_set_linear_mode,
03861 .set_inthreeway = my_set_inthreeway,
03862 .get_and_handle_alarms = my_get_and_handle_alarms,
03863 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03864 .get_sub_fd = my_get_sub_fd,
03865 .set_cadence = my_set_cadence,
03866 .set_alarm = my_set_alarm,
03867 .set_dialing = my_set_dialing,
03868 .set_outgoing = my_set_outgoing,
03869 .set_ringtimeout = my_set_ringtimeout,
03870 .set_waitingfordt = my_set_waitingfordt,
03871 .check_waitingfordt = my_check_waitingfordt,
03872 .set_confirmanswer = my_set_confirmanswer,
03873 .check_confirmanswer = my_check_confirmanswer,
03874 .set_callwaiting = my_set_callwaiting,
03875 .cancel_cidspill = my_cancel_cidspill,
03876 .confmute = my_confmute,
03877 .set_pulsedial = my_set_pulsedial,
03878 .set_new_owner = my_set_new_owner,
03879 .get_orig_dialstring = my_get_orig_dialstring,
03880 .set_needringing = my_set_needringing,
03881 .set_polarity = my_set_polarity,
03882 .start_polarityswitch = my_start_polarityswitch,
03883 .answer_polarityswitch = my_answer_polarityswitch,
03884 .hangup_polarityswitch = my_hangup_polarityswitch,
03885 .have_progressdetect = my_have_progressdetect,
03886 };
03887
03888
03889 static struct dahdi_pvt *round_robin[32];
03890
03891 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03892 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03893 {
03894 int res;
03895 if (p->subs[SUB_REAL].owner == ast)
03896 res = 0;
03897 else if (p->subs[SUB_CALLWAIT].owner == ast)
03898 res = 1;
03899 else if (p->subs[SUB_THREEWAY].owner == ast)
03900 res = 2;
03901 else {
03902 res = -1;
03903 if (!nullok)
03904 ast_log(LOG_WARNING,
03905 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03906 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03907 }
03908 return res;
03909 }
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03927 {
03928 for (;;) {
03929 if (!pvt->subs[sub_idx].owner) {
03930
03931 break;
03932 }
03933 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03934
03935 break;
03936 }
03937
03938 DEADLOCK_AVOIDANCE(&pvt->lock);
03939 }
03940 }
03941
03942 static void wakeup_sub(struct dahdi_pvt *p, int a)
03943 {
03944 dahdi_lock_sub_owner(p, a);
03945 if (p->subs[a].owner) {
03946 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03947 ast_channel_unlock(p->subs[a].owner);
03948 }
03949 }
03950
03951 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03952 {
03953 for (;;) {
03954 if (p->owner) {
03955 if (ast_channel_trylock(p->owner)) {
03956 DEADLOCK_AVOIDANCE(&p->lock);
03957 } else {
03958 ast_queue_frame(p->owner, f);
03959 ast_channel_unlock(p->owner);
03960 break;
03961 }
03962 } else
03963 break;
03964 }
03965 }
03966
03967 static void handle_clear_alarms(struct dahdi_pvt *p)
03968 {
03969 #if defined(HAVE_PRI)
03970 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03971 return;
03972 }
03973 #endif
03974
03975 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03976 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03977
03978
03979
03980
03981
03982 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03983 }
03984 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03985 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03986
03987
03988
03989
03990
03991 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03992 }
03993 }
03994
03995 #ifdef HAVE_OPENR2
03996
03997 static int dahdi_r2_answer(struct dahdi_pvt *p)
03998 {
03999 int res = 0;
04000
04001
04002
04003 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
04004 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
04005 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
04006 if (!double_answer) {
04007
04008
04009 res = openr2_chan_answer_call(p->r2chan);
04010 } else if (wants_double_answer) {
04011 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
04012 } else {
04013 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
04014 }
04015 #else
04016 res = openr2_chan_answer_call(p->r2chan);
04017 #endif
04018 return res;
04019 }
04020
04021
04022
04023
04024 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
04025 {
04026 openr2_calling_party_category_t cat;
04027 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
04028 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
04029 if (ast_strlen_zero(catstr)) {
04030 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
04031 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04032 return p->mfcr2_category;
04033 }
04034 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
04035 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
04036 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04037 return p->mfcr2_category;
04038 }
04039 ast_debug(1, "Using category %s\n", catstr);
04040 return cat;
04041 }
04042
04043 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
04044 {
04045 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04046 ast_mutex_lock(&p->lock);
04047 if (p->mfcr2call) {
04048 ast_mutex_unlock(&p->lock);
04049
04050
04051
04052
04053
04054 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
04055 return;
04056 }
04057 p->mfcr2call = 1;
04058
04059 p->cid_name[0] = '\0';
04060 p->cid_num[0] = '\0';
04061 p->cid_subaddr[0] = '\0';
04062 p->rdnis[0] = '\0';
04063 p->exten[0] = '\0';
04064 p->mfcr2_ani_index = '\0';
04065 p->mfcr2_dnis_index = '\0';
04066 p->mfcr2_dnis_matched = 0;
04067 p->mfcr2_answer_pending = 0;
04068 p->mfcr2_call_accepted = 0;
04069 ast_mutex_unlock(&p->lock);
04070 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
04071 }
04072
04073 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
04074 {
04075 int res;
04076 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04077 ast_mutex_lock(&p->lock);
04078 p->inalarm = alarm ? 1 : 0;
04079 if (p->inalarm) {
04080 res = get_alarms(p);
04081 handle_alarms(p, res);
04082 } else {
04083 handle_clear_alarms(p);
04084 }
04085 ast_mutex_unlock(&p->lock);
04086 }
04087
04088 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
04089 {
04090 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
04091 }
04092
04093 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
04094 {
04095 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04096 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
04097 if (p->owner) {
04098 ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
04099 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04100 }
04101 ast_mutex_lock(&p->lock);
04102 p->mfcr2call = 0;
04103 ast_mutex_unlock(&p->lock);
04104 }
04105
04106 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04107 {
04108 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04109 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04110 p->channel, openr2_proto_get_disconnect_string(cause));
04111
04112 openr2_chan_set_idle(p->r2chan);
04113 ast_mutex_lock(&p->lock);
04114 p->mfcr2call = 0;
04115 ast_mutex_unlock(&p->lock);
04116 }
04117 }
04118
04119 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04120 {
04121 struct dahdi_pvt *p;
04122 struct ast_channel *c;
04123 struct ast_callid *callid = NULL;
04124 int callid_created = ast_callid_threadstorage_auto(&callid);
04125 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04126 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04127 openr2_proto_get_category_string(category));
04128 p = openr2_chan_get_client_data(r2chan);
04129
04130 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04131 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04132 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04133 goto dahdi_r2_on_call_offered_cleanup;
04134 }
04135 ast_mutex_lock(&p->lock);
04136 p->mfcr2_recvd_category = category;
04137
04138 if (!p->use_callerid) {
04139 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
04140 p->cid_num[0] = 0;
04141 p->cid_name[0] = 0;
04142 }
04143
04144 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04145 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
04146 p->exten[0] = 's';
04147 p->exten[1] = 0;
04148 }
04149 ast_mutex_unlock(&p->lock);
04150 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04151 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04152 p->channel, p->exten, p->context);
04153 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04154 goto dahdi_r2_on_call_offered_cleanup;
04155 }
04156 if (!p->mfcr2_accept_on_offer) {
04157
04158 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04159 if (c) {
04160
04161
04162
04163 goto dahdi_r2_on_call_offered_cleanup;
04164 }
04165 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04166 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04167 } else if (p->mfcr2_charge_calls) {
04168 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04169 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04170 } else {
04171 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04172 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04173 }
04174
04175 dahdi_r2_on_call_offered_cleanup:
04176 ast_callid_threadstorage_auto_clean(callid, callid_created);
04177 }
04178
04179 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04180 {
04181 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04182 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04183 ast_mutex_lock(&p->lock);
04184 p->mfcr2call = 0;
04185 ast_mutex_unlock(&p->lock);
04186 }
04187
04188 static void dahdi_enable_ec(struct dahdi_pvt *p);
04189 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04190 {
04191 struct dahdi_pvt *p = NULL;
04192 struct ast_channel *c = NULL;
04193 struct ast_callid *callid = NULL;
04194 int callid_created = ast_callid_threadstorage_auto(&callid);
04195 p = openr2_chan_get_client_data(r2chan);
04196 dahdi_enable_ec(p);
04197 p->mfcr2_call_accepted = 1;
04198
04199 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04200 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04201
04202
04203
04204
04205 if (!p->mfcr2_accept_on_offer) {
04206 openr2_chan_disable_read(r2chan);
04207 if (p->mfcr2_answer_pending) {
04208 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04209 dahdi_r2_answer(p);
04210 }
04211 goto dahdi_r2_on_call_accepted_cleanup;
04212 }
04213 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04214 if (c) {
04215
04216
04217 openr2_chan_disable_read(r2chan);
04218 goto dahdi_r2_on_call_accepted_cleanup;
04219 }
04220 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04221
04222 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04223 goto dahdi_r2_on_call_accepted_cleanup;
04224 }
04225
04226 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04227 p->subs[SUB_REAL].needringing = 1;
04228 p->dialing = 0;
04229
04230 openr2_chan_disable_read(r2chan);
04231
04232 dahdi_r2_on_call_accepted_cleanup:
04233 ast_callid_threadstorage_auto_clean(callid, callid_created);
04234 }
04235
04236 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04237 {
04238 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04239 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04240 p->subs[SUB_REAL].needanswer = 1;
04241 }
04242
04243 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04244 {
04245
04246 }
04247
04248 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04249 {
04250 switch (cause) {
04251 case OR2_CAUSE_BUSY_NUMBER:
04252 return AST_CAUSE_BUSY;
04253 case OR2_CAUSE_NETWORK_CONGESTION:
04254 return AST_CAUSE_CONGESTION;
04255 case OR2_CAUSE_OUT_OF_ORDER:
04256 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04257 case OR2_CAUSE_UNALLOCATED_NUMBER:
04258 return AST_CAUSE_UNREGISTERED;
04259 case OR2_CAUSE_NO_ANSWER:
04260 return AST_CAUSE_NO_ANSWER;
04261 case OR2_CAUSE_NORMAL_CLEARING:
04262 return AST_CAUSE_NORMAL_CLEARING;
04263 case OR2_CAUSE_UNSPECIFIED:
04264 default:
04265 return AST_CAUSE_NOTDEFINED;
04266 }
04267 }
04268
04269 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04270 {
04271 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04272 char cause_str[50];
04273 struct ast_control_pvt_cause_code *cause_code;
04274 int datalen = sizeof(*cause_code);
04275
04276 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04277 ast_mutex_lock(&p->lock);
04278 if (!p->owner) {
04279 ast_mutex_unlock(&p->lock);
04280
04281 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04282 return;
04283 }
04284
04285 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
04286 datalen += strlen(cause_str);
04287 cause_code = ast_alloca(datalen);
04288 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
04289 ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
04290 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
04291 ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
04292 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
04293
04294
04295
04296 if (ast_channel_state(p->owner) == AST_STATE_UP) {
04297 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04298 ast_mutex_unlock(&p->lock);
04299 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04300
04301 switch (cause) {
04302 case OR2_CAUSE_BUSY_NUMBER:
04303 p->subs[SUB_REAL].needbusy = 1;
04304 break;
04305 case OR2_CAUSE_NETWORK_CONGESTION:
04306 case OR2_CAUSE_OUT_OF_ORDER:
04307 case OR2_CAUSE_UNALLOCATED_NUMBER:
04308 case OR2_CAUSE_NO_ANSWER:
04309 case OR2_CAUSE_UNSPECIFIED:
04310 case OR2_CAUSE_NORMAL_CLEARING:
04311 p->subs[SUB_REAL].needcongestion = 1;
04312 break;
04313 default:
04314 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04315 }
04316 ast_mutex_unlock(&p->lock);
04317 } else {
04318 ast_mutex_unlock(&p->lock);
04319
04320
04321 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04322 }
04323 }
04324
04325 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04326 {
04327 switch (level) {
04328 case OR2_LOG_NOTICE:
04329 ast_verbose("%s", logmessage);
04330 break;
04331 case OR2_LOG_WARNING:
04332 ast_log(LOG_WARNING, "%s", logmessage);
04333 break;
04334 case OR2_LOG_ERROR:
04335 ast_log(LOG_ERROR, "%s", logmessage);
04336 break;
04337 case OR2_LOG_STACK_TRACE:
04338 case OR2_LOG_MF_TRACE:
04339 case OR2_LOG_CAS_TRACE:
04340 case OR2_LOG_DEBUG:
04341 case OR2_LOG_EX_DEBUG:
04342 ast_debug(1, "%s", logmessage);
04343 break;
04344 default:
04345 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04346 ast_debug(1, "%s", logmessage);
04347 break;
04348 }
04349 }
04350
04351 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04352 {
04353 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04354 ast_mutex_lock(&p->lock);
04355 p->remotelyblocked = 1;
04356 ast_mutex_unlock(&p->lock);
04357 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04358 }
04359
04360 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04361 {
04362 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04363 ast_mutex_lock(&p->lock);
04364 p->remotelyblocked = 0;
04365 ast_mutex_unlock(&p->lock);
04366 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04367 }
04368
04369 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04370 __attribute__((format (printf, 3, 0)));
04371 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04372 {
04373 #define CONTEXT_TAG "Context - "
04374 char logmsg[256];
04375 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04376 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04377 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04378 dahdi_r2_write_log(level, completemsg);
04379 #undef CONTEXT_TAG
04380 }
04381
04382 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04383 __attribute__((format (printf, 3, 0)));
04384 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04385 {
04386 #define CHAN_TAG "Chan "
04387 char logmsg[256];
04388 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04389 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04390 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04391 dahdi_r2_write_log(level, completemsg);
04392 }
04393
04394 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04395 {
04396 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04397
04398 if (p->immediate) {
04399 return 0;
04400 }
04401 p->exten[p->mfcr2_dnis_index] = digit;
04402 p->rdnis[p->mfcr2_dnis_index] = digit;
04403 p->mfcr2_dnis_index++;
04404 p->exten[p->mfcr2_dnis_index] = 0;
04405 p->rdnis[p->mfcr2_dnis_index] = 0;
04406
04407 if ((p->mfcr2_dnis_matched ||
04408 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04409 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04410 return 0;
04411 }
04412
04413 return 1;
04414 }
04415
04416 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04417 {
04418 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04419 p->cid_num[p->mfcr2_ani_index] = digit;
04420 p->cid_name[p->mfcr2_ani_index] = digit;
04421 p->mfcr2_ani_index++;
04422 p->cid_num[p->mfcr2_ani_index] = 0;
04423 p->cid_name[p->mfcr2_ani_index] = 0;
04424 }
04425
04426 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04427 {
04428 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04429 }
04430
04431 static openr2_event_interface_t dahdi_r2_event_iface = {
04432 .on_call_init = dahdi_r2_on_call_init,
04433 .on_call_offered = dahdi_r2_on_call_offered,
04434 .on_call_accepted = dahdi_r2_on_call_accepted,
04435 .on_call_answered = dahdi_r2_on_call_answered,
04436 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04437 .on_call_end = dahdi_r2_on_call_end,
04438 .on_call_read = dahdi_r2_on_call_read,
04439 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04440 .on_os_error = dahdi_r2_on_os_error,
04441 .on_protocol_error = dahdi_r2_on_protocol_error,
04442 .on_line_blocked = dahdi_r2_on_line_blocked,
04443 .on_line_idle = dahdi_r2_on_line_idle,
04444
04445 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04446 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04447 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04448
04449 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04450 };
04451
04452 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04453 {
04454 return AST_ALAW(sample);
04455 }
04456
04457 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04458 {
04459 return AST_LIN2A(sample);
04460 }
04461
04462 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04463 dahdi_r2_alaw_to_linear,
04464 dahdi_r2_linear_to_alaw
04465 };
04466
04467 #endif
04468
04469 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04470 {
04471 int tchan;
04472 int tinthreeway;
04473 struct ast_channel *towner;
04474
04475 ast_debug(1, "Swapping %d and %d\n", a, b);
04476
04477 tchan = p->subs[a].chan;
04478 towner = p->subs[a].owner;
04479 tinthreeway = p->subs[a].inthreeway;
04480
04481 p->subs[a].chan = p->subs[b].chan;
04482 p->subs[a].owner = p->subs[b].owner;
04483 p->subs[a].inthreeway = p->subs[b].inthreeway;
04484
04485 p->subs[b].chan = tchan;
04486 p->subs[b].owner = towner;
04487 p->subs[b].inthreeway = tinthreeway;
04488
04489 if (p->subs[a].owner)
04490 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04491 if (p->subs[b].owner)
04492 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04493 wakeup_sub(p, a);
04494 wakeup_sub(p, b);
04495 }
04496
04497 static int dahdi_open(char *fn)
04498 {
04499 int fd;
04500 int isnum;
04501 int chan = 0;
04502 int bs;
04503 int x;
04504 isnum = 1;
04505 for (x = 0; x < strlen(fn); x++) {
04506 if (!isdigit(fn[x])) {
04507 isnum = 0;
04508 break;
04509 }
04510 }
04511 if (isnum) {
04512 chan = atoi(fn);
04513 if (chan < 1) {
04514 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04515 return -1;
04516 }
04517 fn = "/dev/dahdi/channel";
04518 }
04519 fd = open(fn, O_RDWR | O_NONBLOCK);
04520 if (fd < 0) {
04521 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04522 return -1;
04523 }
04524 if (chan) {
04525 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04526 x = errno;
04527 close(fd);
04528 errno = x;
04529 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04530 return -1;
04531 }
04532 }
04533 bs = READ_SIZE;
04534 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04535 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04536 x = errno;
04537 close(fd);
04538 errno = x;
04539 return -1;
04540 }
04541 return fd;
04542 }
04543
04544 static void dahdi_close(int fd)
04545 {
04546 if (fd > 0)
04547 close(fd);
04548 }
04549
04550 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04551 {
04552 dahdi_close(chan_pvt->subs[sub_num].dfd);
04553 chan_pvt->subs[sub_num].dfd = -1;
04554 }
04555
04556 #if defined(HAVE_PRI)
04557 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04558 {
04559 dahdi_close(pri->pri.fds[fd_num]);
04560 pri->pri.fds[fd_num] = -1;
04561 }
04562 #endif
04563
04564 #if defined(HAVE_SS7)
04565 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04566 {
04567 dahdi_close(ss7->ss7.fds[fd_num]);
04568 ss7->ss7.fds[fd_num] = -1;
04569 }
04570 #endif
04571
04572 static int dahdi_setlinear(int dfd, int linear)
04573 {
04574 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04575 }
04576
04577
04578 static int alloc_sub(struct dahdi_pvt *p, int x)
04579 {
04580 struct dahdi_bufferinfo bi;
04581 int res;
04582 if (p->subs[x].dfd >= 0) {
04583 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04584 return -1;
04585 }
04586
04587 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04588 if (p->subs[x].dfd <= -1) {
04589 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04590 return -1;
04591 }
04592
04593 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04594 if (!res) {
04595 bi.txbufpolicy = p->buf_policy;
04596 bi.rxbufpolicy = p->buf_policy;
04597 bi.numbufs = p->buf_no;
04598 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04599 if (res < 0) {
04600 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04601 }
04602 } else
04603 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04604
04605 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04606 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04607 dahdi_close_sub(p, x);
04608 p->subs[x].dfd = -1;
04609 return -1;
04610 }
04611 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04612 return 0;
04613 }
04614
04615 static int unalloc_sub(struct dahdi_pvt *p, int x)
04616 {
04617 if (!x) {
04618 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04619 return -1;
04620 }
04621 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04622 dahdi_close_sub(p, x);
04623 p->subs[x].linear = 0;
04624 p->subs[x].chan = 0;
04625 p->subs[x].owner = NULL;
04626 p->subs[x].inthreeway = 0;
04627 p->polarity = POLARITY_IDLE;
04628 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04629 return 0;
04630 }
04631
04632 static int digit_to_dtmfindex(char digit)
04633 {
04634 if (isdigit(digit))
04635 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04636 else if (digit >= 'A' && digit <= 'D')
04637 return DAHDI_TONE_DTMF_A + (digit - 'A');
04638 else if (digit >= 'a' && digit <= 'd')
04639 return DAHDI_TONE_DTMF_A + (digit - 'a');
04640 else if (digit == '*')
04641 return DAHDI_TONE_DTMF_s;
04642 else if (digit == '#')
04643 return DAHDI_TONE_DTMF_p;
04644 else
04645 return -1;
04646 }
04647
04648 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04649 {
04650 struct dahdi_pvt *pvt;
04651 int idx;
04652 int dtmf = -1;
04653 int res;
04654
04655 pvt = ast_channel_tech_pvt(chan);
04656
04657 ast_mutex_lock(&pvt->lock);
04658
04659 idx = dahdi_get_index(chan, pvt, 0);
04660
04661 if ((idx != SUB_REAL) || !pvt->owner)
04662 goto out;
04663
04664 #ifdef HAVE_PRI
04665 switch (pvt->sig) {
04666 case SIG_PRI_LIB_HANDLE_CASES:
04667 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04668 if (!res)
04669 goto out;
04670 break;
04671 default:
04672 break;
04673 }
04674 #endif
04675 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04676 goto out;
04677
04678 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04679 char dial_str[] = { 'T', digit, '\0' };
04680
04681 res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
04682 if (!res) {
04683 pvt->dialing = 1;
04684 }
04685 } else {
04686 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04687 ast_channel_name(chan), digit);
04688 pvt->dialing = 1;
04689 pvt->begindigit = digit;
04690 }
04691
04692 out:
04693 ast_mutex_unlock(&pvt->lock);
04694
04695 return 0;
04696 }
04697
04698 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04699 {
04700 struct dahdi_pvt *pvt;
04701 int res = 0;
04702 int idx;
04703 int x;
04704
04705 pvt = ast_channel_tech_pvt(chan);
04706
04707 ast_mutex_lock(&pvt->lock);
04708
04709 idx = dahdi_get_index(chan, pvt, 0);
04710
04711 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04712 goto out;
04713
04714 #ifdef HAVE_PRI
04715
04716 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04717 goto out;
04718 }
04719 #endif
04720
04721 if (pvt->begindigit) {
04722 x = -1;
04723 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04724 ast_channel_name(chan), digit);
04725 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04726 pvt->dialing = 0;
04727 pvt->begindigit = 0;
04728 }
04729
04730 out:
04731 ast_mutex_unlock(&pvt->lock);
04732
04733 return res;
04734 }
04735
04736 static const char * const events[] = {
04737 "No event",
04738 "On hook",
04739 "Ring/Answered",
04740 "Wink/Flash",
04741 "Alarm",
04742 "No more alarm",
04743 "HDLC Abort",
04744 "HDLC Overrun",
04745 "HDLC Bad FCS",
04746 "Dial Complete",
04747 "Ringer On",
04748 "Ringer Off",
04749 "Hook Transition Complete",
04750 "Bits Changed",
04751 "Pulse Start",
04752 "Timer Expired",
04753 "Timer Ping",
04754 "Polarity Reversal",
04755 "Ring Begin",
04756 };
04757
04758 static struct {
04759 int alarm;
04760 char *name;
04761 } alarms[] = {
04762 { DAHDI_ALARM_RED, "Red Alarm" },
04763 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04764 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04765 { DAHDI_ALARM_RECOVER, "Recovering" },
04766 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04767 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04768 { DAHDI_ALARM_NONE, "None" },
04769 };
04770
04771 static char *alarm2str(int alm)
04772 {
04773 int x;
04774 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04775 if (alarms[x].alarm & alm)
04776 return alarms[x].name;
04777 }
04778 return alm ? "Unknown Alarm" : "No Alarm";
04779 }
04780
04781 static const char *event2str(int event)
04782 {
04783 static char buf[256];
04784 if ((event < (ARRAY_LEN(events))) && (event > -1))
04785 return events[event];
04786 sprintf(buf, "Event %d", event);
04787 return buf;
04788 }
04789
04790 static char *dahdi_sig2str(int sig)
04791 {
04792 static char buf[256];
04793 switch (sig) {
04794 case SIG_EM:
04795 return "E & M Immediate";
04796 case SIG_EMWINK:
04797 return "E & M Wink";
04798 case SIG_EM_E1:
04799 return "E & M E1";
04800 case SIG_FEATD:
04801 return "Feature Group D (DTMF)";
04802 case SIG_FEATDMF:
04803 return "Feature Group D (MF)";
04804 case SIG_FEATDMF_TA:
04805 return "Feature Groud D (MF) Tandem Access";
04806 case SIG_FEATB:
04807 return "Feature Group B (MF)";
04808 case SIG_E911:
04809 return "E911 (MF)";
04810 case SIG_FGC_CAMA:
04811 return "FGC/CAMA (Dialpulse)";
04812 case SIG_FGC_CAMAMF:
04813 return "FGC/CAMA (MF)";
04814 case SIG_FXSLS:
04815 return "FXS Loopstart";
04816 case SIG_FXSGS:
04817 return "FXS Groundstart";
04818 case SIG_FXSKS:
04819 return "FXS Kewlstart";
04820 case SIG_FXOLS:
04821 return "FXO Loopstart";
04822 case SIG_FXOGS:
04823 return "FXO Groundstart";
04824 case SIG_FXOKS:
04825 return "FXO Kewlstart";
04826 case SIG_PRI:
04827 return "ISDN PRI";
04828 case SIG_BRI:
04829 return "ISDN BRI Point to Point";
04830 case SIG_BRI_PTMP:
04831 return "ISDN BRI Point to MultiPoint";
04832 case SIG_SS7:
04833 return "SS7";
04834 case SIG_MFCR2:
04835 return "MFC/R2";
04836 case SIG_SF:
04837 return "SF (Tone) Immediate";
04838 case SIG_SFWINK:
04839 return "SF (Tone) Wink";
04840 case SIG_SF_FEATD:
04841 return "SF (Tone) with Feature Group D (DTMF)";
04842 case SIG_SF_FEATDMF:
04843 return "SF (Tone) with Feature Group D (MF)";
04844 case SIG_SF_FEATB:
04845 return "SF (Tone) with Feature Group B (MF)";
04846 case 0:
04847 return "Pseudo";
04848 default:
04849 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04850 return buf;
04851 }
04852 }
04853
04854 #define sig2str dahdi_sig2str
04855
04856 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04857 {
04858
04859
04860 struct dahdi_confinfo zi;
04861
04862 memset(&zi, 0, sizeof(zi));
04863 zi.chan = 0;
04864
04865 if (slavechannel > 0) {
04866
04867 zi.confmode = DAHDI_CONF_DIGITALMON;
04868 zi.confno = slavechannel;
04869 } else {
04870 if (!idx) {
04871
04872 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04873 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04874 } else
04875 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04876 zi.confno = p->confno;
04877 }
04878 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04879 return 0;
04880 if (c->dfd < 0)
04881 return 0;
04882 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04883 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04884 return -1;
04885 }
04886 if (slavechannel < 1) {
04887 p->confno = zi.confno;
04888 }
04889 c->curconf = zi;
04890 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04891 return 0;
04892 }
04893
04894 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04895 {
04896
04897 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04898 return 1;
04899
04900 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04901 return 1;
04902 return 0;
04903 }
04904
04905 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04906 {
04907 struct dahdi_confinfo zi;
04908 if (
04909 (c->dfd < 0) ||
04910
04911 !isourconf(p, c)
04912
04913 ) return 0;
04914 memset(&zi, 0, sizeof(zi));
04915 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04916 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04917 return -1;
04918 }
04919 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04920 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04921 return 0;
04922 }
04923
04924 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04925 {
04926 int x;
04927 int useslavenative;
04928 struct dahdi_pvt *slave = NULL;
04929
04930 useslavenative = 1;
04931
04932 for (x = 0; x < 3; x++) {
04933
04934
04935 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04936 useslavenative = 0;
04937 }
04938
04939
04940 if (useslavenative) {
04941 for (x = 0; x < MAX_SLAVES; x++) {
04942 if (p->slaves[x]) {
04943 if (slave) {
04944
04945
04946 slave = NULL;
04947 useslavenative = 0;
04948 break;
04949 } else {
04950
04951 slave = p->slaves[x];
04952 }
04953 }
04954 }
04955 }
04956
04957 if (!slave)
04958 useslavenative = 0;
04959 else if (slave->law != p->law) {
04960 useslavenative = 0;
04961 slave = NULL;
04962 }
04963 if (out)
04964 *out = slave;
04965 return useslavenative;
04966 }
04967
04968 static int reset_conf(struct dahdi_pvt *p)
04969 {
04970 p->confno = -1;
04971 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04972 if (p->subs[SUB_REAL].dfd > -1) {
04973 struct dahdi_confinfo zi;
04974
04975 memset(&zi, 0, sizeof(zi));
04976 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04977 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04978 }
04979 return 0;
04980 }
04981
04982 static int update_conf(struct dahdi_pvt *p)
04983 {
04984 int needconf = 0;
04985 int x;
04986 int useslavenative;
04987 struct dahdi_pvt *slave = NULL;
04988
04989 useslavenative = isslavenative(p, &slave);
04990
04991 for (x = 0; x < 3; x++) {
04992
04993 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04994 conf_add(p, &p->subs[x], x, 0);
04995 needconf++;
04996 } else {
04997 conf_del(p, &p->subs[x], x);
04998 }
04999 }
05000
05001
05002 for (x = 0; x < MAX_SLAVES; x++) {
05003 if (p->slaves[x]) {
05004 if (useslavenative)
05005 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
05006 else {
05007 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
05008 needconf++;
05009 }
05010 }
05011 }
05012
05013 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
05014 if (useslavenative)
05015 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
05016 else {
05017 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
05018 needconf++;
05019 }
05020 }
05021
05022 if (p->master) {
05023 if (isslavenative(p->master, NULL)) {
05024 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
05025 } else {
05026 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
05027 }
05028 }
05029 if (!needconf) {
05030
05031
05032 p->confno = -1;
05033 }
05034 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
05035 return 0;
05036 }
05037
05038 static void dahdi_enable_ec(struct dahdi_pvt *p)
05039 {
05040 int res;
05041 if (!p)
05042 return;
05043 if (p->echocanon) {
05044 ast_debug(1, "Echo cancellation already on\n");
05045 return;
05046 }
05047 if (p->digital) {
05048 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
05049 return;
05050 }
05051 if (p->echocancel.head.tap_length) {
05052 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05053 switch (p->sig) {
05054 #if defined(HAVE_PRI)
05055 case SIG_PRI_LIB_HANDLE_CASES:
05056 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05057
05058
05059
05060
05061 return;
05062 }
05063
05064 #endif
05065 #if defined(HAVE_SS7)
05066 case SIG_SS7:
05067 #endif
05068 {
05069 int x = 1;
05070
05071 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
05072 if (res)
05073 ast_log(LOG_WARNING,
05074 "Unable to enable audio mode on channel %d (%s)\n",
05075 p->channel, strerror(errno));
05076 }
05077 break;
05078 default:
05079 break;
05080 }
05081 #endif
05082 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
05083 if (res) {
05084 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
05085 } else {
05086 p->echocanon = 1;
05087 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
05088 }
05089 } else
05090 ast_debug(1, "No echo cancellation requested\n");
05091 }
05092
05093 static void dahdi_train_ec(struct dahdi_pvt *p)
05094 {
05095 int x;
05096 int res;
05097
05098 if (p && p->echocanon && p->echotraining) {
05099 x = p->echotraining;
05100 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
05101 if (res)
05102 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
05103 else
05104 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
05105 } else {
05106 ast_debug(1, "No echo training requested\n");
05107 }
05108 }
05109
05110 static void dahdi_disable_ec(struct dahdi_pvt *p)
05111 {
05112 int res;
05113
05114 if (p->echocanon) {
05115 struct dahdi_echocanparams ecp = { .tap_length = 0 };
05116
05117 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
05118
05119 if (res)
05120 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
05121 else
05122 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05123 }
05124
05125 p->echocanon = 0;
05126 }
05127
05128
05129 static int drc_sample(int sample, float drc)
05130 {
05131 float neg;
05132 float shallow, steep;
05133 float max = SHRT_MAX;
05134
05135 neg = (sample < 0 ? -1 : 1);
05136 steep = drc*sample;
05137 shallow = neg*(max-max/drc)+(float)sample/drc;
05138 if (abs(steep) < abs(shallow)) {
05139 sample = steep;
05140 }
05141 else {
05142 sample = shallow;
05143 }
05144
05145 return sample;
05146 }
05147
05148
05149 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05150 {
05151 int j;
05152 int k;
05153
05154 float linear_gain = pow(10.0, gain / 20.0);
05155
05156 switch (law) {
05157 case DAHDI_LAW_ALAW:
05158 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05159 if (gain || drc) {
05160 k = AST_ALAW(j);
05161 if (drc) {
05162 k = drc_sample(k, drc);
05163 }
05164 k = (float)k*linear_gain;
05165 if (k > 32767) k = 32767;
05166 if (k < -32767) k = -32767;
05167 g->txgain[j] = AST_LIN2A(k);
05168 } else {
05169 g->txgain[j] = j;
05170 }
05171 }
05172 break;
05173 case DAHDI_LAW_MULAW:
05174 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05175 if (gain || drc) {
05176 k = AST_MULAW(j);
05177 if (drc) {
05178 k = drc_sample(k, drc);
05179 }
05180 k = (float)k*linear_gain;
05181 if (k > 32767) k = 32767;
05182 if (k < -32767) k = -32767;
05183 g->txgain[j] = AST_LIN2MU(k);
05184
05185 } else {
05186 g->txgain[j] = j;
05187 }
05188 }
05189 break;
05190 }
05191 }
05192
05193 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05194 {
05195 int j;
05196 int k;
05197 float linear_gain = pow(10.0, gain / 20.0);
05198
05199 switch (law) {
05200 case DAHDI_LAW_ALAW:
05201 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05202 if (gain || drc) {
05203 k = AST_ALAW(j);
05204 if (drc) {
05205 k = drc_sample(k, drc);
05206 }
05207 k = (float)k*linear_gain;
05208 if (k > 32767) k = 32767;
05209 if (k < -32767) k = -32767;
05210 g->rxgain[j] = AST_LIN2A(k);
05211 } else {
05212 g->rxgain[j] = j;
05213 }
05214 }
05215 break;
05216 case DAHDI_LAW_MULAW:
05217 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05218 if (gain || drc) {
05219 k = AST_MULAW(j);
05220 if (drc) {
05221 k = drc_sample(k, drc);
05222 }
05223 k = (float)k*linear_gain;
05224 if (k > 32767) k = 32767;
05225 if (k < -32767) k = -32767;
05226 g->rxgain[j] = AST_LIN2MU(k);
05227 } else {
05228 g->rxgain[j] = j;
05229 }
05230 }
05231 break;
05232 }
05233 }
05234
05235 static int set_actual_txgain(int fd, float gain, float drc, int law)
05236 {
05237 struct dahdi_gains g;
05238 int res;
05239
05240 memset(&g, 0, sizeof(g));
05241 res = ioctl(fd, DAHDI_GETGAINS, &g);
05242 if (res) {
05243 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05244 return res;
05245 }
05246
05247 fill_txgain(&g, gain, drc, law);
05248
05249 return ioctl(fd, DAHDI_SETGAINS, &g);
05250 }
05251
05252 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05253 {
05254 struct dahdi_gains g;
05255 int res;
05256
05257 memset(&g, 0, sizeof(g));
05258 res = ioctl(fd, DAHDI_GETGAINS, &g);
05259 if (res) {
05260 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05261 return res;
05262 }
05263
05264 fill_rxgain(&g, gain, drc, law);
05265
05266 return ioctl(fd, DAHDI_SETGAINS, &g);
05267 }
05268
05269 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05270 {
05271 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05272 }
05273
05274 static int bump_gains(struct dahdi_pvt *p)
05275 {
05276 int res;
05277
05278
05279 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05280 if (res) {
05281 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05282 return -1;
05283 }
05284
05285 return 0;
05286 }
05287
05288 static int restore_gains(struct dahdi_pvt *p)
05289 {
05290 int res;
05291
05292 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05293 if (res) {
05294 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05295 return -1;
05296 }
05297
05298 return 0;
05299 }
05300
05301 static inline int dahdi_set_hook(int fd, int hs)
05302 {
05303 int x, res;
05304
05305 x = hs;
05306 res = ioctl(fd, DAHDI_HOOK, &x);
05307
05308 if (res < 0) {
05309 if (errno == EINPROGRESS)
05310 return 0;
05311 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05312
05313 }
05314
05315 return res;
05316 }
05317
05318 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05319 {
05320 int x, res;
05321
05322 x = muted;
05323 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05324 switch (p->sig) {
05325 #if defined(HAVE_PRI)
05326 case SIG_PRI_LIB_HANDLE_CASES:
05327 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05328
05329 break;
05330 }
05331
05332 #endif
05333 #if defined(HAVE_SS7)
05334 case SIG_SS7:
05335 #endif
05336 {
05337 int y = 1;
05338
05339 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05340 if (res)
05341 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05342 p->channel, strerror(errno));
05343 }
05344 break;
05345 default:
05346 break;
05347 }
05348 #endif
05349 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05350 if (res < 0)
05351 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05352 return res;
05353 }
05354
05355 static int save_conference(struct dahdi_pvt *p)
05356 {
05357 struct dahdi_confinfo c;
05358 int res;
05359 if (p->saveconf.confmode) {
05360 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05361 return -1;
05362 }
05363 p->saveconf.chan = 0;
05364 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05365 if (res) {
05366 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05367 p->saveconf.confmode = 0;
05368 return -1;
05369 }
05370 memset(&c, 0, sizeof(c));
05371 c.confmode = DAHDI_CONF_NORMAL;
05372 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05373 if (res) {
05374 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05375 return -1;
05376 }
05377 ast_debug(1, "Disabled conferencing\n");
05378 return 0;
05379 }
05380
05381 static int restore_conference(struct dahdi_pvt *p)
05382 {
05383 int res;
05384 if (p->saveconf.confmode) {
05385 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05386 p->saveconf.confmode = 0;
05387 if (res) {
05388 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05389 return -1;
05390 }
05391 ast_debug(1, "Restored conferencing\n");
05392 }
05393 return 0;
05394 }
05395
05396 static int send_cwcidspill(struct dahdi_pvt *p)
05397 {
05398 struct ast_format tmpfmt;
05399
05400 p->callwaitcas = 0;
05401 p->cidcwexpire = 0;
05402 p->cid_suppress_expire = 0;
05403 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05404 return -1;
05405 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05406
05407 p->cidlen += READ_SIZE * 4;
05408 p->cidpos = 0;
05409 send_callerid(p);
05410 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05411 return 0;
05412 }
05413
05414 static int has_voicemail(struct dahdi_pvt *p)
05415 {
05416 int new_msgs;
05417 struct ast_event *event;
05418 char *mailbox, *context;
05419
05420 mailbox = context = ast_strdupa(p->mailbox);
05421 strsep(&context, "@");
05422 if (ast_strlen_zero(context))
05423 context = "default";
05424
05425 event = ast_event_get_cached(AST_EVENT_MWI,
05426 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05427 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05428 AST_EVENT_IE_END);
05429
05430 if (event) {
05431 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05432 ast_event_destroy(event);
05433 } else
05434 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05435
05436 return new_msgs;
05437 }
05438
05439
05440
05441 static int send_callerid(struct dahdi_pvt *p)
05442 {
05443
05444 int res;
05445
05446 if (p->subs[SUB_REAL].linear) {
05447 p->subs[SUB_REAL].linear = 0;
05448 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05449 }
05450 while (p->cidpos < p->cidlen) {
05451 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05452 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05453 if (res < 0) {
05454 if (errno == EAGAIN)
05455 return 0;
05456 else {
05457 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05458 return -1;
05459 }
05460 }
05461 if (!res)
05462 return 0;
05463 p->cidpos += res;
05464 }
05465 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05466 ast_free(p->cidspill);
05467 p->cidspill = NULL;
05468 if (p->callwaitcas) {
05469
05470 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05471 p->cid_suppress_expire = p->cidcwexpire;
05472 } else
05473 restore_conference(p);
05474 return 0;
05475 }
05476
05477 static int dahdi_callwait(struct ast_channel *ast)
05478 {
05479 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05480 struct ast_format tmpfmt;
05481 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05482 if (p->cidspill) {
05483 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05484 ast_free(p->cidspill);
05485 }
05486
05487
05488
05489
05490
05491 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05492 return -1;
05493 save_conference(p);
05494
05495 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05496 if (!p->callwaitrings && p->callwaitingcallerid) {
05497 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05498 p->callwaitcas = 1;
05499 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05500 } else {
05501 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05502 p->callwaitcas = 0;
05503 p->cidlen = 2400 + READ_SIZE * 4;
05504 }
05505 p->cidpos = 0;
05506 send_callerid(p);
05507
05508 return 0;
05509 }
05510
05511 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05512 {
05513 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05514 int x, res, mysig;
05515 char *dest;
05516 AST_DECLARE_APP_ARGS(args,
05517 AST_APP_ARG(group);
05518 AST_APP_ARG(ext);
05519
05520 AST_APP_ARG(other);
05521 );
05522
05523 ast_mutex_lock(&p->lock);
05524 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05525
05526
05527 dest = ast_strdupa(rdest);
05528 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05529 if (!args.ext) {
05530 args.ext = "";
05531 }
05532
05533 #if defined(HAVE_PRI)
05534 if (dahdi_sig_pri_lib_handles(p->sig)) {
05535 char *subaddr;
05536
05537 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05538
05539
05540 subaddr = strchr(p->exten, ':');
05541 if (subaddr) {
05542 *subaddr = '\0';
05543 }
05544 } else
05545 #endif
05546 {
05547 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05548 }
05549
05550 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05551 p->subs[SUB_REAL].needbusy = 1;
05552 ast_mutex_unlock(&p->lock);
05553 return 0;
05554 }
05555 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05556 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05557 ast_mutex_unlock(&p->lock);
05558 return -1;
05559 }
05560 p->waitingfordt.tv_sec = 0;
05561 p->dialednone = 0;
05562 if ((p->radio || (p->oprmode < 0)))
05563 {
05564
05565 ast_setstate(ast, AST_STATE_UP);
05566 ast_mutex_unlock(&p->lock);
05567 return 0;
05568 }
05569 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05570 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05571 if (res)
05572 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05573 p->outgoing = 1;
05574
05575 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05576 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05577 } else {
05578 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05579 }
05580
05581 #ifdef HAVE_PRI
05582 if (dahdi_sig_pri_lib_handles(p->sig)) {
05583 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05584 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05585 ast_mutex_unlock(&p->lock);
05586 return res;
05587 }
05588 #endif
05589
05590 #if defined(HAVE_SS7)
05591 if (p->sig == SIG_SS7) {
05592 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05593 ast_mutex_unlock(&p->lock);
05594 return res;
05595 }
05596 #endif
05597
05598
05599 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05600 p->callwaitrings = 0;
05601 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05602 ast_mutex_unlock(&p->lock);
05603 return res;
05604 }
05605
05606 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05607 switch (mysig) {
05608 case 0:
05609
05610 ast_setstate(ast, AST_STATE_UP);
05611 break;
05612 case SIG_MFCR2:
05613 break;
05614 default:
05615 ast_debug(1, "not yet implemented\n");
05616 ast_mutex_unlock(&p->lock);
05617 return -1;
05618 }
05619
05620 #ifdef HAVE_OPENR2
05621 if (p->mfcr2) {
05622 openr2_calling_party_category_t chancat;
05623 int callres = 0;
05624 char *c, *l;
05625
05626
05627 p->dialdest[0] = '\0';
05628
05629 c = args.ext;
05630 if (!p->hidecallerid) {
05631 l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05632 } else {
05633 l = NULL;
05634 }
05635 if (strlen(c) < p->stripmsd) {
05636 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05637 ast_mutex_unlock(&p->lock);
05638 return -1;
05639 }
05640 p->dialing = 1;
05641 chancat = dahdi_r2_get_channel_category(ast);
05642 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05643 if (-1 == callres) {
05644 ast_mutex_unlock(&p->lock);
05645 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05646 return -1;
05647 }
05648 p->mfcr2_call_accepted = 0;
05649 p->mfcr2_progress_sent = 0;
05650 ast_setstate(ast, AST_STATE_DIALING);
05651 }
05652 #endif
05653 ast_mutex_unlock(&p->lock);
05654 return 0;
05655 }
05656
05657
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05673 {
05674 struct dahdi_pvt *cur;
05675
05676 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05677
05678
05679 for (cur = iflist; cur; cur = cur->next) {
05680 if (pvt->channel < cur->channel) {
05681
05682 pvt->prev = cur->prev;
05683 pvt->next = cur;
05684 if (cur->prev) {
05685
05686 cur->prev->next = pvt;
05687 } else {
05688
05689 iflist = pvt;
05690 }
05691 cur->prev = pvt;
05692 return;
05693 }
05694 }
05695
05696
05697 pvt->prev = ifend;
05698 pvt->next = NULL;
05699 if (ifend) {
05700 ifend->next = pvt;
05701 }
05702 ifend = pvt;
05703 if (!iflist) {
05704
05705 iflist = pvt;
05706 }
05707 }
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721
05722 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05723 {
05724
05725 if (pvt->prev) {
05726 pvt->prev->next = pvt->next;
05727 } else if (iflist == pvt) {
05728
05729 iflist = pvt->next;
05730 }
05731
05732
05733 if (pvt->next) {
05734 pvt->next->prev = pvt->prev;
05735 } else if (ifend == pvt) {
05736
05737 ifend = pvt->prev;
05738 }
05739
05740
05741 pvt->which_iflist = DAHDI_IFLIST_NONE;
05742 pvt->prev = NULL;
05743 pvt->next = NULL;
05744 }
05745
05746 #if defined(HAVE_PRI)
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757
05758
05759
05760
05761
05762
05763 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05764 {
05765 struct dahdi_pvt *cur;
05766
05767 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05768
05769
05770 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05771 if (pvt->channel < cur->channel) {
05772
05773 pvt->prev = cur->prev;
05774 pvt->next = cur;
05775 if (cur->prev) {
05776
05777 cur->prev->next = pvt;
05778 } else {
05779
05780 pri->no_b_chan_iflist = pvt;
05781 }
05782 cur->prev = pvt;
05783 return;
05784 }
05785 }
05786
05787
05788 pvt->prev = pri->no_b_chan_end;
05789 pvt->next = NULL;
05790 if (pri->no_b_chan_end) {
05791 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05792 }
05793 pri->no_b_chan_end = pvt;
05794 if (!pri->no_b_chan_iflist) {
05795
05796 pri->no_b_chan_iflist = pvt;
05797 }
05798 }
05799 #endif
05800
05801 #if defined(HAVE_PRI)
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05817 {
05818
05819 if (pvt->prev) {
05820 pvt->prev->next = pvt->next;
05821 } else if (pri->no_b_chan_iflist == pvt) {
05822
05823 pri->no_b_chan_iflist = pvt->next;
05824 }
05825
05826
05827 if (pvt->next) {
05828 pvt->next->prev = pvt->prev;
05829 } else if (pri->no_b_chan_end == pvt) {
05830
05831 pri->no_b_chan_end = pvt->prev;
05832 }
05833
05834
05835 pvt->which_iflist = DAHDI_IFLIST_NONE;
05836 pvt->prev = NULL;
05837 pvt->next = NULL;
05838 }
05839 #endif
05840
05841 #if defined(HAVE_PRI)
05842
05843
05844
05845
05846
05847
05848
05849
05850
05851 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05852 {
05853 unsigned idx;
05854 struct sig_pri_span *pri;
05855
05856 pri = pvt->pri;
05857 if (!pri) {
05858
05859 return;
05860 }
05861 ast_mutex_lock(&pri->lock);
05862 for (idx = 0; idx < pri->numchans; ++idx) {
05863 if (pri->pvts[idx] == pvt->sig_pvt) {
05864 pri->pvts[idx] = NULL;
05865 ast_mutex_unlock(&pri->lock);
05866 return;
05867 }
05868 }
05869 ast_mutex_unlock(&pri->lock);
05870 }
05871 #endif
05872
05873 #if defined(HAVE_SS7)
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05884 {
05885 unsigned idx;
05886 struct sig_ss7_linkset *ss7;
05887
05888 ss7 = pvt->ss7;
05889 if (!ss7) {
05890
05891 return;
05892 }
05893 ast_mutex_lock(&ss7->lock);
05894 for (idx = 0; idx < ss7->numchans; ++idx) {
05895 if (ss7->pvts[idx] == pvt->sig_pvt) {
05896 ss7->pvts[idx] = NULL;
05897 ast_mutex_unlock(&ss7->lock);
05898 return;
05899 }
05900 }
05901 ast_mutex_unlock(&ss7->lock);
05902 }
05903 #endif
05904
05905 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05906 {
05907 if (cur->next && cur->next->span == cur->span) {
05908 return cur->next;
05909 } else if (cur->prev && cur->prev->span == cur->span) {
05910 return cur->prev;
05911 }
05912
05913 return NULL;
05914 }
05915
05916 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05917 {
05918 struct dahdi_pvt *p = pvt;
05919
05920 if (p->manages_span_alarms) {
05921 struct dahdi_pvt *next = find_next_iface_in_span(p);
05922 if (next) {
05923 next->manages_span_alarms = 1;
05924 }
05925 }
05926
05927
05928 #if defined(HAVE_PRI)
05929 dahdi_unlink_pri_pvt(p);
05930 #endif
05931 #if defined(HAVE_SS7)
05932 dahdi_unlink_ss7_pvt(p);
05933 #endif
05934 switch (pvt->which_iflist) {
05935 case DAHDI_IFLIST_NONE:
05936 break;
05937 case DAHDI_IFLIST_MAIN:
05938 dahdi_iflist_extract(p);
05939 break;
05940 #if defined(HAVE_PRI)
05941 case DAHDI_IFLIST_NO_B_CHAN:
05942 if (p->pri) {
05943 dahdi_nobch_extract(p->pri, p);
05944 }
05945 break;
05946 #endif
05947 }
05948
05949 if (p->sig_pvt) {
05950 if (analog_lib_handles(p->sig, 0, 0)) {
05951 analog_delete(p->sig_pvt);
05952 }
05953 switch (p->sig) {
05954 #if defined(HAVE_PRI)
05955 case SIG_PRI_LIB_HANDLE_CASES:
05956 sig_pri_chan_delete(p->sig_pvt);
05957 break;
05958 #endif
05959 #if defined(HAVE_SS7)
05960 case SIG_SS7:
05961 sig_ss7_chan_delete(p->sig_pvt);
05962 break;
05963 #endif
05964 default:
05965 break;
05966 }
05967 }
05968 ast_free(p->cidspill);
05969 if (p->use_smdi)
05970 ast_smdi_interface_unref(p->smdi_iface);
05971 if (p->mwi_event_sub)
05972 ast_event_unsubscribe(p->mwi_event_sub);
05973 if (p->vars) {
05974 ast_variables_destroy(p->vars);
05975 }
05976 if (p->cc_params) {
05977 ast_cc_config_params_destroy(p->cc_params);
05978 }
05979
05980 p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05981 p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05982
05983 ast_mutex_destroy(&p->lock);
05984 dahdi_close_sub(p, SUB_REAL);
05985 if (p->owner)
05986 ast_channel_tech_pvt_set(p->owner, NULL);
05987 ast_free(p);
05988 }
05989
05990 static void destroy_channel(struct dahdi_pvt *cur, int now)
05991 {
05992 int i;
05993
05994 if (!now) {
05995
05996 if (cur->owner) {
05997 return;
05998 }
05999 for (i = 0; i < 3; i++) {
06000 if (cur->subs[i].owner) {
06001 return;
06002 }
06003 }
06004 }
06005 destroy_dahdi_pvt(cur);
06006 }
06007
06008 static void destroy_all_channels(void)
06009 {
06010 int chan;
06011 #if defined(HAVE_PRI)
06012 unsigned span;
06013 struct sig_pri_span *pri;
06014 #endif
06015 struct dahdi_pvt *p;
06016
06017 while (num_restart_pending) {
06018 usleep(1);
06019 }
06020
06021 ast_mutex_lock(&iflock);
06022
06023 while (iflist) {
06024 p = iflist;
06025
06026 chan = p->channel;
06027 #if defined(HAVE_PRI_SERVICE_MESSAGES)
06028 {
06029 char db_chan_name[20];
06030 char db_answer[5];
06031 char state;
06032 int why = -1;
06033
06034 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
06035 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
06036 sscanf(db_answer, "%1c:%30d", &state, &why);
06037 }
06038 if (!why) {
06039
06040 ast_db_del(db_chan_name, SRVST_DBKEY);
06041 }
06042 }
06043 #endif
06044
06045 destroy_dahdi_pvt(p);
06046 ast_verb(3, "Unregistered channel %d\n", chan);
06047 }
06048 ifcount = 0;
06049 ast_mutex_unlock(&iflock);
06050
06051 #if defined(HAVE_PRI)
06052
06053 for (span = 0; span < NUM_SPANS; ++span) {
06054 if (!pris[span].dchannels[0]) {
06055 break;
06056 }
06057 pri = &pris[span].pri;
06058 ast_mutex_lock(&pri->lock);
06059 while (pri->no_b_chan_iflist) {
06060 p = pri->no_b_chan_iflist;
06061
06062
06063 destroy_dahdi_pvt(p);
06064 }
06065 ast_mutex_unlock(&pri->lock);
06066 }
06067 #endif
06068 }
06069
06070 #if defined(HAVE_PRI)
06071 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
06072
06073 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
06074 {
06075
06076 struct dahdi_pvt *p;
06077
06078 if (ast_strlen_zero(digits)) {
06079 ast_debug(1, "No digit string sent to application!\n");
06080 return -1;
06081 }
06082
06083 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06084
06085 if (!p) {
06086 ast_debug(1, "Unable to find technology private\n");
06087 return -1;
06088 }
06089
06090 pri_send_keypad_facility_exec(p->sig_pvt, digits);
06091
06092 return 0;
06093 }
06094 #endif
06095
06096 #if defined(HAVE_PRI)
06097 #if defined(HAVE_PRI_PROG_W_CAUSE)
06098 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
06099
06100 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
06101 {
06102
06103 struct dahdi_pvt *pvt;
06104 char *parse;
06105 int res;
06106 AST_DECLARE_APP_ARGS(args,
06107 AST_APP_ARG(destination);
06108 AST_APP_ARG(original);
06109 AST_APP_ARG(reason);
06110 );
06111
06112 if (ast_strlen_zero(data)) {
06113 ast_debug(1, "No data sent to application!\n");
06114 return -1;
06115 }
06116 if (ast_channel_tech(chan) != &dahdi_tech) {
06117 ast_debug(1, "Only DAHDI technology accepted!\n");
06118 return -1;
06119 }
06120 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
06121 if (!pvt) {
06122 ast_debug(1, "Unable to find technology private\n");
06123 return -1;
06124 }
06125 switch (pvt->sig) {
06126 case SIG_PRI_LIB_HANDLE_CASES:
06127 break;
06128 default:
06129 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
06130 ast_channel_name(chan));
06131 return -1;
06132 }
06133
06134 parse = ast_strdupa(data);
06135 AST_STANDARD_APP_ARGS(args, parse);
06136
06137 if (ast_strlen_zero(args.destination)) {
06138 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
06139 return -1;
06140 }
06141
06142 if (ast_strlen_zero(args.original)) {
06143 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06144 args.original = NULL;
06145 }
06146
06147 if (ast_strlen_zero(args.reason)) {
06148 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06149 args.reason = NULL;
06150 }
06151
06152 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
06153 args.destination, args.original, args.reason);
06154 if (!res) {
06155
06156
06157
06158
06159 ast_safe_sleep(chan, 5000);
06160 }
06161
06162 return -1;
06163 }
06164 #endif
06165 #endif
06166
06167 #if defined(HAVE_OPENR2)
06168 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06169
06170 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06171 {
06172
06173 openr2_call_mode_t accept_mode;
06174 int res, timeout, maxloops;
06175 struct ast_frame *f;
06176 struct dahdi_pvt *p;
06177 char *parse;
06178 AST_DECLARE_APP_ARGS(args,
06179 AST_APP_ARG(charge);
06180 );
06181
06182 if (ast_strlen_zero(data)) {
06183 ast_debug(1, "No data sent to application!\n");
06184 return -1;
06185 }
06186
06187 if (ast_channel_tech(chan) != &dahdi_tech) {
06188 ast_debug(1, "Only DAHDI technology accepted!\n");
06189 return -1;
06190 }
06191
06192 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06193 if (!p) {
06194 ast_debug(1, "Unable to find technology private!\n");
06195 return -1;
06196 }
06197
06198 parse = ast_strdupa(data);
06199 AST_STANDARD_APP_ARGS(args, parse);
06200
06201 if (ast_strlen_zero(args.charge)) {
06202 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06203 return -1;
06204 }
06205
06206 ast_mutex_lock(&p->lock);
06207 if (!p->mfcr2 || !p->mfcr2call) {
06208 ast_mutex_unlock(&p->lock);
06209 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06210 return -1;
06211 }
06212
06213 if (p->mfcr2_call_accepted) {
06214 ast_mutex_unlock(&p->lock);
06215 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06216 return 0;
06217 }
06218 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06219 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06220 ast_mutex_unlock(&p->lock);
06221 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06222 return -1;
06223 }
06224 ast_mutex_unlock(&p->lock);
06225
06226 res = 0;
06227 timeout = 100;
06228 maxloops = 50;
06229
06230 while (maxloops > 0) {
06231 maxloops--;
06232 if (ast_check_hangup(chan)) {
06233 break;
06234 }
06235 res = ast_waitfor(chan, timeout);
06236 if (res < 0) {
06237 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06238 res = -1;
06239 break;
06240 }
06241 if (res == 0) {
06242 continue;
06243 }
06244 f = ast_read(chan);
06245 if (!f) {
06246 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06247 res = -1;
06248 break;
06249 }
06250 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06251 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06252 ast_frfree(f);
06253 res = -1;
06254 break;
06255 }
06256 ast_frfree(f);
06257 ast_mutex_lock(&p->lock);
06258 if (p->mfcr2_call_accepted) {
06259 ast_mutex_unlock(&p->lock);
06260 ast_debug(1, "Accepted MFC/R2 call!\n");
06261 break;
06262 }
06263 ast_mutex_unlock(&p->lock);
06264 }
06265 if (res == -1) {
06266 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06267 }
06268 return res;
06269 }
06270
06271 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06272 {
06273 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06274 switch (cause) {
06275 case AST_CAUSE_USER_BUSY:
06276 case AST_CAUSE_CALL_REJECTED:
06277 case AST_CAUSE_INTERWORKING:
06278 r2cause = OR2_CAUSE_BUSY_NUMBER;
06279 break;
06280
06281 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06282 case AST_CAUSE_SWITCH_CONGESTION:
06283 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06284 break;
06285
06286 case AST_CAUSE_UNALLOCATED:
06287 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06288 break;
06289
06290 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06291 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06292 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06293 break;
06294
06295 case AST_CAUSE_NO_ANSWER:
06296 case AST_CAUSE_NO_USER_RESPONSE:
06297 r2cause = OR2_CAUSE_NO_ANSWER;
06298 break;
06299
06300 default:
06301 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06302 break;
06303 }
06304 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06305 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06306 return r2cause;
06307 }
06308 #endif
06309
06310 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06311 {
06312 if (p->bufferoverrideinuse) {
06313
06314 struct dahdi_bufferinfo bi = {
06315 .txbufpolicy = p->buf_policy,
06316 .rxbufpolicy = p->buf_policy,
06317 .bufsize = p->bufsize,
06318 .numbufs = p->buf_no
06319 };
06320 int bpres;
06321
06322 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06323 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06324 }
06325 p->bufferoverrideinuse = 0;
06326 return bpres;
06327 }
06328
06329 return -1;
06330 }
06331
06332 static int dahdi_hangup(struct ast_channel *ast)
06333 {
06334 int res = 0;
06335 int idx,x;
06336 int law;
06337
06338 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06339 struct dahdi_params par;
06340
06341 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06342 if (!ast_channel_tech_pvt(ast)) {
06343 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06344 return 0;
06345 }
06346
06347 ast_mutex_lock(&p->lock);
06348 p->exten[0] = '\0';
06349 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06350 dahdi_confmute(p, 0);
06351 restore_gains(p);
06352 p->ignoredtmf = 0;
06353 p->waitingfordt.tv_sec = 0;
06354
06355 res = analog_hangup(p->sig_pvt, ast);
06356 revert_fax_buffers(p, ast);
06357
06358 goto hangup_out;
06359 } else {
06360 p->cid_num[0] = '\0';
06361 p->cid_name[0] = '\0';
06362 p->cid_subaddr[0] = '\0';
06363 }
06364
06365 #if defined(HAVE_PRI)
06366 if (dahdi_sig_pri_lib_handles(p->sig)) {
06367 x = 1;
06368 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06369
06370 dahdi_confmute(p, 0);
06371 p->muting = 0;
06372 restore_gains(p);
06373 if (p->dsp) {
06374 ast_dsp_free(p->dsp);
06375 p->dsp = NULL;
06376 }
06377 p->ignoredtmf = 0;
06378
06379
06380 p->subs[SUB_REAL].owner = NULL;
06381 p->subs[SUB_REAL].needbusy = 0;
06382 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06383
06384 p->owner = NULL;
06385 p->cid_tag[0] = '\0';
06386 p->ringt = 0;
06387 p->distinctivering = 0;
06388 p->confirmanswer = 0;
06389 p->outgoing = 0;
06390 p->digital = 0;
06391 p->faxhandled = 0;
06392 p->pulsedial = 0;
06393
06394 revert_fax_buffers(p, ast);
06395
06396 p->law = p->law_default;
06397 law = p->law_default;
06398 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06399 if (res < 0) {
06400 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06401 p->channel, strerror(errno));
06402 }
06403
06404 sig_pri_hangup(p->sig_pvt, ast);
06405
06406 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06407 dahdi_disable_ec(p);
06408
06409 x = 0;
06410 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06411 p->didtdd = 0;
06412
06413 p->rdnis[0] = '\0';
06414 update_conf(p);
06415 reset_conf(p);
06416
06417
06418 x = 0;
06419 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06420
06421 if (num_restart_pending == 0) {
06422 restart_monitor();
06423 }
06424 goto hangup_out;
06425 }
06426 #endif
06427
06428 #if defined(HAVE_SS7)
06429 if (p->sig == SIG_SS7) {
06430 x = 1;
06431 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06432
06433 dahdi_confmute(p, 0);
06434 p->muting = 0;
06435 restore_gains(p);
06436 if (p->dsp) {
06437 ast_dsp_free(p->dsp);
06438 p->dsp = NULL;
06439 }
06440 p->ignoredtmf = 0;
06441
06442
06443 p->subs[SUB_REAL].owner = NULL;
06444 p->subs[SUB_REAL].needbusy = 0;
06445 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06446
06447 p->owner = NULL;
06448 p->ringt = 0;
06449 p->distinctivering = 0;
06450 p->confirmanswer = 0;
06451 p->outgoing = 0;
06452 p->digital = 0;
06453 p->faxhandled = 0;
06454 p->pulsedial = 0;
06455
06456 revert_fax_buffers(p, ast);
06457
06458 p->law = p->law_default;
06459 law = p->law_default;
06460 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06461 if (res < 0) {
06462 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06463 p->channel, strerror(errno));
06464 }
06465
06466 sig_ss7_hangup(p->sig_pvt, ast);
06467
06468 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06469 dahdi_disable_ec(p);
06470
06471 x = 0;
06472 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06473 p->didtdd = 0;
06474
06475 update_conf(p);
06476 reset_conf(p);
06477
06478
06479 x = 0;
06480 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06481
06482 if (num_restart_pending == 0) {
06483 restart_monitor();
06484 }
06485 goto hangup_out;
06486 }
06487 #endif
06488
06489 idx = dahdi_get_index(ast, p, 1);
06490
06491 dahdi_confmute(p, 0);
06492 p->muting = 0;
06493 restore_gains(p);
06494 if (p->origcid_num) {
06495 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06496 ast_free(p->origcid_num);
06497 p->origcid_num = NULL;
06498 }
06499 if (p->origcid_name) {
06500 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06501 ast_free(p->origcid_name);
06502 p->origcid_name = NULL;
06503 }
06504 if (p->dsp)
06505 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06506
06507 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06508 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06509 p->ignoredtmf = 0;
06510
06511 if (idx > -1) {
06512
06513 p->subs[idx].owner = NULL;
06514 p->subs[idx].needanswer = 0;
06515 p->subs[idx].needflash = 0;
06516 p->subs[idx].needringing = 0;
06517 p->subs[idx].needbusy = 0;
06518 p->subs[idx].needcongestion = 0;
06519 p->subs[idx].linear = 0;
06520 p->polarity = POLARITY_IDLE;
06521 dahdi_setlinear(p->subs[idx].dfd, 0);
06522 if (idx == SUB_REAL) {
06523 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06524 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06525 if (p->subs[SUB_CALLWAIT].inthreeway) {
06526
06527 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06528
06529 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06530 unalloc_sub(p, SUB_CALLWAIT);
06531 p->owner = NULL;
06532 } else {
06533
06534 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06535 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06536 unalloc_sub(p, SUB_THREEWAY);
06537 if (p->subs[SUB_REAL].inthreeway) {
06538
06539
06540 ast_debug(1, "Call was complete, setting owner to former third call\n");
06541 p->owner = p->subs[SUB_REAL].owner;
06542 } else {
06543
06544 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06545 p->owner = NULL;
06546 }
06547 p->subs[SUB_REAL].inthreeway = 0;
06548 }
06549 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06550
06551 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06552 unalloc_sub(p, SUB_CALLWAIT);
06553 p->owner = p->subs[SUB_REAL].owner;
06554 if (ast_channel_state(p->owner) != AST_STATE_UP)
06555 p->subs[SUB_REAL].needanswer = 1;
06556 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06557 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06558 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06559 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06560 unalloc_sub(p, SUB_THREEWAY);
06561 if (p->subs[SUB_REAL].inthreeway) {
06562
06563
06564 ast_debug(1, "Call was complete, setting owner to former third call\n");
06565 p->owner = p->subs[SUB_REAL].owner;
06566 } else {
06567
06568 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06569 p->owner = NULL;
06570 }
06571 p->subs[SUB_REAL].inthreeway = 0;
06572 }
06573 } else if (idx == SUB_CALLWAIT) {
06574
06575 if (p->subs[SUB_CALLWAIT].inthreeway) {
06576
06577
06578 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06579 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06580 S_OR(p->mohsuggest, NULL),
06581 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06582 }
06583 p->subs[SUB_THREEWAY].inthreeway = 0;
06584
06585 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06586 unalloc_sub(p, SUB_THREEWAY);
06587 } else
06588 unalloc_sub(p, SUB_CALLWAIT);
06589 } else if (idx == SUB_THREEWAY) {
06590 if (p->subs[SUB_CALLWAIT].inthreeway) {
06591
06592
06593 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06594 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06595 S_OR(p->mohsuggest, NULL),
06596 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06597 }
06598 p->subs[SUB_CALLWAIT].inthreeway = 0;
06599 }
06600 p->subs[SUB_REAL].inthreeway = 0;
06601
06602
06603 unalloc_sub(p, SUB_THREEWAY);
06604 } else {
06605
06606 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06607 }
06608 }
06609
06610 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06611 p->owner = NULL;
06612 p->ringt = 0;
06613 p->distinctivering = 0;
06614 p->confirmanswer = 0;
06615 p->outgoing = 0;
06616 p->digital = 0;
06617 p->faxhandled = 0;
06618 p->pulsedial = 0;
06619 if (p->dsp) {
06620 ast_dsp_free(p->dsp);
06621 p->dsp = NULL;
06622 }
06623
06624 revert_fax_buffers(p, ast);
06625
06626 p->law = p->law_default;
06627 law = p->law_default;
06628 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06629 if (res < 0)
06630 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06631
06632 #ifdef HAVE_OPENR2
06633 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06634 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06635
06636 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06637 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06638 } else {
06639 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06640 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06641 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06642 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06643 dahdi_r2_disconnect_call(p, r2cause);
06644 }
06645 } else if (p->mfcr2call) {
06646 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06647
06648
06649
06650
06651 p->mfcr2call = 0;
06652 }
06653 #endif
06654 switch (p->sig) {
06655 case SIG_SS7:
06656 case SIG_MFCR2:
06657 case SIG_PRI_LIB_HANDLE_CASES:
06658 case 0:
06659 break;
06660 default:
06661 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06662 break;
06663 }
06664 if (res < 0) {
06665 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06666 }
06667 switch (p->sig) {
06668 case SIG_FXOGS:
06669 case SIG_FXOLS:
06670 case SIG_FXOKS:
06671 memset(&par, 0, sizeof(par));
06672 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06673 if (!res) {
06674 struct analog_pvt *analog_p = p->sig_pvt;
06675 #if 0
06676 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06677 #endif
06678
06679 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06680 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06681 else
06682 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06683 analog_p->fxsoffhookstate = par.rxisoffhook;
06684 }
06685 break;
06686 case SIG_FXSGS:
06687 case SIG_FXSLS:
06688 case SIG_FXSKS:
06689
06690
06691 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06692 time(&p->guardtime);
06693 p->guardtime += 2;
06694 }
06695 break;
06696 default:
06697 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06698 break;
06699 }
06700 if (p->sig)
06701 dahdi_disable_ec(p);
06702 x = 0;
06703 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06704 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06705 p->didtdd = 0;
06706 p->callwaitcas = 0;
06707 p->callwaiting = p->permcallwaiting;
06708 p->hidecallerid = p->permhidecallerid;
06709 p->waitingfordt.tv_sec = 0;
06710 p->dialing = 0;
06711 p->rdnis[0] = '\0';
06712 update_conf(p);
06713 reset_conf(p);
06714
06715 switch (p->sig) {
06716 case SIG_PRI_LIB_HANDLE_CASES:
06717 case SIG_SS7:
06718 x = 0;
06719 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06720 break;
06721 default:
06722 break;
06723 }
06724 if (num_restart_pending == 0)
06725 restart_monitor();
06726 }
06727
06728 p->callwaitingrepeat = 0;
06729 p->cidcwexpire = 0;
06730 p->cid_suppress_expire = 0;
06731 p->oprmode = 0;
06732 hangup_out:
06733 ast_channel_tech_pvt_set(ast, NULL);
06734 ast_free(p->cidspill);
06735 p->cidspill = NULL;
06736
06737 ast_mutex_unlock(&p->lock);
06738 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06739
06740 ast_mutex_lock(&iflock);
06741 if (p->restartpending) {
06742 num_restart_pending--;
06743 }
06744
06745 if (p->destroy) {
06746 destroy_channel(p, 0);
06747 }
06748 ast_mutex_unlock(&iflock);
06749
06750 ast_module_unref(ast_module_info->self);
06751 return 0;
06752 }
06753
06754 static int dahdi_answer(struct ast_channel *ast)
06755 {
06756 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06757 int res = 0;
06758 int idx;
06759 ast_setstate(ast, AST_STATE_UP);
06760 ast_mutex_lock(&p->lock);
06761 idx = dahdi_get_index(ast, p, 0);
06762 if (idx < 0)
06763 idx = SUB_REAL;
06764
06765 if ((p->radio || (p->oprmode < 0))) {
06766 ast_mutex_unlock(&p->lock);
06767 return 0;
06768 }
06769
06770 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06771 res = analog_answer(p->sig_pvt, ast);
06772 ast_mutex_unlock(&p->lock);
06773 return res;
06774 }
06775
06776 switch (p->sig) {
06777 #if defined(HAVE_PRI)
06778 case SIG_PRI_LIB_HANDLE_CASES:
06779 res = sig_pri_answer(p->sig_pvt, ast);
06780 break;
06781 #endif
06782 #if defined(HAVE_SS7)
06783 case SIG_SS7:
06784 res = sig_ss7_answer(p->sig_pvt, ast);
06785 break;
06786 #endif
06787 #ifdef HAVE_OPENR2
06788 case SIG_MFCR2:
06789 if (!p->mfcr2_call_accepted) {
06790
06791
06792 p->mfcr2_answer_pending = 1;
06793 if (p->mfcr2_charge_calls) {
06794 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06795 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06796 } else {
06797 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06798 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06799 }
06800 } else {
06801 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06802 dahdi_r2_answer(p);
06803 }
06804 break;
06805 #endif
06806 case 0:
06807 ast_mutex_unlock(&p->lock);
06808 return 0;
06809 default:
06810 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06811 res = -1;
06812 break;
06813 }
06814 ast_mutex_unlock(&p->lock);
06815 return res;
06816 }
06817
06818 static void disable_dtmf_detect(struct dahdi_pvt *p)
06819 {
06820 int val = 0;
06821
06822 p->ignoredtmf = 1;
06823
06824 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06825
06826 if (!p->hardwaredtmf && p->dsp) {
06827 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06828 ast_dsp_set_features(p->dsp, p->dsp_features);
06829 }
06830 }
06831
06832 static void enable_dtmf_detect(struct dahdi_pvt *p)
06833 {
06834 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06835
06836 if (p->channel == CHAN_PSEUDO)
06837 return;
06838
06839 p->ignoredtmf = 0;
06840
06841 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06842
06843 if (!p->hardwaredtmf && p->dsp) {
06844 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06845 ast_dsp_set_features(p->dsp, p->dsp_features);
06846 }
06847 }
06848
06849 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06850 {
06851 char *cp;
06852 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06853
06854
06855 if (!p || !data || (*datalen < 1)) {
06856 errno = EINVAL;
06857 return -1;
06858 }
06859
06860 switch (option) {
06861 case AST_OPTION_DIGIT_DETECT:
06862 cp = (char *) data;
06863 *cp = p->ignoredtmf ? 0 : 1;
06864 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06865 break;
06866 case AST_OPTION_FAX_DETECT:
06867 cp = (char *) data;
06868 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06869 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06870 break;
06871 case AST_OPTION_CC_AGENT_TYPE:
06872 #if defined(HAVE_PRI)
06873 #if defined(HAVE_PRI_CCSS)
06874 if (dahdi_sig_pri_lib_handles(p->sig)) {
06875 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06876 break;
06877 }
06878 #endif
06879 #endif
06880 return -1;
06881 default:
06882 return -1;
06883 }
06884
06885 errno = 0;
06886
06887 return 0;
06888 }
06889
06890 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06891 {
06892 char *cp;
06893 signed char *scp;
06894 int x;
06895 int idx;
06896 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06897 struct oprmode *oprmode;
06898
06899
06900
06901 if (!p || !data || (datalen < 1)) {
06902 errno = EINVAL;
06903 return -1;
06904 }
06905
06906 switch (option) {
06907 case AST_OPTION_TXGAIN:
06908 scp = (signed char *) data;
06909 idx = dahdi_get_index(chan, p, 0);
06910 if (idx < 0) {
06911 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06912 return -1;
06913 }
06914 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06915 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06916 case AST_OPTION_RXGAIN:
06917 scp = (signed char *) data;
06918 idx = dahdi_get_index(chan, p, 0);
06919 if (idx < 0) {
06920 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06921 return -1;
06922 }
06923 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06924 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06925 case AST_OPTION_TONE_VERIFY:
06926 if (!p->dsp)
06927 break;
06928 cp = (char *) data;
06929 switch (*cp) {
06930 case 1:
06931 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06932 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06933 break;
06934 case 2:
06935 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06936 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06937 break;
06938 default:
06939 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06940 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06941 break;
06942 }
06943 break;
06944 case AST_OPTION_TDD:
06945
06946 cp = (char *) data;
06947 p->mate = 0;
06948 if (!*cp) {
06949 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06950 if (p->tdd)
06951 tdd_free(p->tdd);
06952 p->tdd = 0;
06953 break;
06954 }
06955 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06956 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06957 dahdi_disable_ec(p);
06958
06959 if (!p->didtdd) {
06960 unsigned char mybuf[41000];
06961 unsigned char *buf;
06962 int size, res, fd, len;
06963 struct pollfd fds[1];
06964
06965 buf = mybuf;
06966 memset(buf, 0x7f, sizeof(mybuf));
06967 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06968 len = 40000;
06969 idx = dahdi_get_index(chan, p, 0);
06970 if (idx < 0) {
06971 ast_log(LOG_WARNING, "No index in TDD?\n");
06972 return -1;
06973 }
06974 fd = p->subs[idx].dfd;
06975 while (len) {
06976 if (ast_check_hangup(chan))
06977 return -1;
06978 size = len;
06979 if (size > READ_SIZE)
06980 size = READ_SIZE;
06981 fds[0].fd = fd;
06982 fds[0].events = POLLPRI | POLLOUT;
06983 fds[0].revents = 0;
06984 res = poll(fds, 1, -1);
06985 if (!res) {
06986 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06987 continue;
06988 }
06989
06990 if (fds[0].revents & POLLPRI)
06991 return -1;
06992 if (!(fds[0].revents & POLLOUT)) {
06993 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06994 continue;
06995 }
06996 res = write(fd, buf, size);
06997 if (res != size) {
06998 if (res == -1) return -1;
06999 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07000 break;
07001 }
07002 len -= size;
07003 buf += size;
07004 }
07005 p->didtdd = 1;
07006 }
07007 if (*cp == 2) {
07008 if (p->tdd)
07009 tdd_free(p->tdd);
07010 p->tdd = 0;
07011 p->mate = 1;
07012 break;
07013 }
07014 if (!p->tdd) {
07015 p->tdd = tdd_new();
07016 }
07017 break;
07018 case AST_OPTION_RELAXDTMF:
07019 if (!p->dsp)
07020 break;
07021 cp = (char *) data;
07022 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
07023 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
07024 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
07025 break;
07026 case AST_OPTION_AUDIO_MODE:
07027 #if defined(HAVE_PRI)
07028 if (dahdi_sig_pri_lib_handles(p->sig)
07029 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
07030
07031 break;
07032 }
07033 #endif
07034
07035 cp = (char *) data;
07036 if (!*cp) {
07037 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
07038 x = 0;
07039 dahdi_disable_ec(p);
07040 } else {
07041 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
07042 x = 1;
07043 }
07044 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
07045 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
07046 break;
07047 case AST_OPTION_OPRMODE:
07048 oprmode = (struct oprmode *) data;
07049
07050 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
07051 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
07052 ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
07053 errno = EINVAL;
07054 return -1;
07055 }
07056 pp = ast_channel_tech_pvt(oprmode->peer);
07057 p->oprmode = pp->oprmode = 0;
07058
07059 p->oprpeer = pp;
07060 pp->oprpeer = p;
07061
07062 if (oprmode->mode)
07063 {
07064 pp->oprmode = oprmode->mode;
07065 p->oprmode = -oprmode->mode;
07066 }
07067 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
07068 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
07069 break;
07070 case AST_OPTION_ECHOCAN:
07071 cp = (char *) data;
07072 if (*cp) {
07073 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
07074 dahdi_enable_ec(p);
07075 } else {
07076 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
07077 dahdi_disable_ec(p);
07078 }
07079 break;
07080 case AST_OPTION_DIGIT_DETECT:
07081 cp = (char *) data;
07082 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07083 if (*cp) {
07084 enable_dtmf_detect(p);
07085 } else {
07086 disable_dtmf_detect(p);
07087 }
07088 break;
07089 case AST_OPTION_FAX_DETECT:
07090 cp = (char *) data;
07091 if (p->dsp) {
07092 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07093 if (*cp) {
07094 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
07095 } else {
07096 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07097 }
07098 ast_dsp_set_features(p->dsp, p->dsp_features);
07099 }
07100 break;
07101 default:
07102 return -1;
07103 }
07104 errno = 0;
07105
07106 return 0;
07107 }
07108
07109 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
07110 {
07111 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07112 int res = 0;
07113
07114 if (!p) {
07115
07116 *buf = '\0';
07117 return -1;
07118 }
07119
07120 if (!strcasecmp(data, "rxgain")) {
07121 ast_mutex_lock(&p->lock);
07122 snprintf(buf, len, "%f", p->rxgain);
07123 ast_mutex_unlock(&p->lock);
07124 } else if (!strcasecmp(data, "txgain")) {
07125 ast_mutex_lock(&p->lock);
07126 snprintf(buf, len, "%f", p->txgain);
07127 ast_mutex_unlock(&p->lock);
07128 } else if (!strcasecmp(data, "dahdi_channel")) {
07129 ast_mutex_lock(&p->lock);
07130 snprintf(buf, len, "%d", p->channel);
07131 ast_mutex_unlock(&p->lock);
07132 } else if (!strcasecmp(data, "dahdi_span")) {
07133 ast_mutex_lock(&p->lock);
07134 snprintf(buf, len, "%d", p->span);
07135 ast_mutex_unlock(&p->lock);
07136 } else if (!strcasecmp(data, "dahdi_type")) {
07137 ast_mutex_lock(&p->lock);
07138 switch (p->sig) {
07139 #if defined(HAVE_OPENR2)
07140 case SIG_MFCR2:
07141 ast_copy_string(buf, "mfc/r2", len);
07142 break;
07143 #endif
07144 #if defined(HAVE_PRI)
07145 case SIG_PRI_LIB_HANDLE_CASES:
07146 ast_copy_string(buf, "pri", len);
07147 break;
07148 #endif
07149 case 0:
07150 ast_copy_string(buf, "pseudo", len);
07151 break;
07152 #if defined(HAVE_SS7)
07153 case SIG_SS7:
07154 ast_copy_string(buf, "ss7", len);
07155 break;
07156 #endif
07157 default:
07158
07159 ast_copy_string(buf, "analog", len);
07160 break;
07161 }
07162 ast_mutex_unlock(&p->lock);
07163 #if defined(HAVE_PRI)
07164 #if defined(HAVE_PRI_REVERSE_CHARGE)
07165 } else if (!strcasecmp(data, "reversecharge")) {
07166 ast_mutex_lock(&p->lock);
07167 switch (p->sig) {
07168 case SIG_PRI_LIB_HANDLE_CASES:
07169 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07170 break;
07171 default:
07172 *buf = '\0';
07173 res = -1;
07174 break;
07175 }
07176 ast_mutex_unlock(&p->lock);
07177 #endif
07178 #if defined(HAVE_PRI_SETUP_KEYPAD)
07179 } else if (!strcasecmp(data, "keypad_digits")) {
07180 ast_mutex_lock(&p->lock);
07181 switch (p->