Wed Mar 4 19:58:03 2009

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI Pseudo TDM interface 
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * Connects to the DAHDI telephony library as well as 
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <depend>res_smdi</depend>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <depend>res_features</depend>
00045    <use>pri</use>
00046  ***/
00047 
00048 #include "asterisk.h"
00049 
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 166380 $")
00051 
00052 #include <stdio.h>
00053 #include <string.h>
00054 #ifdef __NetBSD__
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdlib.h>
00062 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00063 #include <stdint.h>
00064 #endif
00065 #include <unistd.h>
00066 #include <sys/ioctl.h>
00067 #include <math.h>
00068 #include <ctype.h>
00069 
00070 #ifdef HAVE_PRI
00071 #include <libpri.h>
00072 #endif
00073 
00074 #include "asterisk/lock.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/config.h"
00077 #include "asterisk/logger.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/options.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/ulaw.h"
00083 #include "asterisk/alaw.h"
00084 #include "asterisk/callerid.h"
00085 #include "asterisk/adsi.h"
00086 #include "asterisk/cli.h"
00087 #include "asterisk/cdr.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/say.h"
00091 #include "asterisk/tdd.h"
00092 #include "asterisk/app.h"
00093 #include "asterisk/dsp.h"
00094 #include "asterisk/astdb.h"
00095 #include "asterisk/manager.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/term.h"
00098 #include "asterisk/utils.h"
00099 #include "asterisk/transcap.h"
00100 #include "asterisk/stringfields.h"
00101 #include "asterisk/abstract_jb.h"
00102 #include "asterisk/smdi.h"
00103 #include "asterisk/astobj.h"
00104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00105 
00106 #include "asterisk/dahdi_compat.h"
00107 #include "asterisk/tonezone_compat.h"
00108 
00109 /*! Global jitterbuffer configuration - by default, jb is disabled */
00110 static struct ast_jb_conf default_jbconf =
00111 {
00112    .flags = 0,
00113    .max_size = -1,
00114    .resync_threshold = -1,
00115    .impl = ""
00116 };
00117 static struct ast_jb_conf global_jbconf;
00118 
00119 #ifndef DAHDI_TONEDETECT
00120 /* Work around older code with no tone detect */
00121 #define DAHDI_EVENT_DTMFDOWN 0
00122 #define DAHDI_EVENT_DTMFUP 0
00123 #endif
00124 
00125 /* define this to send PRI user-user information elements */
00126 #undef SUPPORT_USERUSER
00127 
00128 /*! 
00129  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00130  * the user hangs up to reset the state machine so ring works properly.
00131  * This is used to be able to support kewlstart by putting the zhone in
00132  * groundstart mode since their forward disconnect supervision is entirely
00133  * broken even though their documentation says it isn't and their support
00134  * is entirely unwilling to provide any assistance with their channel banks
00135  * even though their web site says they support their products for life.
00136  */
00137 /* #define ZHONE_HACK */
00138 
00139 /*! \note
00140  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00141  * before dialing on it.  Certain FXO interfaces always think they're out of
00142  * service with this method however.
00143  */
00144 /* #define DAHDI_CHECK_HOOKSTATE */
00145 
00146 /*! \brief Typically, how many rings before we should send Caller*ID */
00147 #define DEFAULT_CIDRINGS 1
00148 
00149 #define CHANNEL_PSEUDO -12
00150 
00151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00152 
00153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00154 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
00155 
00156 static const char tdesc[] = "DAHDI Telephony Driver"
00157 #ifdef HAVE_PRI
00158                " w/PRI"
00159 #endif
00160 ;
00161 
00162 #define SIG_EM    DAHDI_SIG_EM
00163 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00165 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00166 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00167 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00168 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00169 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00170 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00171 #define SIG_FXSLS DAHDI_SIG_FXSLS
00172 #define SIG_FXSGS DAHDI_SIG_FXSGS
00173 #define SIG_FXSKS DAHDI_SIG_FXSKS
00174 #define SIG_FXOLS DAHDI_SIG_FXOLS
00175 #define SIG_FXOGS DAHDI_SIG_FXOGS
00176 #define SIG_FXOKS DAHDI_SIG_FXOKS
00177 #define SIG_PRI      DAHDI_SIG_CLEAR
00178 #define  SIG_SF      DAHDI_SIG_SF
00179 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00181 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00182 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00184 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00185 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00186 
00187 #define NUM_SPANS       32
00188 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00189 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00190 
00191 #define CHAN_PSEUDO  -2
00192 
00193 #define DCHAN_PROVISIONED (1 << 0)
00194 #define DCHAN_NOTINALARM  (1 << 1)
00195 #define DCHAN_UP          (1 << 2)
00196 
00197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00198 
00199 static char defaultcic[64] = "";
00200 static char defaultozz[64] = "";
00201 
00202 static char progzone[10] = "";
00203 
00204 static int distinctiveringaftercid = 0;
00205 
00206 static int numbufs = 4;
00207 
00208 #ifdef HAVE_PRI
00209 static struct ast_channel inuse;
00210 #ifdef PRI_GETSET_TIMERS
00211 static int pritimers[PRI_MAX_TIMERS];
00212 #endif
00213 static int pridebugfd = -1;
00214 static char pridebugfilename[1024] = "";
00215 #endif
00216 
00217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00218 static int firstdigittimeout = 16000;
00219 
00220 /*! \brief How long to wait for following digits (FXO logic) */
00221 static int gendigittimeout = 8000;
00222 
00223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00224 static int matchdigittimeout = 3000;
00225 
00226 /*! \brief Protect the interface list (of dahdi_pvt's) */
00227 AST_MUTEX_DEFINE_STATIC(iflock);
00228 
00229 
00230 static int ifcount = 0;
00231 
00232 #ifdef HAVE_PRI
00233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00234 #endif
00235 
00236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00237    when it's doing something critical. */
00238 AST_MUTEX_DEFINE_STATIC(monlock);
00239 
00240 /*! \brief This is the thread for the monitor which checks for input on the channels
00241    which are not currently in use. */
00242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00243 static ast_cond_t ss_thread_complete;
00244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00245 AST_MUTEX_DEFINE_STATIC(restart_lock);
00246 static int ss_thread_count = 0;
00247 static int num_restart_pending = 0;
00248 
00249 static int restart_monitor(void);
00250 
00251 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00252 
00253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00254 
00255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00256 static inline int dahdi_get_event(int fd)
00257 {
00258    int j;
00259    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }
00263 
00264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00265 static inline int dahdi_wait_event(int fd)
00266 {
00267    int i, j = 0;
00268    i = DAHDI_IOMUX_SIGEVENT;
00269    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }
00275 
00276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00277 #define READ_SIZE 160
00278 
00279 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00280 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00281 
00282 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00283 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00284 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00285 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00286 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00287 
00288 struct dahdi_pvt;
00289 
00290 static int ringt_base = DEFAULT_RINGT;
00291 
00292 #ifdef HAVE_PRI
00293 
00294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00295 #define PRI_CHANNEL(p) ((p) & 0xff)
00296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00298 
00299 struct dahdi_pri {
00300    pthread_t master;                /*!< Thread of master */
00301    ast_mutex_t lock;                /*!< Mutex */
00302    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00303    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00304    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00305    int minunused;                   /*!< Min # of channels to keep empty */
00306    int minidle;                     /*!< Min # of "idling" calls to keep active */
00307    int nodetype;                    /*!< Node type */
00308    int switchtype;                     /*!< Type of switch to emulate */
00309    int nsf;                   /*!< Network-Specific Facilities */
00310    int dialplan;                    /*!< Dialing plan */
00311    int localdialplan;                  /*!< Local dialing plan */
00312    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00313    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00314    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00315    char privateprefix[20];                /*!< for private dialplans */
00316    char unknownprefix[20];                /*!< for unknown dialplans */
00317    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00318    int trunkgroup;                     /*!< What our trunkgroup is */
00319    int mastertrunkgroup;                  /*!< What trunk group is our master */
00320    int prilogicalspan;                 /*!< Logical span number within trunk group */
00321    int numchans;                    /*!< Num of channels we represent */
00322    int overlapdial;                 /*!< In overlap dialing mode */
00323    int facilityenable;                 /*!< Enable facility IEs */
00324    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00325    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00326    struct pri *pri;                 /*!< Currently active D-channel */
00327    int debug;
00328    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00329    int offset;
00330    int span;
00331    int resetting;
00332    int resetpos;
00333 #ifdef HAVE_PRI_INBANDDISCONNECT
00334    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00335 #endif
00336    time_t lastreset;                /*!< time when unused channels were last reset */
00337    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00338    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00339    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00340    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00341 };
00342 
00343 
00344 static struct dahdi_pri pris[NUM_SPANS];
00345 
00346 #if 0
00347 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00348 #else
00349 #define DEFAULT_PRI_DEBUG 0
00350 #endif
00351 
00352 static inline void pri_rel(struct dahdi_pri *pri)
00353 {
00354    ast_mutex_unlock(&pri->lock);
00355 }
00356 
00357 #else
00358 /*! Shut up the compiler */
00359 struct dahdi_pri;
00360 #endif
00361 
00362 #define SUB_REAL  0        /*!< Active call */
00363 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00364 #define SUB_THREEWAY 2        /*!< Three-way call */
00365 
00366 /* Polarity states */
00367 #define POLARITY_IDLE   0
00368 #define POLARITY_REV    1
00369 
00370 
00371 static struct dahdi_distRings drings;
00372 
00373 struct distRingData {
00374    int ring[3];
00375 };
00376 struct ringContextData {
00377    char contextData[AST_MAX_CONTEXT];
00378 };
00379 struct dahdi_distRings {
00380    struct distRingData ringnum[3];
00381    struct ringContextData ringContext[3];
00382 };
00383 
00384 static char *subnames[] = {
00385    "Real",
00386    "Callwait",
00387    "Threeway"
00388 };
00389 
00390 struct dahdi_subchannel {
00391    int dfd;
00392    struct ast_channel *owner;
00393    int chan;
00394    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00395    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00396    unsigned int needringing:1;
00397    unsigned int needbusy:1;
00398    unsigned int needcongestion:1;
00399    unsigned int needcallerid:1;
00400    unsigned int needanswer:1;
00401    unsigned int needflash:1;
00402    unsigned int needhold:1;
00403    unsigned int needunhold:1;
00404    unsigned int linear:1;
00405    unsigned int inthreeway:1;
00406    struct dahdi_confinfo curconf;
00407 };
00408 
00409 #define CONF_USER_REAL     (1 << 0)
00410 #define CONF_USER_THIRDCALL   (1 << 1)
00411 
00412 #define MAX_SLAVES   4
00413 
00414 static struct dahdi_pvt {
00415    ast_mutex_t lock;
00416    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00417                      /*!< Up to three channels can be associated with this call */
00418       
00419    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00420    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00421    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00422 
00423    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00424    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00425    int inconference;          /*!< If our real should be in the conference */
00426    
00427    int buf_no;             /*!< Number of buffers */
00428    int buf_policy;            /*!< Buffer policy */
00429    int sig;             /*!< Signalling style */
00430    int radio;              /*!< radio type */
00431    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00432    int oprmode;               /*!< "Operator Services" mode */
00433    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00434    float rxgain;
00435    float txgain;
00436    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00437    struct dahdi_pvt *next;          /*!< Next channel in list */
00438    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00439 
00440    /* flags */
00441    unsigned int adsi:1;
00442    unsigned int answeronpolarityswitch:1;
00443    unsigned int busydetect:1;
00444    unsigned int callreturn:1;
00445    unsigned int callwaiting:1;
00446    unsigned int callwaitingcallerid:1;
00447    unsigned int cancallforward:1;
00448    unsigned int canpark:1;
00449    unsigned int confirmanswer:1;       /*!< Wait for '#' to confirm answer */
00450    unsigned int destroy:1;
00451    unsigned int didtdd:1;           /*!< flag to say its done it once */
00452    unsigned int dialednone:1;
00453    unsigned int dialing:1;
00454    unsigned int digital:1;
00455    unsigned int dnd:1;
00456    unsigned int echobreak:1;
00457    unsigned int echocanbridged:1;
00458    unsigned int echocanon:1;
00459    unsigned int faxhandled:1;       /*!< Has a fax tone already been handled? */
00460    unsigned int firstradio:1;
00461    unsigned int hanguponpolarityswitch:1;
00462    unsigned int hardwaredtmf:1;
00463    unsigned int hidecallerid:1;
00464    unsigned int hidecalleridname:1;      /*!< Hide just the name not the number for legacy PBX use */
00465    unsigned int ignoredtmf:1;
00466    unsigned int immediate:1;        /*!< Answer before getting digits? */
00467    unsigned int inalarm:1;
00468    unsigned int unknown_alarm:1;
00469    unsigned int mate:1;          /*!< flag to say its in MATE mode */
00470    unsigned int outgoing:1;
00471    unsigned int overlapdial:1;
00472    unsigned int permcallwaiting:1;
00473    unsigned int permhidecallerid:1;    /*!< Whether to hide our outgoing caller ID or not */
00474    unsigned int priindication_oob:1;
00475    unsigned int priexclusive:1;
00476    unsigned int pulse:1;
00477    unsigned int pulsedial:1;        /*!< whether a pulse dial phone is detected */
00478    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00479    unsigned int restrictcid:1;         /*!< Whether restrict the callerid -> only send ANI */
00480    unsigned int threewaycalling:1;
00481    unsigned int transfer:1;
00482    unsigned int use_callerid:1;        /*!< Whether or not to use caller id on this channel */
00483    unsigned int use_callingpres:1;        /*!< Whether to use the callingpres the calling switch sends */
00484    unsigned int usedistinctiveringdetection:1;
00485    unsigned int dahditrcallerid:1;        /*!< should we use the callerid from incoming call on dahdi transfer or not */
00486    unsigned int transfertobusy:1;         /*!< allow flash-transfers to busy channels */
00487 #if defined(HAVE_PRI)
00488    unsigned int alerting:1;
00489    unsigned int alreadyhungup:1;
00490    unsigned int isidlecall:1;
00491    unsigned int proceeding:1;
00492    unsigned int progress:1;
00493    unsigned int resetting:1;
00494    unsigned int setup_ack:1;
00495 #endif
00496    unsigned int use_smdi:1;      /* Whether to use SMDI on this channel */
00497    struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
00498 
00499    struct dahdi_distRings drings;
00500 
00501    char context[AST_MAX_CONTEXT];
00502    char defcontext[AST_MAX_CONTEXT];
00503    char exten[AST_MAX_EXTENSION];
00504    char language[MAX_LANGUAGE];
00505    char mohinterpret[MAX_MUSICCLASS];
00506    char mohsuggest[MAX_MUSICCLASS];
00507 #ifdef PRI_ANI
00508    char cid_ani[AST_MAX_EXTENSION];
00509 #endif
00510    char cid_num[AST_MAX_EXTENSION];
00511    int cid_ton;               /*!< Type Of Number (TON) */
00512    char cid_name[AST_MAX_EXTENSION];
00513    char lastcid_num[AST_MAX_EXTENSION];
00514    char lastcid_name[AST_MAX_EXTENSION];
00515    char *origcid_num;            /*!< malloced original callerid */
00516    char *origcid_name;           /*!< malloced original callerid */
00517    char callwait_num[AST_MAX_EXTENSION];
00518    char callwait_name[AST_MAX_EXTENSION];
00519    char rdnis[AST_MAX_EXTENSION];
00520    char dnid[AST_MAX_EXTENSION];
00521    ast_group_t group;
00522    int law;
00523    int confno;             /*!< Our conference */
00524    int confusers;             /*!< Who is using our conference */
00525    int propconfno;               /*!< Propagated conference number */
00526    ast_group_t callgroup;
00527    ast_group_t pickupgroup;
00528    int channel;               /*!< Channel Number or CRV */
00529    int span;               /*!< Span number */
00530    time_t guardtime;          /*!< Must wait this much time before using for new call */
00531    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00532    int cid_start;             /*!< CID start indicator, polarity or ring */
00533    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00534    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00535    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00536    unsigned char *cidspill;
00537    int cidpos;
00538    int cidlen;
00539    int ringt;
00540    int ringt_base;
00541    int stripmsd;
00542    int callwaitcas;
00543    int callwaitrings;
00544    int echocancel;
00545    int echotraining;
00546    char echorest[20];
00547    int busycount;
00548    int busycompare;
00549    int busytonelength;
00550    int busyquietlength;
00551    int busyfuzziness;
00552    int silencethreshold;
00553    int callprogress;
00554    struct timeval flashtime;        /*!< Last flash-hook time */
00555    struct ast_dsp *dsp;
00556    int cref;               /*!< Call reference number */
00557    struct dahdi_dialoperation dop;
00558    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00559    char finaldial[64];
00560    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00561    int amaflags;              /*!< AMA Flags */
00562    struct tdd_state *tdd;           /*!< TDD flag */
00563    char call_forward[AST_MAX_EXTENSION];
00564    char mailbox[AST_MAX_EXTENSION];
00565    char dialdest[256];
00566    int onhooktime;
00567    int msgstate;
00568    int distinctivering;          /*!< Which distinctivering to use */
00569    int cidrings;              /*!< Which ring to deliver CID on */
00570    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00571    int fake_event;
00572    int polarityonanswerdelay;
00573    struct timeval polaritydelaytv;
00574    int sendcalleridafter;
00575 #ifdef HAVE_PRI
00576    struct dahdi_pri *pri;
00577    struct dahdi_pvt *bearer;
00578    struct dahdi_pvt *realcall;
00579    q931_call *call;
00580    int prioffset;
00581    int logicalspan;
00582 #endif   
00583    int polarity;
00584    int dsp_features;
00585    char begindigit;
00586 } *iflist = NULL, *ifend = NULL;
00587 
00588 /*! \brief Channel configuration from chan_dahdi.conf .
00589  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00590  * Generally there is a field here for every possible configuration item.
00591  *
00592  * The state of fields is saved along the parsing and whenever a 'channel'
00593  * statement is reached, the current dahdi_chan_conf is used to configure the 
00594  * channel (struct dahdi_pvt)
00595  *
00596  * @seealso dahdi_chan_init for the default values.
00597  */
00598 struct dahdi_chan_conf {
00599    struct dahdi_pvt chan;
00600 #ifdef HAVE_PRI
00601    struct dahdi_pri pri;
00602 #endif
00603    struct dahdi_params timing;
00604 
00605    char smdi_port[SMDI_MAX_FILENAME_LEN];
00606 };
00607 
00608 /** returns a new dahdi_chan_conf with default values (by-value) */
00609 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00610    /* recall that if a field is not included here it is initialized
00611     * to 0 or equivalent
00612     */
00613    struct dahdi_chan_conf conf = {
00614 #ifdef HAVE_PRI
00615       .pri = {
00616          .nsf = PRI_NSF_NONE,
00617          .switchtype = PRI_SWITCH_NI2,
00618          .dialplan = PRI_NATIONAL_ISDN + 1,
00619          .localdialplan = PRI_NATIONAL_ISDN + 1,
00620          .nodetype = PRI_CPE,
00621 
00622          .minunused = 2,
00623          .idleext = "",
00624          .idledial = "",
00625          .internationalprefix = "",
00626          .nationalprefix = "",
00627          .localprefix = "",
00628          .privateprefix = "",
00629          .unknownprefix = "",
00630 
00631          .resetinterval = 3600
00632       },
00633 #endif
00634       .chan = {
00635          .context = "default",
00636          .cid_num = "",
00637          .cid_name = "",
00638          .mohinterpret = "default",
00639          .mohsuggest = "",
00640          .transfertobusy = 1,
00641 
00642          .cid_signalling = CID_SIG_BELL,
00643          .cid_start = CID_START_RING,
00644          .dahditrcallerid = 0,
00645          .use_callerid = 1,
00646          .sig = -1,
00647          .outsigmod = -1,
00648 
00649          .tonezone = -1,
00650 
00651          .echocancel = 1,
00652 
00653          .busycount = 3,
00654          .busycompare = 0,
00655          .busytonelength = 0,
00656          .busyquietlength = 0,
00657          .busyfuzziness = 0,
00658          .silencethreshold = 0,
00659 
00660          .accountcode = "",
00661 
00662          .mailbox = "",
00663 
00664 
00665          .polarityonanswerdelay = 600,
00666 
00667          .sendcalleridafter = DEFAULT_CIDRINGS,
00668 
00669          .buf_policy = DAHDI_POLICY_IMMEDIATE,
00670          .buf_no = numbufs
00671       },
00672       .timing = {
00673          .prewinktime = -1,
00674          .preflashtime = -1,
00675          .winktime = -1,
00676          .flashtime = -1,
00677          .starttime = -1,
00678          .rxwinktime = -1,
00679          .rxflashtime = -1,
00680          .debouncetime = -1
00681       },
00682       .smdi_port = "/dev/ttyS0",
00683    };
00684 
00685    return conf;
00686 }
00687 
00688 
00689 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
00690 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
00691 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00692 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00693 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
00694 static int dahdi_hangup(struct ast_channel *ast);
00695 static int dahdi_answer(struct ast_channel *ast);
00696 static struct ast_frame *dahdi_read(struct ast_channel *ast);
00697 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
00698 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
00699 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
00700 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00701 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
00702 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
00703 
00704 static const struct ast_channel_tech dahdi_tech = {
00705    .type = "DAHDI",
00706    .description = tdesc,
00707    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00708    .requester = dahdi_request,
00709    .send_digit_begin = dahdi_digit_begin,
00710    .send_digit_end = dahdi_digit_end,
00711    .send_text = dahdi_sendtext,
00712    .call = dahdi_call,
00713    .hangup = dahdi_hangup,
00714    .answer = dahdi_answer,
00715    .read = dahdi_read,
00716    .write = dahdi_write,
00717    .bridge = dahdi_bridge,
00718    .exception = dahdi_exception,
00719    .indicate = dahdi_indicate,
00720    .fixup = dahdi_fixup,
00721    .setoption = dahdi_setoption,
00722    .func_channel_read = dahdi_func_read,
00723 };
00724 
00725 static const struct ast_channel_tech zap_tech = {
00726    .type = "Zap",
00727    .description = tdesc,
00728    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00729    .requester = dahdi_request,
00730    .send_digit_begin = dahdi_digit_begin,
00731    .send_digit_end = dahdi_digit_end,
00732    .send_text = dahdi_sendtext,
00733    .call = dahdi_call,
00734    .hangup = dahdi_hangup,
00735    .answer = dahdi_answer,
00736    .read = dahdi_read,
00737    .write = dahdi_write,
00738    .bridge = dahdi_bridge,
00739    .exception = dahdi_exception,
00740    .indicate = dahdi_indicate,
00741    .fixup = dahdi_fixup,
00742    .setoption = dahdi_setoption,
00743    .func_channel_read = dahdi_func_read,
00744 };
00745 
00746 static const struct ast_channel_tech *chan_tech;
00747 
00748 #ifdef HAVE_PRI
00749 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
00750 #else
00751 #define GET_CHANNEL(p) ((p)->channel)
00752 #endif
00753 
00754 struct dahdi_pvt *round_robin[32];
00755 
00756 #ifdef HAVE_PRI
00757 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
00758 {
00759    int res;
00760    /* Grab the lock first */
00761    do {
00762       res = ast_mutex_trylock(&pri->lock);
00763       if (res) {
00764          DEADLOCK_AVOIDANCE(&pvt->lock);
00765       }
00766    } while (res);
00767    /* Then break the poll */
00768    if (pri->master != AST_PTHREADT_NULL)
00769       pthread_kill(pri->master, SIGURG);
00770    return 0;
00771 }
00772 #endif
00773 
00774 #define NUM_CADENCE_MAX 25
00775 static int num_cadence = 4;
00776 static int user_has_defined_cadences = 0;
00777 
00778 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00779    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00780    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00781    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00782    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00783 };
00784 
00785 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00786  * is 1, the second pause is 2 and so on.
00787  */
00788 
00789 static int cidrings[NUM_CADENCE_MAX] = {
00790    2,                            /*!< Right after first long ring */
00791    4,                            /*!< Right after long part */
00792    3,                            /*!< After third chirp */
00793    2,                            /*!< Second spell */
00794 };
00795 
00796 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00797          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00798 
00799 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00800 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00801 
00802 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
00803 {
00804    int res;
00805    if (p->subs[SUB_REAL].owner == ast)
00806       res = 0;
00807    else if (p->subs[SUB_CALLWAIT].owner == ast)
00808       res = 1;
00809    else if (p->subs[SUB_THREEWAY].owner == ast)
00810       res = 2;
00811    else {
00812       res = -1;
00813       if (!nullok)
00814          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00815    }
00816    return res;
00817 }
00818 
00819 #ifdef HAVE_PRI
00820 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
00821 #else
00822 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
00823 #endif
00824 {
00825 #ifdef HAVE_PRI
00826    if (pri)
00827       ast_mutex_unlock(&pri->lock);
00828 #endif         
00829    for (;;) {
00830       if (p->subs[a].owner) {
00831          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00832             DEADLOCK_AVOIDANCE(&p->lock);
00833          } else {
00834             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00835             ast_mutex_unlock(&p->subs[a].owner->lock);
00836             break;
00837          }
00838       } else
00839          break;
00840    }
00841 #ifdef HAVE_PRI
00842    if (pri)
00843       ast_mutex_lock(&pri->lock);
00844 #endif         
00845 }
00846 
00847 #ifdef HAVE_PRI
00848 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
00849 #else
00850 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
00851 #endif
00852 {
00853    /* We must unlock the PRI to avoid the possibility of a deadlock */
00854 #ifdef HAVE_PRI
00855    if (pri)
00856       ast_mutex_unlock(&pri->lock);
00857 #endif      
00858    for (;;) {
00859       if (p->owner) {
00860          if (ast_mutex_trylock(&p->owner->lock)) {
00861             DEADLOCK_AVOIDANCE(&p->lock);
00862          } else {
00863             ast_queue_frame(p->owner, f);
00864             ast_mutex_unlock(&p->owner->lock);
00865             break;
00866          }
00867       } else
00868          break;
00869    }
00870 #ifdef HAVE_PRI
00871    if (pri)
00872       ast_mutex_lock(&pri->lock);
00873 #endif      
00874 }
00875 
00876 static int restore_gains(struct dahdi_pvt *p);
00877 
00878 static void swap_subs(struct dahdi_pvt *p, int a, int b)
00879 {
00880    int tchan;
00881    int tinthreeway;
00882    struct ast_channel *towner;
00883 
00884    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00885 
00886    tchan = p->subs[a].chan;
00887    towner = p->subs[a].owner;
00888    tinthreeway = p->subs[a].inthreeway;
00889 
00890    p->subs[a].chan = p->subs[b].chan;
00891    p->subs[a].owner = p->subs[b].owner;
00892    p->subs[a].inthreeway = p->subs[b].inthreeway;
00893 
00894    p->subs[b].chan = tchan;
00895    p->subs[b].owner = towner;
00896    p->subs[b].inthreeway = tinthreeway;
00897 
00898    if (p->subs[a].owner) 
00899       p->subs[a].owner->fds[0] = p->subs[a].dfd;
00900    if (p->subs[b].owner) 
00901       p->subs[b].owner->fds[0] = p->subs[b].dfd;
00902    wakeup_sub(p, a, NULL);
00903    wakeup_sub(p, b, NULL);
00904 }
00905 
00906 static int dahdi_open(char *fn)
00907 {
00908    int fd;
00909    int isnum;
00910    int chan = 0;
00911    int bs;
00912    int x;
00913    isnum = 1;
00914    for (x = 0; x < strlen(fn); x++) {
00915       if (!isdigit(fn[x])) {
00916          isnum = 0;
00917          break;
00918       }
00919    }
00920    if (isnum) {
00921       chan = atoi(fn);
00922       if (chan < 1) {
00923          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00924          return -1;
00925       }
00926       fn = DAHDI_FILE_CHANNEL;
00927    }
00928    fd = open(fn, O_RDWR | O_NONBLOCK);
00929    if (fd < 0) {
00930       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00931       return -1;
00932    }
00933    if (chan) {
00934       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
00935          x = errno;
00936          close(fd);
00937          errno = x;
00938          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00939          return -1;
00940       }
00941    }
00942    bs = READ_SIZE;
00943    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
00944       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
00945       x = errno;
00946       close(fd);
00947       errno = x;
00948       return -1;
00949    }
00950    return fd;
00951 }
00952 
00953 static void dahdi_close(int fd)
00954 {
00955    if (fd > 0)
00956       close(fd);
00957 }
00958 
00959 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
00960 {
00961    dahdi_close(chan_pvt->subs[sub_num].dfd);
00962    chan_pvt->subs[sub_num].dfd = -1;
00963 }
00964  
00965 #ifdef HAVE_PRI
00966 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
00967 {
00968    dahdi_close(pri->fds[fd_num]);
00969    pri->fds[fd_num] = -1;
00970 }
00971 #endif
00972 
00973 static int dahdi_setlinear(int dfd, int linear)
00974 {
00975    int res;
00976    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
00977    if (res)
00978       return res;
00979    return 0;
00980 }
00981 
00982 
00983 static int alloc_sub(struct dahdi_pvt *p, int x)
00984 {
00985    struct dahdi_bufferinfo bi;
00986    int res;
00987    if (p->subs[x].dfd < 0) {
00988       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
00989       if (p->subs[x].dfd > -1) {
00990          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
00991          if (!res) {
00992             bi.txbufpolicy = p->buf_policy;
00993             bi.rxbufpolicy = p->buf_policy;
00994             bi.numbufs = p->buf_no;
00995             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
00996             if (res < 0) {
00997                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
00998             }
00999          } else 
01000             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01001          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01002             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01003             dahdi_close_sub(p, x);
01004             return -1;
01005          }
01006          if (option_debug)
01007             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01008          return 0;
01009       } else
01010          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01011       return -1;
01012    }
01013    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01014    return -1;
01015 }
01016 
01017 static int unalloc_sub(struct dahdi_pvt *p, int x)
01018 {
01019    if (!x) {
01020       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01021       return -1;
01022    }
01023    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01024    dahdi_close_sub(p, x);
01025    p->subs[x].linear = 0;
01026    p->subs[x].chan = 0;
01027    p->subs[x].owner = NULL;
01028    p->subs[x].inthreeway = 0;
01029    p->polarity = POLARITY_IDLE;
01030    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01031    return 0;
01032 }
01033 
01034 static int digit_to_dtmfindex(char digit)
01035 {
01036    if (isdigit(digit))
01037       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01038    else if (digit >= 'A' && digit <= 'D')
01039       return DAHDI_TONE_DTMF_A + (digit - 'A');
01040    else if (digit >= 'a' && digit <= 'd')
01041       return DAHDI_TONE_DTMF_A + (digit - 'a');
01042    else if (digit == '*')
01043       return DAHDI_TONE_DTMF_s;
01044    else if (digit == '#')
01045       return DAHDI_TONE_DTMF_p;
01046    else
01047       return -1;
01048 }
01049 
01050 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01051 {
01052    struct dahdi_pvt *pvt;
01053    int index;
01054    int dtmf = -1;
01055    
01056    pvt = chan->tech_pvt;
01057 
01058    ast_mutex_lock(&pvt->lock);
01059 
01060    index = dahdi_get_index(chan, pvt, 0);
01061 
01062    if ((index != SUB_REAL) || !pvt->owner)
01063       goto out;
01064 
01065 #ifdef HAVE_PRI
01066    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01067       if (pvt->setup_ack) {
01068          if (!pri_grab(pvt, pvt->pri)) {
01069             pri_information(pvt->pri->pri, pvt->call, digit);
01070             pri_rel(pvt->pri);
01071          } else
01072             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01073       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01074          int res;
01075          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01076          res = strlen(pvt->dialdest);
01077          pvt->dialdest[res++] = digit;
01078          pvt->dialdest[res] = '\0';
01079       }
01080       goto out;
01081    }
01082 #endif
01083    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01084       goto out;
01085 
01086    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01087       int res;
01088       struct dahdi_dialoperation zo = {
01089          .op = DAHDI_DIAL_OP_APPEND,
01090          .dialstr[0] = 'T',
01091          .dialstr[1] = digit,
01092          .dialstr[2] = 0,
01093       };
01094       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01095          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01096       else
01097          pvt->dialing = 1;
01098    } else {
01099       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01100       pvt->dialing = 1;
01101       pvt->begindigit = digit;
01102    }
01103 
01104 out:
01105    ast_mutex_unlock(&pvt->lock);
01106 
01107    return 0;
01108 }
01109 
01110 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01111 {
01112    struct dahdi_pvt *pvt;
01113    int res = 0;
01114    int index;
01115    int x;
01116    
01117    pvt = chan->tech_pvt;
01118 
01119    ast_mutex_lock(&pvt->lock);
01120    
01121    index = dahdi_get_index(chan, pvt, 0);
01122 
01123    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01124       goto out;
01125 
01126 #ifdef HAVE_PRI
01127    /* This means that the digit was already sent via PRI signalling */
01128    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01129       goto out;
01130 #endif
01131 
01132    if (pvt->begindigit) {
01133       x = -1;
01134       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01135       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01136       pvt->dialing = 0;
01137       pvt->begindigit = 0;
01138    }
01139 
01140 out:
01141    ast_mutex_unlock(&pvt->lock);
01142 
01143    return res;
01144 }
01145 
01146 static char *events[] = {
01147    "No event",
01148    "On hook",
01149    "Ring/Answered",
01150    "Wink/Flash",
01151    "Alarm",
01152    "No more alarm",
01153    "HDLC Abort",
01154    "HDLC Overrun",
01155    "HDLC Bad FCS",
01156    "Dial Complete",
01157    "Ringer On",
01158    "Ringer Off",
01159    "Hook Transition Complete",
01160    "Bits Changed",
01161    "Pulse Start",
01162    "Timer Expired",
01163    "Timer Ping",
01164    "Polarity Reversal",
01165    "Ring Begin",
01166 };
01167 
01168 static struct {
01169    int alarm;
01170    char *name;
01171 } alarms[] = {
01172    { DAHDI_ALARM_RED, "Red Alarm" },
01173    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01174    { DAHDI_ALARM_BLUE, "Blue Alarm" },
01175    { DAHDI_ALARM_RECOVER, "Recovering" },
01176    { DAHDI_ALARM_LOOPBACK, "Loopback" },
01177    { DAHDI_ALARM_NOTOPEN, "Not Open" },
01178    { DAHDI_ALARM_NONE, "None" },
01179 };
01180 
01181 static char *alarm2str(int alarm)
01182 {
01183    int x;
01184    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01185       if (alarms[x].alarm & alarm)
01186          return alarms[x].name;
01187    }
01188    return alarm ? "Unknown Alarm" : "No Alarm";
01189 }
01190 
01191 static char *event2str(int event)
01192 {
01193    static char buf[256];
01194    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01195       return events[event];
01196    sprintf(buf, "Event %d", event); /* safe */
01197    return buf;
01198 }
01199 
01200 #ifdef HAVE_PRI
01201 static char *dialplan2str(int dialplan)
01202 {
01203    if (dialplan == -1) {
01204       return("Dynamically set dialplan in ISDN");
01205    }
01206    return (pri_plan2str(dialplan));
01207 }
01208 #endif
01209 
01210 static char *dahdi_sig2str(int sig)
01211 {
01212    static char buf[256];
01213    switch (sig) {
01214    case SIG_EM:
01215       return "E & M Immediate";
01216    case SIG_EMWINK:
01217       return "E & M Wink";
01218    case SIG_EM_E1:
01219       return "E & M E1";
01220    case SIG_FEATD:
01221       return "Feature Group D (DTMF)";
01222    case SIG_FEATDMF:
01223       return "Feature Group D (MF)";
01224    case SIG_FEATDMF_TA:
01225       return "Feature Groud D (MF) Tandem Access";
01226    case SIG_FEATB:
01227       return "Feature Group B (MF)";
01228    case SIG_E911:
01229       return "E911 (MF)";
01230    case SIG_FGC_CAMA:
01231       return "FGC/CAMA (Dialpulse)";
01232    case SIG_FGC_CAMAMF:
01233       return "FGC/CAMA (MF)";
01234    case SIG_FXSLS:
01235       return "FXS Loopstart";
01236    case SIG_FXSGS:
01237       return "FXS Groundstart";
01238    case SIG_FXSKS:
01239       return "FXS Kewlstart";
01240    case SIG_FXOLS:
01241       return "FXO Loopstart";
01242    case SIG_FXOGS:
01243       return "FXO Groundstart";
01244    case SIG_FXOKS:
01245       return "FXO Kewlstart";
01246    case SIG_PRI:
01247       return "ISDN PRI";
01248    case SIG_SF:
01249       return "SF (Tone) Immediate";
01250    case SIG_SFWINK:
01251       return "SF (Tone) Wink";
01252    case SIG_SF_FEATD:
01253       return "SF (Tone) with Feature Group D (DTMF)";
01254    case SIG_SF_FEATDMF:
01255       return "SF (Tone) with Feature Group D (MF)";
01256    case SIG_SF_FEATB:
01257       return "SF (Tone) with Feature Group B (MF)";
01258    case SIG_GR303FXOKS:
01259       return "GR-303 with FXOKS";
01260    case SIG_GR303FXSKS:
01261       return "GR-303 with FXSKS";
01262    case 0:
01263       return "Pseudo";
01264    default:
01265       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01266       return buf;
01267    }
01268 }
01269 
01270 #define sig2str dahdi_sig2str
01271 
01272 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01273 {
01274    /* If the conference already exists, and we're already in it
01275       don't bother doing anything */
01276    struct dahdi_confinfo zi;
01277    
01278    memset(&zi, 0, sizeof(zi));
01279    zi.chan = 0;
01280 
01281    if (slavechannel > 0) {
01282       /* If we have only one slave, do a digital mon */
01283       zi.confmode = DAHDI_CONF_DIGITALMON;
01284       zi.confno = slavechannel;
01285    } else {
01286       if (!index) {
01287          /* Real-side and pseudo-side both participate in conference */
01288          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01289             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01290       } else
01291          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01292       zi.confno = p->confno;
01293    }
01294    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01295       return 0;
01296    if (c->dfd < 0)
01297       return 0;
01298    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01299       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01300       return -1;
01301    }
01302    if (slavechannel < 1) {
01303       p->confno = zi.confno;
01304    }
01305    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01306    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01307    return 0;
01308 }
01309 
01310 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01311 {
01312    /* If they're listening to our channel, they're ours */  
01313    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01314       return 1;
01315    /* If they're a talker on our (allocated) conference, they're ours */
01316    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01317       return 1;
01318    return 0;
01319 }
01320 
01321 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01322 {
01323    struct dahdi_confinfo zi;
01324    if (/* Can't delete if there's no dfd */
01325       (c->dfd < 0) ||
01326       /* Don't delete from the conference if it's not our conference */
01327       !isourconf(p, c)
01328       /* Don't delete if we don't think it's conferenced at all (implied) */
01329       ) return 0;
01330    memset(&zi, 0, sizeof(zi));
01331    zi.chan = 0;
01332    zi.confno = 0;
01333    zi.confmode = 0;
01334    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01335       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01336       return -1;
01337    }
01338    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01339    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01340    return 0;
01341 }
01342 
01343 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01344 {
01345    int x;
01346    int useslavenative;
01347    struct dahdi_pvt *slave = NULL;
01348    /* Start out optimistic */
01349    useslavenative = 1;
01350    /* Update conference state in a stateless fashion */
01351    for (x = 0; x < 3; x++) {
01352       /* Any three-way calling makes slave native mode *definitely* out
01353          of the question */
01354       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01355          useslavenative = 0;
01356    }
01357    /* If we don't have any 3-way calls, check to see if we have
01358       precisely one slave */
01359    if (useslavenative) {
01360       for (x = 0; x < MAX_SLAVES; x++) {
01361          if (p->slaves[x]) {
01362             if (slave) {
01363                /* Whoops already have a slave!  No 
01364                   slave native and stop right away */
01365                slave = NULL;
01366                useslavenative = 0;
01367                break;
01368             } else {
01369                /* We have one slave so far */
01370                slave = p->slaves[x];
01371             }
01372          }
01373       }
01374    }
01375    /* If no slave, slave native definitely out */
01376    if (!slave)
01377       useslavenative = 0;
01378    else if (slave->law != p->law) {
01379       useslavenative = 0;
01380       slave = NULL;
01381    }
01382    if (out)
01383       *out = slave;
01384    return useslavenative;
01385 }
01386 
01387 static int reset_conf(struct dahdi_pvt *p)
01388 {
01389    struct dahdi_confinfo zi;
01390    memset(&zi, 0, sizeof(zi));
01391    p->confno = -1;
01392    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01393    if (p->subs[SUB_REAL].dfd > -1) {
01394       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01395          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01396    }
01397    return 0;
01398 }
01399 
01400 static int update_conf(struct dahdi_pvt *p)
01401 {
01402    int needconf = 0;
01403    int x;
01404    int useslavenative;
01405    struct dahdi_pvt *slave = NULL;
01406 
01407    useslavenative = isslavenative(p, &slave);
01408    /* Start with the obvious, general stuff */
01409    for (x = 0; x < 3; x++) {
01410       /* Look for three way calls */
01411       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01412          conf_add(p, &p->subs[x], x, 0);
01413          needconf++;
01414       } else {
01415          conf_del(p, &p->subs[x], x);
01416       }
01417    }
01418    /* If we have a slave, add him to our conference now. or DAX
01419       if this is slave native */
01420    for (x = 0; x < MAX_SLAVES; x++) {
01421       if (p->slaves[x]) {
01422          if (useslavenative)
01423             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01424          else {
01425             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01426             needconf++;
01427          }
01428       }
01429    }
01430    /* If we're supposed to be in there, do so now */
01431    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01432       if (useslavenative)
01433          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01434       else {
01435          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01436          needconf++;
01437       }
01438    }
01439    /* If we have a master, add ourselves to his conference */
01440    if (p->master) {
01441       if (isslavenative(p->master, NULL)) {
01442          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01443       } else {
01444          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01445       }
01446    }
01447    if (!needconf) {
01448       /* Nobody is left (or should be left) in our conference.
01449          Kill it. */
01450       p->confno = -1;
01451    }
01452    if (option_debug)
01453       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01454    return 0;
01455 }
01456 
01457 static void dahdi_enable_ec(struct dahdi_pvt *p)
01458 {
01459    int x;
01460    int res;
01461    if (!p)
01462       return;
01463    if (p->echocanon) {
01464       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01465       return;
01466    }
01467    if (p->digital) {
01468       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01469       return;
01470    }
01471    if (p->echocancel) {
01472       if (p->sig == SIG_PRI) {
01473          x = 1;
01474          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01475          if (res)
01476             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01477       }
01478       x = p->echocancel;
01479       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01480       if (res) 
01481          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01482       else {
01483          p->echocanon = 1;
01484          if (option_debug)
01485             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01486       }
01487    } else if (option_debug)
01488       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01489 }
01490 
01491 static void dahdi_train_ec(struct dahdi_pvt *p)
01492 {
01493    int x;
01494    int res;
01495    if (p && p->echocancel && p->echotraining) {
01496       x = p->echotraining;
01497       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01498       if (res)
01499          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01500       else {
01501          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01502       }
01503    } else
01504       ast_log(LOG_DEBUG, "No echo training requested\n");
01505 }
01506 
01507 static void dahdi_disable_ec(struct dahdi_pvt *p)
01508 {
01509    int x;
01510    int res;
01511    if (p->echocancel) {
01512       x = 0;
01513       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01514       if (res)
01515          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01516       else if (option_debug)
01517          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01518    }
01519    p->echocanon = 0;
01520 }
01521 
01522 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01523 {
01524    int j;
01525    int k;
01526    float linear_gain = pow(10.0, gain / 20.0);
01527 
01528    switch (law) {
01529    case DAHDI_LAW_ALAW:
01530       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01531          if (gain) {
01532             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01533             if (k > 32767) k = 32767;
01534             if (k < -32767) k = -32767;
01535             g->txgain[j] = AST_LIN2A(k);
01536          } else {
01537             g->txgain[j] = j;
01538          }
01539       }
01540       break;
01541    case DAHDI_LAW_MULAW:
01542       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01543          if (gain) {
01544             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01545             if (k > 32767) k = 32767;
01546             if (k < -32767) k = -32767;
01547             g->txgain[j] = AST_LIN2MU(k);
01548          } else {
01549             g->txgain[j] = j;
01550          }
01551       }
01552       break;
01553    }
01554 }
01555 
01556 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01557 {
01558    int j;
01559    int k;
01560    float linear_gain = pow(10.0, gain / 20.0);
01561 
01562    switch (law) {
01563    case DAHDI_LAW_ALAW:
01564       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01565          if (gain) {
01566             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01567             if (k > 32767) k = 32767;
01568             if (k < -32767) k = -32767;
01569             g->rxgain[j] = AST_LIN2A(k);
01570          } else {
01571             g->rxgain[j] = j;
01572          }
01573       }
01574       break;
01575    case DAHDI_LAW_MULAW:
01576       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01577          if (gain) {
01578             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01579             if (k > 32767) k = 32767;
01580             if (k < -32767) k = -32767;
01581             g->rxgain[j] = AST_LIN2MU(k);
01582          } else {
01583             g->rxgain[j] = j;
01584          }
01585       }
01586       break;
01587    }
01588 }
01589 
01590 static int set_actual_txgain(int fd, int chan, float gain, int law)
01591 {
01592    struct dahdi_gains g;
01593    int res;
01594 
01595    memset(&g, 0, sizeof(g));
01596    g.chan = chan;
01597    res = ioctl(fd, DAHDI_GETGAINS, &g);
01598    if (res) {
01599       if (option_debug)
01600          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01601       return res;
01602    }
01603 
01604    fill_txgain(&g, gain, law);
01605 
01606    return ioctl(fd, DAHDI_SETGAINS, &g);
01607 }
01608 
01609 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01610 {
01611    struct dahdi_gains g;
01612    int res;
01613 
01614    memset(&g, 0, sizeof(g));
01615    g.chan = chan;
01616    res = ioctl(fd, DAHDI_GETGAINS, &g);
01617    if (res) {
01618       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01619       return res;
01620    }
01621 
01622    fill_rxgain(&g, gain, law);
01623 
01624    return ioctl(fd, DAHDI_SETGAINS, &g);
01625 }
01626 
01627 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01628 {
01629    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01630 }
01631 
01632 static int bump_gains(struct dahdi_pvt *p)
01633 {
01634    int res;
01635 
01636    /* Bump receive gain by 5.0db */
01637    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01638    if (res) {
01639       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01640       return -1;
01641    }
01642 
01643    return 0;
01644 }
01645 
01646 static int restore_gains(struct dahdi_pvt *p)
01647 {
01648    int res;
01649 
01650    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01651    if (res) {
01652       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01653       return -1;
01654    }
01655 
01656    return 0;
01657 }
01658 
01659 static inline int dahdi_set_hook(int fd, int hs)
01660 {
01661    int x, res;
01662 
01663    x = hs;
01664    res = ioctl(fd, DAHDI_HOOK, &x);
01665 
01666    if (res < 0) {
01667       if (errno == EINPROGRESS)
01668          return 0;
01669       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01670       /* will expectedly fail if phone is off hook during operation, such as during a restart */
01671    }
01672 
01673    return res;
01674 }
01675 
01676 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01677 {
01678    int x, y, res;
01679    x = muted;
01680    if (p->sig == SIG_PRI) {
01681       y = 1;
01682       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01683       if (res)
01684          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01685    }
01686    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
01687    if (res < 0)
01688       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01689    return res;
01690 }
01691 
01692 static int save_conference(struct dahdi_pvt *p)
01693 {
01694    struct dahdi_confinfo c;
01695    int res;
01696    if (p->saveconf.confmode) {
01697       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01698       return -1;
01699    }
01700    p->saveconf.chan = 0;
01701    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
01702    if (res) {
01703       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01704       p->saveconf.confmode = 0;
01705       return -1;
01706    }
01707    c.chan = 0;
01708    c.confno = 0;
01709    c.confmode = DAHDI_CONF_NORMAL;
01710    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
01711    if (res) {
01712       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01713       return -1;
01714    }
01715    if (option_debug)
01716       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01717    return 0;
01718 }
01719 
01720 static int restore_conference(struct dahdi_pvt *p)
01721 {
01722    int res;
01723    if (p->saveconf.confmode) {
01724       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
01725       p->saveconf.confmode = 0;
01726       if (res) {
01727          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01728          return -1;
01729       }
01730    }
01731    if (option_debug)
01732       ast_log(LOG_DEBUG, "Restored conferencing\n");
01733    return 0;
01734 }
01735 
01736 static int send_callerid(struct dahdi_pvt *p);
01737 
01738 static int send_cwcidspill(struct dahdi_pvt *p)
01739 {
01740    p->callwaitcas = 0;
01741    p->cidcwexpire = 0;
01742    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01743       return -1;
01744    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01745    /* Make sure we account for the end */
01746    p->cidlen += READ_SIZE * 4;
01747    p->cidpos = 0;
01748    send_callerid(p);
01749    if (option_verbose > 2)
01750       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01751    return 0;
01752 }
01753 
01754 static int has_voicemail(struct dahdi_pvt *p)
01755 {
01756 
01757    return ast_app_has_voicemail(p->mailbox, NULL);
01758 }
01759 
01760 static int send_callerid(struct dahdi_pvt *p)
01761 {
01762    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01763    int res;
01764    /* Take out of linear mode if necessary */
01765    if (p->subs[SUB_REAL].linear) {
01766       p->subs[SUB_REAL].linear = 0;
01767       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
01768    }
01769    while (p->cidpos < p->cidlen) {
01770       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01771       if (res < 0) {
01772          if (errno == EAGAIN)
01773             return 0;
01774          else {
01775             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01776             return -1;
01777          }
01778       }
01779       if (!res)
01780          return 0;
01781       p->cidpos += res;
01782    }
01783    free(p->cidspill);
01784    p->cidspill = NULL;
01785    if (p->callwaitcas) {
01786       /* Wait for CID/CW to expire */
01787       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01788    } else
01789       restore_conference(p);
01790    return 0;
01791 }
01792 
01793 static int dahdi_callwait(struct ast_channel *ast)
01794 {
01795    struct dahdi_pvt *p = ast->tech_pvt;
01796    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01797    if (p->cidspill) {
01798       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01799       free(p->cidspill);
01800    }
01801    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01802       return -1;
01803    save_conference(p);
01804    /* Silence */
01805    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01806    if (!p->callwaitrings && p->callwaitingcallerid) {
01807       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01808       p->callwaitcas = 1;
01809       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01810    } else {
01811       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01812       p->callwaitcas = 0;
01813       p->cidlen = 2400 + READ_SIZE * 4;
01814    }
01815    p->cidpos = 0;
01816    send_callerid(p);
01817    
01818    return 0;
01819 }
01820 
01821 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
01822 {
01823    struct dahdi_pvt *p = ast->tech_pvt;
01824    int x, res, index,mysig;
01825    char *c, *n, *l;
01826 #ifdef HAVE_PRI
01827    char *s = NULL;
01828 #endif
01829    char dest[256]; /* must be same length as p->dialdest */
01830    ast_mutex_lock(&p->lock);
01831    ast_copy_string(dest, rdest, sizeof(dest));
01832    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01833    if ((ast->_state == AST_STATE_BUSY)) {
01834       p->subs[SUB_REAL].needbusy = 1;
01835       ast_mutex_unlock(&p->lock);
01836       return 0;
01837    }
01838    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01839       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
01840       ast_mutex_unlock(&p->lock);
01841       return -1;
01842    }
01843    p->dialednone = 0;
01844    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
01845    {
01846       /* Special pseudo -- automatically up */
01847       ast_setstate(ast, AST_STATE_UP); 
01848       ast_mutex_unlock(&p->lock);
01849       return 0;
01850    }
01851    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
01852    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
01853    if (res)
01854       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
01855    p->outgoing = 1;
01856 
01857    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01858 
01859    mysig = p->sig;
01860    if (p->outsigmod > -1)
01861       mysig = p->outsigmod;
01862 
01863    switch (mysig) {
01864    case SIG_FXOLS:
01865    case SIG_FXOGS:
01866    case SIG_FXOKS:
01867       if (p->owner == ast) {
01868          /* Normal ring, on hook */
01869          
01870          /* Don't send audio while on hook, until the call is answered */
01871          p->dialing = 1;
01872          if (p->use_callerid) {
01873             /* Generate the Caller-ID spill if desired */
01874             if (p->cidspill) {
01875                ast_log(LOG_WARNING, "cidspill already exists??\n");
01876                free(p->cidspill);
01877             }
01878             p->callwaitcas = 0;
01879             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01880                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01881                p->cidpos = 0;
01882                send_callerid(p);
01883             }
01884          }
01885          /* Choose proper cadence */
01886          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01887             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01888                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
01889             p->cidrings = cidrings[p->distinctivering - 1];
01890          } else {
01891             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01892                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
01893             p->cidrings = p->sendcalleridafter;
01894          }
01895 
01896          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
01897          c = strchr(dest, '/');
01898          if (c)
01899             c++;
01900          if (c && (strlen(c) < p->stripmsd)) {
01901             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01902             c = NULL;
01903          }
01904          if (c) {
01905             p->dop.op = DAHDI_DIAL_OP_REPLACE;
01906             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01907             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01908          } else {
01909             p->dop.dialstr[0] = '\0';
01910          }
01911          x = DAHDI_RING;
01912          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
01913             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01914             ast_mutex_unlock(&p->lock);
01915             return -1;
01916          }
01917          p->dialing = 1;
01918       } else {
01919          /* Call waiting call */
01920          p->callwaitrings = 0;
01921          if (ast->cid.cid_num)
01922             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01923          else
01924             p->callwait_num[0] = '\0';
01925          if (ast->cid.cid_name)
01926             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01927          else
01928             p->callwait_name[0] = '\0';
01929          /* Call waiting tone instead */
01930          if (dahdi_callwait(ast)) {
01931             ast_mutex_unlock(&p->lock);
01932             return -1;
01933          }
01934          /* Make ring-back */
01935          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
01936             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01937             
01938       }
01939       n = ast->cid.cid_name;
01940       l = ast->cid.cid_num;
01941       if (l)
01942          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01943       else
01944          p->lastcid_num[0] = '\0';
01945       if (n)
01946          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01947       else
01948          p->lastcid_name[0] = '\0';
01949       ast_setstate(ast, AST_STATE_RINGING);
01950       index = dahdi_get_index(ast, p, 0);
01951       if (index > -1) {
01952          p->subs[index].needringing = 1;
01953       }
01954       break;
01955    case SIG_FXSLS:
01956    case SIG_FXSGS:
01957    case SIG_FXSKS:
01958    case SIG_EMWINK:
01959    case SIG_EM:
01960    case SIG_EM_E1:
01961    case SIG_FEATD:
01962    case SIG_FEATDMF:
01963    case SIG_E911:
01964    case SIG_FGC_CAMA:
01965    case SIG_FGC_CAMAMF:
01966    case SIG_FEATB:
01967    case SIG_SFWINK:
01968    case SIG_SF:
01969    case SIG_SF_FEATD:
01970    case SIG_SF_FEATDMF:
01971    case SIG_FEATDMF_TA:
01972    case SIG_SF_FEATB:
01973       c = strchr(dest, '/');
01974       if (c)
01975          c++;
01976       else
01977          c = "";
01978       if (strlen(c) < p->stripmsd) {
01979          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01980          ast_mutex_unlock(&p->lock);
01981          return -1;
01982       }
01983 #ifdef HAVE_PRI
01984       /* Start the trunk, if not GR-303 */
01985       if (!p->pri) {
01986 #endif
01987          x = DAHDI_START;
01988          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
01989          if (res < 0) {
01990             if (errno != EINPROGRESS) {
01991                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
01992                ast_mutex_unlock(&p->lock);
01993                return -1;
01994             }
01995          }
01996 #ifdef HAVE_PRI
01997       }
01998 #endif
01999       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02000       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02001 
02002       c += p->stripmsd;
02003 
02004       switch (mysig) {
02005       case SIG_FEATD:
02006          l = ast->cid.cid_num;
02007          if (l) 
02008             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02009          else
02010             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02011          break;
02012       case SIG_FEATDMF:
02013          l = ast->cid.cid_num;
02014          if (l) 
02015             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02016          else
02017             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02018          break;
02019       case SIG_FEATDMF_TA:
02020       {
02021          const char *cic, *ozz;
02022 
02023          /* If you have to go through a Tandem Access point you need to use this */
02024          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02025          if (!ozz)
02026             ozz = defaultozz;
02027          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02028          if (!cic)
02029             cic = defaultcic;
02030          if (!ozz || !cic) {
02031             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02032             ast_mutex_unlock(&p->lock);
02033             return -1;
02034          }
02035          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02036          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02037          p->whichwink = 0;
02038       }
02039          break;
02040       case SIG_E911:
02041          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02042          break;
02043       case SIG_FGC_CAMA:
02044          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02045          break;
02046       case SIG_FGC_CAMAMF:
02047       case SIG_FEATB:
02048          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02049          break;
02050       default:
02051          if (p->pulse)
02052             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02053          else
02054             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02055          break;
02056       }
02057 
02058       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02059          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02060          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02061          p->echorest[sizeof(p->echorest) - 1] = '\0';
02062          p->echobreak = 1;
02063          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02064       } else
02065          p->echobreak = 0;
02066       if (!res) {
02067          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02068             int saveerr = errno;
02069 
02070             x = DAHDI_ONHOOK;
02071             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02072             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02073             ast_mutex_unlock(&p->lock);
02074             return -1;
02075          }
02076       } else
02077          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02078       p->dialing = 1;
02079       if (ast_strlen_zero(c))
02080          p->dialednone = 1;
02081       ast_setstate(ast, AST_STATE_DIALING);
02082       break;
02083    case 0:
02084       /* Special pseudo -- automatically up*/
02085       ast_setstate(ast, AST_STATE_UP);
02086       break;      
02087    case SIG_PRI:
02088       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02089       p->dialdest[0] = '\0';
02090       break;
02091    default:
02092       ast_log(LOG_DEBUG, "not yet implemented\n");
02093       ast_mutex_unlock(&p->lock);
02094       return -1;
02095    }
02096 #ifdef HAVE_PRI
02097    if (p->pri) {
02098       struct pri_sr *sr;
02099 #ifdef SUPPORT_USERUSER
02100       const char *useruser;
02101 #endif
02102       int pridialplan;
02103       int dp_strip;
02104       int prilocaldialplan;
02105       int ldp_strip;
02106       int exclusive;
02107       const char *rr_str;
02108       int redirect_reason;
02109 
02110       c = strchr(dest, '/');
02111       if (c)
02112          c++;
02113       else
02114          c = dest;
02115 
02116       l = NULL;
02117       n = NULL;
02118 
02119       if (!p->hidecallerid) {
02120          l = ast->cid.cid_num;
02121          if (!p->hidecalleridname) {
02122             n = ast->cid.cid_name;
02123          }
02124       }
02125 
02126 
02127       if (strlen(c) < p->stripmsd) {
02128          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02129          ast_mutex_unlock(&p->lock);
02130          return -1;
02131       }
02132       if (mysig != SIG_FXSKS) {
02133          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02134          s = strchr(c + p->stripmsd, 'w');
02135          if (s) {
02136             if (strlen(s) > 1)
02137                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02138             else
02139                p->dop.dialstr[0] = '\0';
02140             *s = '\0';
02141          } else {
02142             p->dop.dialstr[0] = '\0';
02143          }
02144       }
02145       if (pri_grab(p, p->pri)) {
02146          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02147          ast_mutex_unlock(&p->lock);
02148          return -1;
02149       }
02150       if (!(p->call = pri_new_call(p->pri->pri))) {
02151          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02152          pri_rel(p->pri);
02153          ast_mutex_unlock(&p->lock);
02154          return -1;
02155       }
02156       if (!(sr = pri_sr_new())) {
02157          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02158          pri_destroycall(p->pri->pri, p->call);
02159          p->call = NULL;
02160          pri_rel(p->pri);
02161          ast_mutex_unlock(&p->lock);
02162          return -1;
02163       }
02164       if (p->bearer || (mysig == SIG_FXSKS)) {
02165          if (p->bearer) {
02166             ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02167             p->bearer->call = p->call;
02168          } else
02169             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02170          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02171       }
02172       p->digital = IS_DIGITAL(ast->transfercapability);
02173       /* Add support for exclusive override */
02174       if (p->priexclusive)
02175          exclusive = 1;
02176       else {
02177       /* otherwise, traditional behavior */
02178          if (p->pri->nodetype == PRI_NETWORK)
02179             exclusive = 0;
02180          else
02181             exclusive = 1;
02182       }
02183       
02184       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02185       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02186                (p->digital ? -1 : 
02187                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02188       if (p->pri->facilityenable)
02189          pri_facility_enable(p->pri->pri);
02190 
02191       if (option_verbose > 2)
02192          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02193       dp_strip = 0;
02194       pridialplan = p->pri->dialplan - 1;
02195       if (pridialplan == -2) { /* compute dynamically */
02196          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02197             dp_strip = strlen(p->pri->internationalprefix);
02198             pridialplan = PRI_INTERNATIONAL_ISDN;
02199          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02200             dp_strip = strlen(p->pri->nationalprefix);
02201             pridialplan = PRI_NATIONAL_ISDN;
02202          } else {
02203             pridialplan = PRI_LOCAL_ISDN;
02204          }
02205       }
02206       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02207 
02208       ldp_strip = 0;
02209       prilocaldialplan = p->pri->localdialplan - 1;
02210       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02211          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02212             ldp_strip = strlen(p->pri->internationalprefix);
02213             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02214          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02215             ldp_strip = strlen(p->pri->nationalprefix);
02216             prilocaldialplan = PRI_NATIONAL_ISDN;
02217          } else {
02218             prilocaldialplan = PRI_LOCAL_ISDN;
02219          }
02220       }
02221       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02222          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02223       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02224          if (!strcasecmp(rr_str, "UNKNOWN"))
02225             redirect_reason = 0;
02226          else if (!strcasecmp(rr_str, "BUSY"))
02227             redirect_reason = 1;
02228          else if (!strcasecmp(rr_str, "NO_REPLY"))
02229             redirect_reason = 2;
02230          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02231             redirect_reason = 15;
02232          else
02233             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02234       } else
02235          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02236       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02237 
02238 #ifdef SUPPORT_USERUSER
02239       /* User-user info */
02240       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02241 
02242       if (useruser)
02243          pri_sr_set_useruser(sr, useruser);
02244 #endif
02245 
02246       if (pri_setup(p->pri->pri, p->call, sr)) {
02247          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02248             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02249          pri_rel(p->pri);
02250          ast_mutex_unlock(&p->lock);
02251          pri_sr_free(sr);
02252          return -1;
02253       }
02254       pri_sr_free(sr);
02255       ast_setstate(ast, AST_STATE_DIALING);
02256       pri_rel(p->pri);
02257    }
02258 #endif      
02259    ast_mutex_unlock(&p->lock);
02260    return 0;
02261 }
02262 
02263 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02264 {
02265    struct dahdi_pvt *p = *pvt;
02266    /* Remove channel from the list */
02267    if (p->prev)
02268       p->prev->next = p->next;
02269    if (p->next)
02270       p->next->prev = p->prev;
02271    if (p->use_smdi)
02272       ast_smdi_interface_unref(p->smdi_iface);
02273    ast_mutex_destroy(&p->lock);
02274    dahdi_close_sub(p, SUB_REAL);
02275    if (p->owner)
02276       p->owner->tech_pvt = NULL;
02277    free(p);
02278    *pvt = NULL;
02279 }
02280 
02281 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02282 {
02283    int owned = 0;
02284    int i = 0;
02285 
02286    if (!now) {
02287       if (cur->owner) {
02288          owned = 1;
02289       }
02290 
02291       for (i = 0; i < 3; i++) {
02292          if (cur->subs[i].owner) {
02293             owned = 1;
02294          }
02295       }
02296       if (!owned) {
02297          if (prev) {
02298             prev->next = cur->next;
02299             if (prev->next)
02300                prev->next->prev = prev;
02301             else
02302                ifend = prev;
02303          } else {
02304             iflist = cur->next;
02305             if (iflist)
02306                iflist->prev = NULL;
02307             else
02308                ifend = NULL;
02309          }
02310          destroy_dahdi_pvt(&cur);
02311       }
02312    } else {
02313       if (prev) {
02314          prev->next = cur->next;
02315          if (prev->next)
02316             prev->next->prev = prev;
02317          else
02318             ifend = prev;
02319       } else {
02320          iflist = cur->next;
02321          if (iflist)
02322             iflist->prev = NULL;
02323          else
02324             ifend = NULL;
02325       }
02326       destroy_dahdi_pvt(&cur);
02327    }
02328    return 0;
02329 }
02330 
02331 static void destroy_all_channels(void)
02332 {
02333    int x;
02334    struct dahdi_pvt *p, *pl;
02335 
02336    while (num_restart_pending) {
02337       usleep(1);
02338    }
02339 
02340    ast_mutex_lock(&iflock);
02341    /* Destroy all the interfaces and free their memory */
02342    p = iflist;
02343    while (p) {
02344       /* Free any callerid */
02345       if (p->cidspill)
02346          ast_free(p->cidspill);
02347       pl = p;
02348       p = p->next;
02349       x = pl->channel;
02350       /* Free associated memory */
02351       if (pl)
02352          destroy_dahdi_pvt(&pl);
02353       if (option_verbose > 2) 
02354          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02355    }
02356    iflist = NULL;
02357    ifcount = 0;
02358    ast_mutex_unlock(&iflock);
02359 }
02360 
02361 #ifdef HAVE_PRI
02362 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02363 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02364 
02365 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02366 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02367 
02368 static char *dahdi_send_keypad_facility_descrip = 
02369 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02370 "  IE over the current channel.\n";
02371 static char *zap_send_keypad_facility_descrip = 
02372 "  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02373 "  IE over the current channel.\n";
02374 
02375 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02376 {
02377    /* Data will be our digit string */
02378    struct dahdi_pvt *p;
02379    char *digits = (char *) data;
02380 
02381    if (ast_strlen_zero(digits)) {
02382       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02383       return -1;
02384    }
02385 
02386    p = (struct dahdi_pvt *)chan->tech_pvt;
02387 
02388    if (!p) {
02389       ast_log(LOG_DEBUG, "Unable to find technology private\n");
02390       return -1;
02391    }
02392 
02393    ast_mutex_lock(&p->lock);
02394 
02395    if (!p->pri || !p->call) {
02396       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02397       ast_mutex_unlock(&p->lock);
02398       return -1;
02399    }
02400 
02401    if (!pri_grab(p, p->pri)) {
02402       pri_keypad_facility(p->pri->pri, p->call, digits);
02403       pri_rel(p->pri);
02404    } else {
02405       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02406       ast_mutex_unlock(&p->lock);
02407       return -1;
02408    }
02409 
02410    ast_mutex_unlock(&p->lock);
02411 
02412    return 0;
02413 }
02414 
02415 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02416 {
02417    return send_keypad_facility_exec(chan, data);
02418 }
02419 
02420 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02421 {
02422    ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);  
02423    return send_keypad_facility_exec(chan, data);
02424 }
02425 
02426 static int pri_is_up(struct dahdi_pri *pri)
02427 {
02428    int x;
02429    for (x = 0; x < NUM_DCHANS; x++) {
02430       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02431          return 1;
02432    }
02433    return 0;
02434 }
02435 
02436 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02437 {
02438    bearer->owner = &inuse;
02439    bearer->realcall = crv;
02440    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02441    if (crv->subs[SUB_REAL].owner)
02442       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02443    crv->bearer = bearer;
02444    crv->call = bearer->call;
02445    crv->pri = pri;
02446    return 0;
02447 }
02448 
02449 static char *pri_order(int level)
02450 {
02451    switch (level) {
02452    case 0:
02453       return "Primary";
02454    case 1:
02455       return "Secondary";
02456    case 2:
02457       return "Tertiary";
02458    case 3:
02459       return "Quaternary";
02460    default:
02461       return "<Unknown>";
02462    }     
02463 }
02464 
02465 /* Returns fd of the active dchan */
02466 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02467 {
02468    int x = -1;
02469 
02470    for (x = 0; x < NUM_DCHANS; x++) {
02471       if ((pri->dchans[x] == pri->pri))
02472          break;
02473    }
02474 
02475    return pri->fds[x];
02476 }
02477 
02478 static int pri_find_dchan(struct dahdi_pri *pri)
02479 {
02480    int oldslot = -1;
02481    struct pri *old;
02482    int newslot = -1;
02483    int x;
02484    old = pri->pri;
02485    for (x = 0; x < NUM_DCHANS; x++) {
02486       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02487          newslot = x;
02488       if (pri->dchans[x] == old) {
02489          oldslot = x;
02490       }
02491    }
02492    if (newslot < 0) {
02493       newslot = 0;
02494       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
02495          pri->dchannels[newslot]);
02496    }
02497    if (old && (oldslot != newslot))
02498       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02499          pri->dchannels[oldslot], pri->dchannels[newslot]);
02500    pri->pri = pri->dchans[newslot];
02501    return 0;
02502 }
02503 #endif
02504 
02505 static int dahdi_hangup(struct ast_channel *ast)
02506 {
02507    int res;
02508    int index,x, law;
02509    /*static int restore_gains(struct dahdi_pvt *p);*/
02510    struct dahdi_pvt *p = ast->tech_pvt;
02511    struct dahdi_pvt *tmp = NULL;
02512    struct dahdi_pvt *prev = NULL;
02513    struct dahdi_params par;
02514 
02515    if (option_debug)
02516       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02517    if (!ast->tech_pvt) {
02518       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02519       return 0;
02520    }
02521    
02522    ast_mutex_lock(&p->lock);
02523    
02524    index = dahdi_get_index(ast, p, 1);
02525 
02526    if (p->sig == SIG_PRI) {
02527       x = 1;
02528       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02529    }
02530 
02531    x = 0;
02532    dahdi_confmute(p, 0);
02533    restore_gains(p);
02534    if (p->origcid_num) {
02535       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02536       free(p->origcid_num);
02537       p->origcid_num = NULL;
02538    }  
02539    if (p->origcid_name) {
02540       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02541       free(p->origcid_name);
02542       p->origcid_name = NULL;
02543    }  
02544    if (p->dsp)
02545       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02546    if (p->exten)
02547       p->exten[0] = '\0';
02548 
02549    if (option_debug)
02550       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02551       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02552    p->ignoredtmf = 0;
02553    
02554    if (index > -1) {
02555       /* Real channel, do some fixup */
02556       p->subs[index].owner = NULL;
02557       p->subs[index].needanswer = 0;
02558       p->subs[index].needflash = 0;
02559       p->subs[index].needringing = 0;
02560       p->subs[index].needbusy = 0;
02561       p->subs[index].needcongestion = 0;
02562       p->subs[index].linear = 0;
02563       p->subs[index].needcallerid = 0;
02564       p->polarity = POLARITY_IDLE;
02565       dahdi_setlinear(p->subs[index].dfd, 0);
02566       if (index == SUB_REAL) {
02567          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02568             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02569             if (p->subs[SUB_CALLWAIT].inthreeway) {
02570                /* We had flipped over to answer a callwait and now it's gone */
02571                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02572                /* Move to the call-wait, but un-own us until they flip back. */
02573                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02574                unalloc_sub(p, SUB_CALLWAIT);
02575                p->owner = NULL;
02576             } else {
02577                /* The three way hung up, but we still have a call wait */
02578                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02579                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02580                unalloc_sub(p, SUB_THREEWAY);
02581                if (p->subs[SUB_REAL].inthreeway) {
02582                   /* This was part of a three way call.  Immediately make way for
02583                      another call */
02584                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02585                   p->owner = p->subs[SUB_REAL].owner;
02586                } else {
02587                   /* This call hasn't been completed yet...  Set owner to NULL */
02588                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02589                   p->owner = NULL;
02590                }
02591                p->subs[SUB_REAL].inthreeway = 0;
02592             }
02593          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02594             /* Move to the call-wait and switch back to them. */
02595             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02596             unalloc_sub(p, SUB_CALLWAIT);
02597             p->owner = p->subs[SUB_REAL].owner;
02598             if (p->owner->_state != AST_STATE_UP)
02599                p->subs[SUB_REAL].needanswer = 1;
02600             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02601                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02602          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02603             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02604             unalloc_sub(p, SUB_THREEWAY);
02605             if (p->subs[SUB_REAL].inthreeway) {
02606                /* This was part of a three way call.  Immediately make way for
02607                   another call */
02608                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02609                p->owner = p->subs[SUB_REAL].owner;
02610             } else {
02611                /* This call hasn't been completed yet...  Set owner to NULL */
02612                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02613                p->owner = NULL;
02614             }
02615             p->subs[SUB_REAL].inthreeway = 0;
02616          }
02617       } else if (index == SUB_CALLWAIT) {
02618          /* Ditch the holding callwait call, and immediately make it availabe */
02619          if (p->subs[SUB_CALLWAIT].inthreeway) {
02620             /* This is actually part of a three way, placed on hold.  Place the third part
02621                on music on hold now */
02622             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02623                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02624                   S_OR(p->mohsuggest, NULL),
02625                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02626             }
02627             p->subs[SUB_THREEWAY].inthreeway = 0;
02628             /* Make it the call wait now */
02629             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02630             unalloc_sub(p, SUB_THREEWAY);
02631          } else
02632             unalloc_sub(p, SUB_CALLWAIT);
02633       } else if (index == SUB_THREEWAY) {
02634          if (p->subs[SUB_CALLWAIT].inthreeway) {
02635             /* The other party of the three way call is currently in a call-wait state.
02636                Start music on hold for them, and take the main guy out of the third call */
02637             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02638                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02639                   S_OR(p->mohsuggest, NULL),
02640                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02641             }
02642             p->subs[SUB_CALLWAIT].inthreeway = 0;
02643          }
02644          p->subs[SUB_REAL].inthreeway = 0;
02645          /* If this was part of a three way call index, let us make
02646             another three way call */
02647          unalloc_sub(p, SUB_THREEWAY);
02648       } else {
02649          /* This wasn't any sort of call, but how are we an index? */
02650          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02651       }
02652    }
02653 
02654    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02655       p->owner = NULL;
02656       p->ringt = 0;
02657       p->distinctivering = 0;
02658       p->confirmanswer = 0;
02659       p->cidrings = 1;
02660       p->outgoing = 0;
02661       p->digital = 0;
02662       p->faxhandled = 0;
02663       p->pulsedial = 0;
02664       p->onhooktime = time(NULL);
02665 #ifdef HAVE_PRI
02666       p->proceeding = 0;
02667       p->progress = 0;
02668       p->alerting = 0;
02669       p->setup_ack = 0;
02670 #endif      
02671       if (p->dsp) {
02672          ast_dsp_free(p->dsp);
02673          p->dsp = NULL;
02674       }
02675 
02676       law = DAHDI_LAW_DEFAULT;
02677       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02678       if (res < 0) 
02679          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02680       /* Perform low level hangup if no owner left */
02681 #ifdef HAVE_PRI
02682       if (p->pri) {
02683 #ifdef SUPPORT_USERUSER
02684          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02685 #endif
02686 
02687          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02688          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02689             if (!pri_grab(p, p->pri)) {
02690                if (p->alreadyhungup) {
02691                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02692 
02693 #ifdef SUPPORT_USERUSER
02694                   pri_call_set_useruser(p->call, useruser);
02695 #endif
02696 
02697                   pri_hangup(p->pri->pri, p->call, -1);
02698                   p->call = NULL;
02699                   if (p->bearer) 
02700                      p->bearer->call = NULL;
02701                } else {
02702                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02703                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02704                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02705 
02706 #ifdef SUPPORT_USERUSER
02707                   pri_call_set_useruser(p->call, useruser);
02708 #endif
02709 
02710                   p->alreadyhungup = 1;
02711                   if (p->bearer)
02712                      p->bearer->alreadyhungup = 1;
02713                   if (cause) {
02714                      if (atoi(cause))
02715                         icause = atoi(cause);
02716                   }
02717                   pri_hangup(p->pri->pri, p->call, icause);
02718                }
02719                if (res < 0) 
02720                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02721                pri_rel(p->pri);        
02722             } else {
02723                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02724                res = -1;
02725             }
02726          } else {
02727             if (p->bearer)
02728                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02729             p->call = NULL;
02730             res = 0;
02731          }
02732       }
02733 #endif
02734       if (p->sig && (p->sig != SIG_PRI))
02735          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
02736       if (res < 0) {
02737          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02738       }
02739       switch (p->sig) {
02740       case SIG_FXOGS:
02741       case SIG_FXOLS:
02742       case SIG_FXOKS:
02743          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02744          if (!res) {
02745 #if 0
02746             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02747 #endif
02748             /* If they're off hook, try playing congestion */
02749             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02750                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
02751             else
02752                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02753          }
02754          break;
02755       case SIG_FXSGS:
02756       case SIG_FXSLS:
02757       case SIG_FXSKS:
02758          /* Make sure we're not made available for at least two seconds assuming
02759             we were actually used for an inbound or outbound call. */
02760          if (ast->_state != AST_STATE_RESERVED) {
02761             time(&p->guardtime);
02762             p->guardtime += 2;
02763          }
02764          break;
02765       default:
02766          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02767       }
02768       if (p->cidspill)
02769          free(p->cidspill);
02770       if (p->sig)
02771          dahdi_disable_ec(p);
02772       x = 0;
02773       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02774       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02775       p->didtdd = 0;
02776       p->cidspill = NULL;
02777       p->callwaitcas = 0;
02778       p->callwaiting = p->permcallwaiting;
02779       p->hidecallerid = p->permhidecallerid;
02780       p->dialing = 0;
02781       p->rdnis[0] = '\0';
02782       update_conf(p);
02783       reset_conf(p);
02784       /* Restore data mode */
02785       if (p->sig == SIG_PRI) {
02786          x = 0;
02787          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02788       }
02789 #ifdef HAVE_PRI
02790       if (p->bearer) {
02791          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02792          /* Free up the bearer channel as well, and
02793             don't use its file descriptor anymore */
02794          update_conf(p->bearer);
02795          reset_conf(p->bearer);
02796          p->bearer->owner = NULL;
02797          p->bearer->realcall = NULL;
02798          p->bearer = NULL;
02799          p->subs[SUB_REAL].dfd = -1;
02800          p->pri = NULL;
02801       }
02802 #endif
02803       if (num_restart_pending == 0)
02804          restart_monitor();
02805    }
02806 
02807    p->callwaitingrepeat = 0;
02808    p->cidcwexpire = 0;
02809    p->oprmode = 0;
02810    ast->tech_pvt = NULL;
02811    ast_mutex_unlock(&p->lock);
02812    ast_module_unref(ast_module_info->self);
02813    if (option_verbose > 2) 
02814       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02815 
02816    ast_mutex_lock(&iflock);
02817 
02818    if (p->restartpending) {
02819       num_restart_pending--;
02820    }
02821 
02822    tmp = iflist;
02823    prev = NULL;
02824    if (p->destroy) {
02825       while (tmp) {
02826          if (tmp == p) {
02827             destroy_channel(prev, tmp, 0);
02828             break;
02829          } else {
02830             prev = tmp;
02831             tmp = tmp->next;
02832          }
02833       }
02834    }
02835    ast_mutex_unlock(&iflock);
02836    return 0;
02837 }
02838 
02839 static int dahdi_answer(struct ast_channel *ast)
02840 {
02841    struct dahdi_pvt *p = ast->tech_pvt;
02842    int res = 0;
02843    int index;
02844    int oldstate = ast->_state;
02845    ast_setstate(ast, AST_STATE_UP);
02846    ast_mutex_lock(&p->lock);
02847    index = dahdi_get_index(ast, p, 0);
02848    if (index < 0)
02849       index = SUB_REAL;
02850    /* nothing to do if a radio channel */
02851    if ((p->radio || (p->oprmode < 0))) {
02852       ast_mutex_unlock(&p->lock);
02853       return 0;
02854    }
02855    switch (p->sig) {
02856    case SIG_FXSLS:
02857    case SIG_FXSGS:
02858    case SIG_FXSKS:
02859       p->ringt = 0;
02860       /* Fall through */
02861    case SIG_EM:
02862    case SIG_EM_E1:
02863    case SIG_EMWINK:
02864    case SIG_FEATD:
02865    case SIG_FEATDMF:
02866    case SIG_FEATDMF_TA:
02867    case SIG_E911:
02868    case SIG_FGC_CAMA:
02869    case SIG_FGC_CAMAMF:
02870    case SIG_FEATB:
02871    case SIG_SF:
02872    case SIG_SFWINK:
02873    case SIG_SF_FEATD:
02874    case SIG_SF_FEATDMF:
02875    case SIG_SF_FEATB:
02876    case SIG_FXOLS:
02877    case SIG_FXOGS:
02878    case SIG_FXOKS:
02879       /* Pick up the line */
02880       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02881       if (p->hanguponpolarityswitch) {
02882          gettimeofday(&p->polaritydelaytv, NULL);
02883       }
02884       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02885       tone_zone_play_tone(p->subs[index].dfd, -1);
02886       p->dialing = 0;
02887       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02888          if (oldstate == AST_STATE_RINGING) {
02889             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02890             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
02891             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02892             p->owner = p->subs[SUB_REAL].owner;
02893          }
02894       }
02895       if (p->sig & __DAHDI_SIG_FXS) {
02896          dahdi_enable_ec(p);
02897          dahdi_train_ec(p);
02898       }
02899       break;
02900 #ifdef HAVE_PRI
02901    case SIG_PRI:
02902       /* Send a pri acknowledge */
02903       if (!pri_grab(p, p->pri)) {
02904          p->proceeding = 1;
02905          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02906          pri_rel(p->pri);
02907       } else {
02908          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02909          res = -1;
02910       }
02911       break;
02912 #endif
02913    case 0:
02914       ast_mutex_unlock(&p->lock);
02915       return 0;
02916    default:
02917       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02918       res = -1;
02919    }
02920    ast_mutex_unlock(&p->lock);
02921    return res;
02922 }
02923 
02924 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
02925 {
02926    char *cp;
02927    signed char *scp;
02928    int x;
02929    int index;
02930    struct dahdi_pvt *p = chan->tech_pvt, *pp;
02931    struct oprmode *oprmode;
02932    
02933 
02934    /* all supported options require data */
02935    if (!data || (datalen < 1)) {
02936       errno = EINVAL;
02937       return -1;
02938    }
02939 
02940    switch (option) {
02941    case AST_OPTION_TXGAIN:
02942       scp = (signed char *) data;
02943       index = dahdi_get_index(chan, p, 0);
02944       if (index < 0) {
02945          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02946          return -1;
02947       }
02948       if (option_debug)
02949          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02950       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
02951    case AST_OPTION_RXGAIN:
02952       scp = (signed char *) data;
02953       index = dahdi_get_index(chan, p, 0);
02954       if (index < 0) {
02955          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02956          return -1;
02957       }
02958       if (option_debug)
02959          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02960       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
02961    case AST_OPTION_TONE_VERIFY:
02962       if (!p->dsp)
02963          break;
02964       cp = (char *) data;
02965       switch (*cp) {
02966       case 1:
02967          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02968          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
02969          break;
02970       case 2:
02971          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02972          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
02973          break;
02974       default:
02975          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02976          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
02977          break;
02978       }
02979       break;
02980    case AST_OPTION_TDD:
02981       /* turn on or off TDD */
02982       cp = (char *) data;
02983       p->mate = 0;
02984       if (!*cp) { /* turn it off */
02985          if (option_debug)
02986             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02987          if (p->tdd)
02988             tdd_free(p->tdd);
02989          p->tdd = 0;
02990          break;
02991       }
02992       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
02993          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
02994       dahdi_disable_ec(p);
02995       /* otherwise, turn it on */
02996       if (!p->didtdd) { /* if havent done it yet */
02997          unsigned char mybuf[41000], *buf;
02998          int size, res, fd, len;
02999          struct pollfd fds[1];
03000 
03001          buf = mybuf;
03002          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03003          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03004          len = 40000;
03005          index = dahdi_get_index(chan, p, 0);
03006          if (index < 0) {
03007             ast_log(LOG_WARNING, "No index in TDD?\n");
03008             return -1;
03009          }
03010          fd = p->subs[index].dfd;
03011          while (len) {
03012             if (ast_check_hangup(chan))
03013                return -1;
03014             size = len;
03015             if (size > READ_SIZE)
03016                size = READ_SIZE;
03017             fds[0].fd = fd;
03018             fds[0].events = POLLPRI | POLLOUT;
03019             fds[0].revents = 0;
03020             res = poll(fds, 1, -1);
03021             if (!res) {
03022                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03023                continue;
03024             }
03025             /* if got exception */
03026             if (fds[0].revents & POLLPRI)
03027                return -1;
03028             if (!(fds[0].revents & POLLOUT)) {
03029                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03030                continue;
03031             }
03032             res = write(fd, buf, size);
03033             if (res != size) {
03034                if (res == -1) return -1;
03035                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03036                break;
03037             }
03038             len -= size;
03039             buf += size;
03040          }
03041          p->didtdd = 1; /* set to have done it now */    
03042       }
03043       if (*cp == 2) { /* Mate mode */
03044          if (p->tdd)
03045             tdd_free(p->tdd);
03046          p->tdd = 0;
03047          p->mate = 1;
03048          break;
03049       }     
03050       if (!p->tdd) { /* if we dont have one yet */
03051          p->tdd = tdd_new(); /* allocate one */
03052       }     
03053       break;
03054    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03055       if (!p->dsp)
03056          break;
03057       cp = (char *) data;
03058       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03059          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03060                 p->dtmfrelax = 0;
03061                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03062                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03063       break;
03064    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03065       cp = (char *) data;
03066       if (!*cp) {    
03067          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03068          x = 0;
03069          dahdi_disable_ec(p);
03070       } else {    
03071          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03072          x = 1;
03073       }
03074       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03075          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03076       break;
03077    case AST_OPTION_OPRMODE:  /* Operator services mode */
03078       oprmode = (struct oprmode *) data;
03079       pp = oprmode->peer->tech_pvt;
03080       p->oprmode = pp->oprmode = 0;
03081       /* setup peers */
03082       p->oprpeer = pp;
03083       pp->oprpeer = p;
03084       /* setup modes, if any */
03085       if (oprmode->mode) 
03086       {
03087          pp->oprmode = oprmode->mode;
03088          p->oprmode = -oprmode->mode;
03089       }
03090       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03091          oprmode->mode, chan->name,oprmode->peer->name);;
03092       break;
03093    case AST_OPTION_ECHOCAN:
03094       cp = (char *) data;
03095       if (*cp) {
03096          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03097          dahdi_enable_ec(p);
03098       } else {
03099          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03100          dahdi_disable_ec(p);
03101       }
03102       break;
03103    }
03104    errno = 0;
03105 
03106    return 0;
03107 }
03108 
03109 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03110 {
03111    struct dahdi_pvt *p = chan->tech_pvt;
03112    
03113    if (!strcasecmp(data, "rxgain")) {
03114       ast_mutex_lock(&p->lock);
03115       snprintf(buf, len, "%f", p->rxgain);
03116       ast_mutex_unlock(&p->lock);   
03117    } else if (!strcasecmp(data, "txgain")) {
03118       ast_mutex_lock(&p->lock);
03119       snprintf(buf, len, "%f", p->txgain);
03120       ast_mutex_unlock(&p->lock);   
03121    } else {
03122       ast_copy_string(buf, "", len);
03123    }
03124    return 0;
03125 }
03126 
03127 
03128 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03129 {
03130    /* Unlink a specific slave or all slaves/masters from a given master */
03131    int x;
03132    int hasslaves;
03133    if (!master)
03134       return;
03135    if (needlock) {
03136       ast_mutex_lock(&master->lock);
03137       if (slave) {
03138          while (ast_mutex_trylock(&slave->lock)) {
03139             DEADLOCK_AVOIDANCE(&master->lock);
03140          }
03141       }
03142    }
03143    hasslaves = 0;
03144    for (x = 0; x < MAX_SLAVES; x++) {
03145       if (master->slaves[x]) {
03146          if (!slave || (master->slaves[x] == slave)) {
03147             /* Take slave out of the conference */
03148             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03149             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03150             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03151             master->slaves[x]->master = NULL;
03152             master->slaves[x] = NULL;
03153          } else
03154             hasslaves = 1;
03155       }
03156       if (!hasslaves)
03157          master->inconference = 0;
03158    }
03159    if (!slave) {
03160       if (master->master) {
03161          /* Take master out of the conference */
03162          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03163          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03164          hasslaves = 0;
03165          for (x = 0; x < MAX_SLAVES; x++) {
03166             if (master->master->slaves[x] == master)
03167                master->master->slaves[x] = NULL;
03168             else if (master->master->slaves[x])
03169                hasslaves = 1;
03170          }
03171          if (!hasslaves)
03172             master->master->inconference = 0;
03173       }
03174       master->master = NULL;
03175    }
03176    update_conf(master);
03177    if (needlock) {
03178       if (slave)
03179          ast_mutex_unlock(&slave->lock);
03180       ast_mutex_unlock(&master->lock);
03181    }
03182 }
03183 
03184 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03185    int x;
03186    if (!slave || !master) {
03187       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03188       return;
03189    }
03190    for (x = 0; x < MAX_SLAVES; x++) {
03191       if (!master->slaves[x]) {
03192          master->slaves[x] = slave;
03193          break;
03194       }
03195    }
03196    if (x >= MAX_SLAVES) {
03197       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03198       master->slaves[MAX_SLAVES - 1] = slave;
03199    }
03200    if (slave->master) 
03201       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03202    slave->master = master;
03203    
03204    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03205 }
03206 
03207 static void disable_dtmf_detect(struct dahdi_pvt *p)
03208 {
03209 #ifdef DAHDI_TONEDETECT
03210    int val;
03211 #endif
03212 
03213    p->ignoredtmf = 1;
03214 
03215 #ifdef DAHDI_TONEDETECT
03216    val = 0;
03217    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03218 #endif      
03219    if (!p->hardwaredtmf && p->dsp) {
03220       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03221       ast_dsp_set_features(p->dsp, p->dsp_features);
03222    }
03223 }
03224 
03225 static void enable_dtmf_detect(struct dahdi_pvt *p)
03226 {
03227 #ifdef DAHDI_TONEDETECT
03228    int val;
03229 #endif
03230 
03231    if (p->channel == CHAN_PSEUDO)
03232       return;
03233 
03234    p->ignoredtmf = 0;
03235 
03236 #ifdef DAHDI_TONEDETECT
03237    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03238    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03239 #endif      
03240    if (!p->hardwaredtmf && p->dsp) {
03241       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03242       ast_dsp_set_features(p->dsp, p->dsp_features);
03243    }
03244 }
03245 
03246 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
03247 {
03248    struct ast_channel *who;
03249    struct dahdi_pvt *p0, *p1, *op0, *op1;
03250    struct dahdi_pvt *master = NULL, *slave = NULL;
03251    struct ast_frame *f;
03252    int inconf = 0;
03253    int nothingok = 1;
03254    int ofd0, ofd1;
03255    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03256    int os0 = -1, os1 = -1;
03257    int priority = 0;
03258    struct ast_channel *oc0, *oc1;
03259    enum ast_bridge_result res;
03260 
03261 #ifdef PRI_2BCT
03262    int triedtopribridge = 0;
03263    q931_call *q931c0 = NULL, *q931c1 = NULL;
03264 #endif
03265 
03266    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03267       There is code below to handle it properly until DTMF is actually seen,
03268       but due to currently unresolved issues it's ignored...
03269    */
03270 
03271    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03272       return AST_BRIDGE_FAILED_NOWARN;
03273 
03274    ast_mutex_lock(&c0->lock);
03275    while (ast_mutex_trylock(&c1->lock)) {
03276       DEADLOCK_AVOIDANCE(&c0->lock);
03277    }
03278 
03279    p0 = c0->tech_pvt;
03280    p1 = c1->tech_pvt;
03281    /* cant do pseudo-channels here */
03282    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03283       ast_mutex_unlock(&c0->lock);
03284       ast_mutex_unlock(&c1->lock);
03285       return AST_BRIDGE_FAILED_NOWARN;
03286    }
03287 
03288    oi0 = dahdi_get_index(c0, p0, 0);
03289    oi1 = dahdi_get_index(c1, p1, 0);
03290    if ((oi0 < 0) || (oi1 < 0)) {
03291       ast_mutex_unlock(&c0->lock);
03292       ast_mutex_unlock(&c1->lock);
03293       return AST_BRIDGE_FAILED;
03294    }
03295 
03296    op0 = p0 = c0->tech_pvt;
03297    op1 = p1 = c1->tech_pvt;
03298    ofd0 = c0->fds[0];
03299    ofd1 = c1->fds[0];
03300    oc0 = p0->owner;
03301    oc1 = p1->owner;
03302 
03303    if (ast_mutex_trylock(&p0->lock)) {
03304       /* Don't block, due to potential for deadlock */
03305       ast_mutex_unlock(&c0->lock);
03306       ast_mutex_unlock(&c1->lock);
03307       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03308       return AST_BRIDGE_RETRY;
03309    }
03310    if (ast_mutex_trylock(&p1->lock)) {
03311       /* Don't block, due to potential for deadlock */
03312       ast_mutex_unlock(&p0->lock);
03313       ast_mutex_unlock(&c0->lock);
03314       ast_mutex_unlock(&c1->lock);
03315       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03316       return AST_BRIDGE_RETRY;
03317    }
03318 
03319    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03320       if (p0->owner && p1->owner) {
03321          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03322          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03323             master = p0;
03324             slave = p1;
03325             inconf = 1;
03326          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03327             master = p1;
03328             slave = p0;
03329             inconf = 1;
03330          } else {
03331             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03332             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03333                p0->channel,
03334                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03335                p0->subs[SUB_REAL].inthreeway, p0->channel,
03336                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03337                p1->subs[SUB_REAL].inthreeway);
03338          }
03339          nothingok = 0;
03340       }
03341    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03342       if (p1->subs[SUB_THREEWAY].inthreeway) {
03343          master = p1;
03344          slave = p0;
03345          nothingok = 0;
03346       }
03347    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03348       if (p0->subs[SUB_THREEWAY].inthreeway) {
03349          master = p0;
03350          slave = p1;
03351          nothingok = 0;
03352       }
03353    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03354       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03355          don't put us in anything */
03356       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03357          master = p1;
03358          slave = p0;
03359          nothingok = 0;
03360       }
03361    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03362       /* Same as previous */
03363       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03364          master = p0;
03365          slave = p1;
03366          nothingok = 0;
03367       }
03368    }
03369    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03370       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03371    if (master && slave) {
03372       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03373          in an active threeway call with a channel that is ringing, we should
03374          indicate ringing. */
03375       if ((oi1 == SUB_THREEWAY) && 
03376           p1->subs[SUB_THREEWAY].inthreeway && 
03377           p1->subs[SUB_REAL].owner && 
03378           p1->subs[SUB_REAL].inthreeway && 
03379           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03380          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03381          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03382          os1 = p1->subs[SUB_REAL].owner->_state;
03383       } else {
03384          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03385          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03386       }
03387       if ((oi0 == SUB_THREEWAY) && 
03388           p0->subs[SUB_THREEWAY].inthreeway && 
03389           p0->subs[SUB_REAL].owner && 
03390           p0->subs[SUB_REAL].inthreeway && 
03391           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03392          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03393          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03394          os0 = p0->subs[SUB_REAL].owner->_state;
03395       } else {
03396          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03397          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03398       }
03399       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03400          if (!p0->echocanbridged || !p1->echocanbridged) {
03401             /* Disable echo cancellation if appropriate */
03402             dahdi_disable_ec(p0);
03403             dahdi_disable_ec(p1);
03404          }
03405       }
03406       dahdi_link(slave, master);
03407       master->inconference = inconf;
03408    } else if (!nothingok)
03409       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03410 
03411    update_conf(p0);
03412    update_conf(p1);
03413    t0 = p0->subs[SUB_REAL].inthreeway;
03414    t1 = p1->subs[SUB_REAL].inthreeway;
03415 
03416    ast_mutex_unlock(&p0->lock);
03417    ast_mutex_unlock(&p1->lock);
03418 
03419    ast_mutex_unlock(&c0->lock);
03420    ast_mutex_unlock(&c1->lock);
03421 
03422    /* Native bridge failed */
03423    if ((!master || !slave) && !nothingok) {
03424       dahdi_enable_ec(p0);
03425       dahdi_enable_ec(p1);
03426       return AST_BRIDGE_FAILED;
03427    }
03428    
03429    if (option_verbose > 2) 
03430       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03431 
03432    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03433       disable_dtmf_detect(op0);
03434 
03435    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03436       disable_dtmf_detect(op1);
03437 
03438    for (;;) {
03439       struct ast_channel *c0_priority[2] = {c0, c1};
03440       struct ast_channel *c1_priority[2] = {c1, c0};
03441 
03442       /* Here's our main loop...  Start by locking things, looking for private parts, 
03443          and then balking if anything is wrong */
03444       ast_mutex_lock(&c0->lock);
03445       while (ast_mutex_trylock(&c1->lock)) {
03446          DEADLOCK_AVOIDANCE(&c0->lock);
03447       }
03448 
03449       p0 = c0->tech_pvt;
03450       p1 = c1->tech_pvt;
03451 
03452       if (op0 == p0)
03453          i0 = dahdi_get_index(c0, p0, 1);
03454       if (op1 == p1)
03455          i1 = dahdi_get_index(c1, p1, 1);
03456       ast_mutex_unlock(&c0->lock);
03457       ast_mutex_unlock(&c1->lock);
03458 
03459       if (!timeoutms || 
03460           (op0 != p0) ||
03461           (op1 != p1) || 
03462           (ofd0 != c0->fds[0]) || 
03463           (ofd1 != c1->fds[0]) ||
03464           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03465           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03466           (oc0 != p0->owner) || 
03467           (oc1 != p1->owner) ||
03468           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03469           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03470           (oi0 != i0) ||
03471           (oi1 != i1)) {
03472          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03473             op0->channel, oi0, op1->channel, oi1);
03474          res = AST_BRIDGE_RETRY;
03475          goto return_from_bridge;
03476       }
03477 
03478 #ifdef PRI_2BCT
03479       q931c0 = p0->call;
03480       q931c1 = p1->call;
03481       if (p0->transfer && p1->transfer 
03482           && q931c0 && q931c1 
03483           && !triedtopribridge) {
03484          pri_channel_bridge(q931c0, q931c1);
03485          triedtopribridge = 1;
03486       }
03487 #endif
03488 
03489       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03490       if (!who) {
03491          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03492          continue;
03493       }
03494       f = ast_read(who);
03495       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03496          *fo = f;
03497          *rc = who;
03498          res = AST_BRIDGE_COMPLETE;
03499          goto return_from_bridge;
03500       }
03501       if (f->frametype == AST_FRAME_DTMF) {
03502          if ((who == c0) && p0->pulsedial) {
03503             ast_write(c1, f);
03504          } else if ((who == c1) && p1->pulsedial) {
03505             ast_write(c0, f);
03506          } else {
03507             *fo = f;
03508             *rc = who;
03509             res = AST_BRIDGE_COMPLETE;
03510             goto return_from_bridge;
03511          }
03512       }
03513       ast_frfree(f);
03514       
03515       /* Swap who gets priority */
03516       priority = !priority;
03517    }
03518 
03519 return_from_bridge:
03520    if (op0 == p0)
03521       dahdi_enable_ec(p0);
03522 
03523    if (op1 == p1)
03524       dahdi_enable_ec(p1);
03525 
03526    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03527       enable_dtmf_detect(op0);
03528 
03529    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03530       enable_dtmf_detect(op1);
03531 
03532    dahdi_unlink(slave, master, 1);
03533 
03534    return res;
03535 }
03536 
03537 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03538 {
03539    struct dahdi_pvt *p = newchan->tech_pvt;
03540    int x;
03541    ast_mutex_lock(&p->lock);
03542    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03543    if (p->owner == oldchan) {
03544       p->owner = newchan;
03545    }
03546    for (x = 0; x < 3; x++)
03547       if (p->subs[x].owner == oldchan) {
03548          if (!x)
03549             dahdi_unlink(NULL, p, 0);
03550          p->subs[x].owner = newchan;
03551       }
03552    if (newchan->_state == AST_STATE_RINGING) 
03553       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03554    update_conf(p);
03555    ast_mutex_unlock(&p->lock);
03556    return 0;
03557 }
03558 
03559 static int dahdi_ring_phone(struct dahdi_pvt *p)
03560 {
03561    int x;
03562    int res;
03563    /* Make sure our transmit state is on hook */
03564    x = 0;
03565    x = DAHDI_ONHOOK;
03566    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03567    do {
03568       x = DAHDI_RING;
03569       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03570       if (res) {
03571          switch (errno) {
03572          case EBUSY:
03573          case EINTR:
03574             /* Wait just in case */
03575             usleep(10000);
03576             continue;
03577          case EINPROGRESS:
03578             res = 0;
03579             break;
03580          default:
03581             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03582             res = 0;
03583          }
03584       }
03585    } while (res);
03586    return res;
03587 }
03588 
03589 static void *ss_thread(void *data);
03590 
03591 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03592 
03593 static int attempt_transfer(struct dahdi_pvt *p)
03594 {
03595    /* In order to transfer, we need at least one of the channels to
03596       actually be in a call bridge.  We can't conference two applications
03597       together (but then, why would we want to?) */
03598    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03599       /* The three-way person we're about to transfer to could still be in MOH, so
03600          stop if now if appropriate */
03601       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03602          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03603       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03604          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03605       }
03606       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03607          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03608       }
03609        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03610          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03611                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03612          return -1;
03613       }
03614       /* Orphan the channel after releasing the lock */
03615       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03616       unalloc_sub(p, SUB_THREEWAY);
03617    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03618       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03619       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03620          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03621       }
03622       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03623          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03624       }
03625       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03626          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03627                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03628          return -1;
03629       }
03630       /* Three-way is now the REAL */
03631       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03632       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03633       unalloc_sub(p, SUB_THREEWAY);
03634       /* Tell the caller not to hangup */
03635       return 1;
03636    } else {
03637       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03638                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03639       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03640       return -1;
03641    }
03642    return 0;
03643 }
03644 
03645 static int check_for_conference(struct dahdi_pvt *p)
03646 {
03647    struct dahdi_confinfo ci;
03648    /* Fine if we already have a master, etc */
03649    if (p->master || (p->confno > -1))
03650       return 0;
03651    memset(&ci, 0, sizeof(ci));
03652    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03653       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03654       return 0;
03655    }
03656    /* If we have no master and don't have a confno, then 
03657       if we're in a conference, it's probably a MeetMe room or
03658       some such, so don't let us 3-way out! */
03659    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03660       if (option_verbose > 2) 
03661          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03662       return 1;
03663    }
03664    return 0;
03665 }
03666 
03667 static int get_alarms(struct dahdi_pvt *p)
03668 {
03669    int res;
03670    struct dahdi_spaninfo zi;
03671 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03672    /*
03673     * The conditional compilation is needed only in asterisk-1.4 for
03674     * backward compatibility with old zaptel drivers that don't have
03675     * a DAHDI_PARAMS.chan_alarms field.
03676     */
03677    struct dahdi_params params;
03678 #endif
03679 
03680    memset(&zi, 0, sizeof(zi));
03681    zi.spanno = p->span;
03682 
03683    /* First check for span alarms */
03684    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03685       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03686       return 0;
03687    }
03688    if (zi.alarms != DAHDI_ALARM_NONE)
03689       return zi.alarms;
03690 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03691    /* No alarms on the span. Check for channel alarms. */
03692    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
03693       return params.chan_alarms;
03694    /* ioctl failed */
03695    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03696 #endif
03697    return DAHDI_ALARM_NONE;
03698 }
03699 
03700 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
03701 {
03702    struct dahdi_pvt *p = ast->tech_pvt;
03703    struct ast_frame *f = *dest;
03704 
03705    if (option_debug)
03706       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03707 
03708    if (p->confirmanswer) {
03709       if (option_debug)
03710          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03711       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03712          of a DTMF digit */
03713       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03714       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03715       *dest = &p->subs[index].f;
03716       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03717       p->confirmanswer = 0;
03718    } else if (p->callwaitcas) {
03719       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03720          if (option_debug)
03721             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03722          if (p->cidspill)
03723             free(p->cidspill);
03724          send_cwcidspill(p);
03725       }
03726       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03727          p->callwaitcas = 0;
03728       p->subs[index].f.frametype = AST_FRAME_NULL;
03729       p->subs[index].f.subclass = 0;
03730       *dest = &p->subs[index].f;
03731    } else if (f->subclass == 'f') {
03732       /* Fax tone -- Handle and return NULL */
03733       if ((p->callprogress & 0x6) && !p->faxhandled) {
03734          p->faxhandled++;
03735          if (strcmp(ast->exten, "fax")) {
03736             const char *target_context = S_OR(ast->macrocontext, ast->context);
03737 
03738             /* We need to unlock 'ast' here because ast_exists_extension has the
03739              * potential to start autoservice on the channel. Such action is prone
03740              * to deadlock.
03741              */
03742             ast_mutex_unlock(&p->lock);
03743             ast_channel_unlock(ast);
03744             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03745                ast_channel_lock(ast);
03746                ast_mutex_lock(&p->lock);
03747                if (option_verbose > 2)
03748                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03749                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03750                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03751                if (ast_async_goto(ast, target_context, "fax", 1))
03752                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03753             } else {
03754                ast_channel_lock(ast);
03755                ast_mutex_lock(&p->lock);
03756                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03757             }
03758          } else if (option_debug)
03759             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03760       } else if (option_debug)
03761             ast_log(LOG_DEBUG, "Fax already handled\n");
03762       dahdi_confmute(p, 0);
03763       p->subs[index].f.frametype = AST_FRAME_NULL;
03764       p->subs[index].f.subclass = 0;
03765       *dest = &p->subs[index].f;
03766    } else if (f->subclass == 'm') {
03767       /* Confmute request */
03768       dahdi_confmute(p, 1);
03769       p->subs[index].f.frametype = AST_FRAME_NULL;
03770       p->subs[index].f.subclass = 0;
03771       *dest = &p->subs[index].f;    
03772    } else if (f->subclass == 'u') {
03773       /* Unmute */
03774       dahdi_confmute(p, 0);
03775       p->subs[index].f.frametype = AST_FRAME_NULL;
03776       p->subs[index].f.subclass = 0;
03777       *dest = &p->subs[index].f;    
03778    } else
03779       dahdi_confmute(p, 0);
03780 }
03781          
03782 static void handle_alarms(struct dahdi_pvt *p, int alarms)
03783 {
03784    const char *alarm_str = alarm2str(alarms);
03785    
03786    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
03787     * doesn't know what to do with it.  Don't confuse users with log messages. */
03788    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
03789       p->unknown_alarm = 1;
03790       return;
03791    } else {
03792       p->unknown_alarm = 0;
03793    }
03794    
03795    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
03796    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03797             "Alarm: %s\r\n"
03798             "Channel: %d\r\n",
03799             alarm_str, p->channel);
03800 }
03801 
03802 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
03803 {
03804    int res, x;
03805    int index, mysig;
03806    char *c;
03807    struct dahdi_pvt *p = ast->tech_pvt;
03808    pthread_t threadid;
03809    pthread_attr_t attr;
03810    struct ast_channel *chan;
03811    struct ast_frame *f;
03812 
03813    index = dahdi_get_index(ast, p, 0);
03814    mysig = p->sig;
03815    if (p->outsigmod > -1)
03816       mysig = p->outsigmod;
03817    p->subs[index].f.frametype = AST_FRAME_NULL;
03818    p->subs[index].f.subclass = 0;
03819    p->subs[index].f.datalen = 0;
03820    p->subs[index].f.samples = 0;
03821    p->subs[index].f.mallocd = 0;
03822    p->subs[index].f.offset = 0;
03823    p->subs[index].f.src = "dahdi_handle_event";
03824    p->subs[index].f.data = NULL;
03825    f = &p->subs[index].f;
03826 
03827    if (index < 0)
03828       return &p->subs[index].f;
03829    if (p->fake_event) {
03830       res = p->fake_event;
03831       p->fake_event = 0;
03832    } else
03833       res = dahdi_get_event(p->subs[index].dfd);
03834 
03835    if (option_debug)
03836       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03837 
03838    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
03839       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
03840 
03841       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03842 #ifdef HAVE_PRI
03843       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03844          /* absorb event */
03845       } else {
03846 #endif
03847          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03848          p->subs[index].f.subclass = res & 0xff;
03849 #ifdef HAVE_PRI
03850       }
03851 #endif
03852       dahdi_handle_dtmfup(ast, index, &f);
03853       return f;
03854    }
03855 
03856    if (res & DAHDI_EVENT_DTMFDOWN) {
03857       if (option_debug)
03858          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03859       /* Mute conference */
03860       dahdi_confmute(p, 1);
03861       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03862       p->subs[index].f.subclass = res & 0xff;
03863       return &p->subs[index].f;
03864    }
03865 
03866    switch (res) {
03867 #ifdef DAHDI_EVENT_EC_DISABLED
03868       case DAHDI_EVENT_EC_DISABLED:
03869          if (option_verbose > 2) 
03870             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03871          p->echocanon = 0;
03872          break;
03873 #endif
03874       case DAHDI_EVENT_BITSCHANGED:
03875          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03876       case DAHDI_EVENT_PULSE_START:
03877          /* Stop tone if there's a pulse start and the PBX isn't started */
03878          if (!ast->pbx)
03879             tone_zone_play_tone(p->subs[index].dfd, -1);
03880          break;   
03881       case DAHDI_EVENT_DIALCOMPLETE:
03882          if (p->inalarm) break;
03883          if ((p->radio || (p->oprmode < 0))) break;
03884          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
03885             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
03886             return NULL;
03887          }
03888          if (!x) { /* if not still dialing in driver */
03889             dahdi_enable_ec(p);
03890             if (p->echobreak) {
03891                dahdi_train_ec(p);
03892                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03893                p->dop.op = DAHDI_DIAL_OP_REPLACE;
03894                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
03895                p->echobreak = 0;
03896             } else {
03897                p->dialing = 0;
03898                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03899                   /* if thru with dialing after offhook */
03900                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03901                      ast_setstate(ast, AST_STATE_UP);
03902                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03903                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03904                      break;
03905                   } else { /* if to state wait for offhook to dial rest */
03906                      /* we now wait for off hook */
03907                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03908                   }
03909                }
03910                if (ast->_state == AST_STATE_DIALING) {
03911                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03912                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03913                   } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
03914                      ast_setstate(ast, AST_STATE_RINGING);
03915                   } else if (!p->answeronpolarityswitch) {
03916                      ast_setstate(ast, AST_STATE_UP);
03917                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03918                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03919                      /* If aops=0 and hops=1, this is necessary */
03920                      p->polarity = POLARITY_REV;
03921                   } else {
03922                      /* Start clean, so we can catch the change to REV polarity when party answers */
03923                      p->polarity = POLARITY_IDLE;
03924                   }
03925                }
03926             }
03927          }
03928          break;
03929       case DAHDI_EVENT_ALARM:
03930 #ifdef HAVE_PRI
03931          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03932             /* T309 is not enabled : hangup calls when alarm occurs */
03933             if (p->call) {
03934                if (p->pri && p->pri->pri) {
03935                   if (!pri_grab(p, p->pri)) {
03936                      pri_hangup(p->pri->pri, p->call, -1);
03937                      pri_destroycall(p->pri->pri, p->call);
03938                      p->call = NULL;
03939                      pri_rel(p->pri);
03940                   } else
03941                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03942                } else
03943                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03944             }
03945             if (p->owner)
03946                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03947          }
03948          if (p->bearer)
03949             p->bearer->inalarm = 1;
03950          else
03951 #endif
03952          p->inalarm = 1;
03953          res = get_alarms(p);
03954          handle_alarms(p, res);
03955 #ifdef HAVE_LIBPRI
03956          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03957             /* fall through intentionally */
03958          } else {
03959             break;
03960          }
03961 #endif
03962       case DAHDI_EVENT_ONHOOK:
03963          if (p->radio) {
03964             p->subs[index].f.frametype = AST_FRAME_CONTROL;
03965             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03966             break;
03967          }
03968          if (p->oprmode < 0)
03969          {
03970             if (p->oprmode != -1) break;
03971             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03972             {
03973                /* Make sure it starts ringing */
03974                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
03975                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
03976                save_conference(p->oprpeer);
03977                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03978             }
03979             break;
03980          }
03981          switch (p->sig) {
03982          case SIG_FXOLS:
03983          case SIG_FXOGS:
03984          case SIG_FXOKS:
03985             p->onhooktime = time(NULL);
03986             p->msgstate = -1;
03987             /* Check for some special conditions regarding call waiting */
03988             if (index == SUB_REAL) {
03989                /* The normal line was hung up */
03990                if (p->subs[SUB_CALLWAIT].owner) {
03991                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
03992                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03993                   if (option_verbose > 2) 
03994                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03995                   unalloc_sub(p, SUB_CALLWAIT); 
03996 #if 0
03997                   p->subs[index].needanswer = 0;
03998                   p->subs[index].needringing = 0;
03999 #endif                  
04000                   p->callwaitingrepeat = 0;
04001                   p->cidcwexpire = 0;
04002                   p->owner = NULL;
04003                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04004                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04005                      p->dialing = 1;
04006                   dahdi_ring_phone(p);
04007                } else if (p->subs[SUB_THREEWAY].owner) {
04008                   unsigned int mssinceflash;
04009                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04010                      the private structure -- not especially easy or clean */
04011                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04012                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04013                      ast_mutex_unlock(&p->lock);
04014                      DEADLOCK_AVOIDANCE(&ast->lock);
04015                      /* We can grab ast and p in that order, without worry.  We should make sure
04016                         nothing seriously bad has happened though like some sort of bizarre double
04017                         masquerade! */
04018                      ast_mutex_lock(&p->lock);
04019                      if (p->owner != ast) {
04020                         ast_log(LOG_WARNING, "This isn't good...\n");
04021                         return NULL;
04022                      }
04023                   }
04024                   if (!p->subs[SUB_THREEWAY].owner) {
04025                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04026                      return NULL;
04027                   }
04028                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04029                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04030                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04031                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04032                         hanging up.  Hangup both channels now */
04033                      if (p->subs[SUB_THREEWAY].owner)
04034                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04035                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04036                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04037                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04038                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04039                      if (p->transfer) {
04040                         /* In any case this isn't a threeway call anymore */
04041                         p->subs[SUB_REAL].inthreeway = 0;
04042                         p->subs[SUB_THREEWAY].inthreeway = 0;
04043                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04044                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04045                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04046                            /* Swap subs and dis-own channel */
04047                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04048                            p->owner = NULL;
04049                            /* Ring the phone */
04050                            dahdi_ring_phone(p);
04051                         } else {
04052                            if ((res = attempt_transfer(p)) < 0) {
04053                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04054                               if (p->subs[SUB_THREEWAY].owner)
04055                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04056                            } else if (res) {
04057                               /* Don't actually hang up at this point */
04058                               if (p->subs[SUB_THREEWAY].owner)
04059                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04060                               break;
04061                            }
04062                         }
04063                      } else {
04064                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04065                         if (p->subs[SUB_THREEWAY].owner)
04066                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04067                      }
04068                   } else {
04069                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04070                      /* Swap subs and dis-own channel */
04071                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04072                      p->owner = NULL;
04073                      /* Ring the phone */
04074                      dahdi_ring_phone(p);
04075                   }
04076                }
04077             } else {
04078                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04079             }
04080             /* Fall through */
04081          default:
04082             dahdi_disable_ec(p);
04083             return NULL;
04084          }
04085          break;
04086       case DAHDI_EVENT_RINGOFFHOOK:
04087          if (p->inalarm) break;
04088          if (p->oprmode < 0)
04089          {
04090             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04091             {
04092                /* Make sure it stops ringing */
04093                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04094                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04095                restore_conference(p->oprpeer);
04096             }
04097             break;
04098          }
04099          if (p->radio)
04100          {
04101             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04102             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04103             break;
04104          }
04105          /* for E911, its supposed to wait for offhook then dial
04106             the second half of the dial string */
04107          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04108             c = strchr(p->dialdest, '/');
04109             if (c)
04110                c++;
04111             else
04112                c = p->dialdest;
04113             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04114             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04115             if (strlen(p->dop.dialstr) > 4) {
04116                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04117                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04118                p->echorest[sizeof(p->echorest) - 1] = '\0';
04119                p->echobreak = 1;
04120                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04121             } else
04122                p->echobreak = 0;
04123             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04124                int saveerr = errno;
04125 
04126                x = DAHDI_ONHOOK;
04127                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04128                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04129                return NULL;
04130                }
04131             p->dialing = 1;
04132             return &p->subs[index].f;
04133          }
04134          switch (p->sig) {
04135          case SIG_FXOLS:
04136          case SIG_FXOGS:
04137          case SIG_FXOKS:
04138             switch (ast->_state) {
04139             case AST_STATE_RINGING:
04140                dahdi_enable_ec(p);
04141                dahdi_train_ec(p);
04142                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04143                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04144                /* Make sure it stops ringing */
04145                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04146                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04147                if (p->cidspill) {
04148                   /* Cancel any running CallerID spill */
04149                   free(p->cidspill);
04150                   p->cidspill = NULL;
04151                }
04152                p->dialing = 0;
04153                p->callwaitcas = 0;
04154                if (p->confirmanswer) {
04155                   /* Ignore answer if "confirm answer" is enabled */
04156                   p->subs[index].f.frametype = AST_FRAME_NULL;
04157                   p->subs[index].f.subclass = 0;
04158                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04159                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04160                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04161                   if (res < 0) {
04162                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04163                      p->dop.dialstr[0] = '\0';
04164                      return NULL;
04165                   } else {
04166                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04167                      p->subs[index].f.frametype = AST_FRAME_NULL;
04168                      p->subs[index].f.subclass = 0;
04169                      p->dialing = 1;
04170                   }
04171                   p->dop.dialstr[0] = '\0';
04172                   ast_setstate(ast, AST_STATE_DIALING);
04173                } else
04174                   ast_setstate(ast, AST_STATE_UP);
04175                return &p->subs[index].f;
04176             case AST_STATE_DOWN:
04177                ast_setstate(ast, AST_STATE_RING);
04178                ast->rings = 1;
04179                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04180                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04181                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04182                return &p->subs[index].f;
04183             case AST_STATE_UP:
04184                /* Make sure it stops ringing */
04185                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04186                /* Okay -- probably call waiting*/
04187                if (ast_bridged_channel(p->owner))
04188                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04189                p->subs[index].needunhold = 1;
04190                break;
04191             case AST_STATE_RESERVED:
04192                /* Start up dialtone */
04193                if (has_voicemail(p))
04194                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04195                else
04196                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04197                break;
04198             default:
04199                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04200             }
04201             break;
04202          case SIG_FXSLS:
04203          case SIG_FXSGS:
04204          case SIG_FXSKS:
04205             if (ast->_state == AST_STATE_RING) {
04206                p->ringt = p->ringt_base;
04207             }
04208 
04209             /* Fall through */
04210          case SIG_EM:
04211          case SIG_EM_E1:
04212          case SIG_EMWINK:
04213          case SIG_FEATD:
04214          case SIG_FEATDMF:
04215          case SIG_FEATDMF_TA:
04216          case SIG_E911:
04217          case SIG_FGC_CAMA:
04218          case SIG_FGC_CAMAMF:
04219          case SIG_FEATB:
04220          case SIG_SF:
04221          case SIG_SFWINK:
04222          case SIG_SF_FEATD:
04223          case SIG_SF_FEATDMF:
04224          case SIG_SF_FEATB:
04225             if (ast->_state == AST_STATE_PRERING)
04226                ast_setstate(ast, AST_STATE_RING);
04227             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04228                if (option_debug)
04229                   ast_log(LOG_DEBUG, "Ring detected\n");
04230                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04231                p->subs[index].f.subclass = AST_CONTROL_RING;
04232             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04233                if (option_debug)
04234                   ast_log(LOG_DEBUG, "Line answered\n");
04235                if (p->confirmanswer) {
04236                   p->subs[index].f.frametype = AST_FRAME_NULL;
04237                   p->subs[index].f.subclass = 0;
04238                } else {
04239                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04240                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04241                   ast_setstate(ast, AST_STATE_UP);
04242                }
04243             } else if (ast->_state != AST_STATE_RING)
04244                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04245             break;
04246          default:
04247             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04248          }
04249          break;
04250 #ifdef DAHDI_EVENT_RINGBEGIN
04251       case DAHDI_EVENT_RINGBEGIN:
04252          switch (p->sig) {
04253          case SIG_FXSLS:
04254          case SIG_FXSGS:
04255          case SIG_FXSKS:
04256             if (ast->_state == AST_STATE_RING) {
04257                p->ringt = p->ringt_base;
04258             }
04259             break;
04260          }
04261          break;
04262 #endif         
04263       case DAHDI_EVENT_RINGEROFF:
04264          if (p->inalarm) break;
04265          if ((p->radio || (p->oprmode < 0))) break;
04266          ast->rings++;
04267          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04268             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04269             free(p->cidspill);
04270             p->cidspill = NULL;
04271             p->callwaitcas = 0;
04272          }
04273          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04274          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04275          break;
04276       case DAHDI_EVENT_RINGERON:
04277          break;
04278       case DAHDI_EVENT_NOALARM:
04279          p->inalarm = 0;
04280 #ifdef HAVE_PRI
04281          /* Extremely unlikely but just in case */
04282          if (p->bearer)
04283             p->bearer->inalarm = 0;
04284 #endif            
04285          if (!p->unknown_alarm) {
04286             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04287             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04288                "Channel: %d\r\n", p->channel);
04289          } else {
04290             p->unknown_alarm = 0;
04291          }
04292          break;
04293       case DAHDI_EVENT_WINKFLASH:
04294          if (p->inalarm) break;
04295          if (p->radio) break;
04296          if (p->oprmode < 0) break;
04297          if (p->oprmode > 1)
04298          {
04299             struct dahdi_params par;
04300 
04301             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04302             {
04303                if (!par.rxisoffhook)
04304                {
04305                   /* Make sure it stops ringing */
04306                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04307                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04308                   save_conference(p);
04309                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04310                }
04311             }
04312             break;
04313          }
04314          /* Remember last time we got a flash-hook */
04315          gettimeofday(&p->flashtime, NULL);
04316          switch (mysig) {
04317          case SIG_FXOLS:
04318          case SIG_FXOGS:
04319          case SIG_FXOKS:
04320             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04321                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04322             p->callwaitcas = 0;
04323 
04324             if (index != SUB_REAL) {
04325                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04326                goto winkflashdone;
04327             }
04328             
04329             if (p->subs[SUB_CALLWAIT].owner) {
04330                /* Swap to call-wait */
04331                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04332                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04333                p->owner = p->subs[SUB_REAL].owner;
04334                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04335                if (p->owner->_state == AST_STATE_RINGING) {
04336                   ast_setstate(p->owner, AST_STATE_UP);
04337                   p->subs[SUB_REAL].needanswer = 1;
04338                }
04339                p->callwaitingrepeat = 0;
04340                p->cidcwexpire = 0;
04341                /* Start music on hold if appropriate */
04342                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04343                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04344                      S_OR(p->mohsuggest, NULL),
04345                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04346                }
04347                p->subs[SUB_CALLWAIT].needhold = 1;
04348                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04349                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04350                      S_OR(p->mohsuggest, NULL),
04351                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04352                }
04353                p->subs[SUB_REAL].needunhold = 1;
04354             } else if (!p->subs[SUB_THREEWAY].owner) {
04355                char cid_num[256];
04356                char cid_name[256];
04357 
04358                if (!p->threewaycalling) {
04359                   /* Just send a flash if no 3-way calling */
04360                   p->subs[SUB_REAL].needflash = 1;
04361                   goto winkflashdone;
04362                } else if (!check_for_conference(p)) {
04363                   if (p->dahditrcallerid && p->owner) {
04364                      if (p->owner->cid.cid_num)
04365                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04366                      if (p->owner->cid.cid_name)
04367                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04368                   }
04369                   /* XXX This section needs much more error checking!!! XXX */
04370                   /* Start a 3-way call if feasible */
04371                   if (!((ast->pbx) ||
04372                         (ast->_state == AST_STATE_UP) ||
04373                         (ast->_state == AST_STATE_RING))) {
04374                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04375                         goto winkflashdone;
04376                   }
04377                   if (alloc_sub(p, SUB_THREEWAY)) {
04378                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04379                      goto winkflashdone;
04380                   }
04381                   /* Make new channel */
04382                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04383                   if (p->dahditrcallerid) {
04384                      if (!p->origcid_num)
04385                         p->origcid_num = ast_strdup(p->cid_num);
04386                      if (!p->origcid_name)
04387                         p->origcid_name = ast_strdup(p->cid_name);
04388                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04389                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04390                   }
04391                   /* Swap things around between the three-way and real call */
04392                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04393                   /* Disable echo canceller for better dialing */
04394                   dahdi_disable_ec(p);
04395                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04396                   if (res)
04397                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04398                   p->owner = chan;
04399                   pthread_attr_init(&attr);
04400                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04401                   if (!chan) {
04402                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04403                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04404                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04405                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04406                      dahdi_enable_ec(p);
04407                      ast_hangup(chan);
04408                   } else {
04409                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04410                      int way3bridge = 0, cdr3way = 0;
04411                      
04412                      if (!other) {
04413                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04414                      } else
04415                         way3bridge = 1;
04416                      
04417                      if (p->subs[SUB_THREEWAY].owner->cdr)
04418                         cdr3way = 1;
04419                      
04420                      if (option_verbose > 2) 
04421                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04422                      /* Start music on hold if appropriate */
04423                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04424                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04425                            S_OR(p->mohsuggest, NULL),
04426                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04427                      }
04428                      p->subs[SUB_THREEWAY].needhold = 1;
04429                   }
04430                   pthread_attr_destroy(&attr);
04431                }
04432             } else {
04433                /* Already have a 3 way call */
04434                if (p->subs[SUB_THREEWAY].inthreeway) {
04435                   /* Call is already up, drop the last person */
04436                   if (option_debug)
04437                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04438                   /* If the primary call isn't answered yet, use it */
04439                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04440                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04441                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04442                      p->owner = p->subs[SUB_REAL].owner;
04443                   }
04444                   /* Drop the last call and stop the conference */
04445                   if (option_verbose > 2)
04446                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04447                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04448                   p->subs[SUB_REAL].inthreeway = 0;
04449                   p->subs[SUB_THREEWAY].inthreeway = 0;
04450                } else {
04451                   /* Lets see what we're up to */
04452                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04453                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04454                      int otherindex = SUB_THREEWAY;
04455                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04456                      int way3bridge = 0, cdr3way = 0;
04457                      
04458                      if (!other) {
04459                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04460                      } else
04461                         way3bridge = 1;
04462                      
04463                      if (p->subs[SUB_THREEWAY].owner->cdr)
04464                         cdr3way = 1;
04465 
04466                      if (option_verbose > 2)
04467                         ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
04468                      /* Put them in the threeway, and flip */
04469                      p->subs[SUB_THREEWAY].inthreeway = 1;
04470                      p->subs[SUB_REAL].inthreeway = 1;
04471                      if (ast->_state == AST_STATE_UP) {
04472                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04473                         otherindex = SUB_REAL;
04474                      }
04475                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04476                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04477                      p->subs[otherindex].needunhold = 1;
04478                      p->owner = p->subs[SUB_REAL].owner;
04479                      if (ast->_state == AST_STATE_RINGING) {
04480                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04481                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04482                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04483                      }
04484                   } else {
04485                      if (option_verbose > 2)
04486                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04487                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04488                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04489                      p->owner = p->subs[SUB_REAL].owner;
04490                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04491                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04492                      p->subs[SUB_REAL].needunhold = 1;
04493                      dahdi_enable_ec(p);
04494                   }
04495                      
04496                }
04497             }
04498          winkflashdone:              
04499             update_conf(p);
04500             break;
04501          case SIG_EM:
04502          case SIG_EM_E1:
04503          case SIG_EMWINK:
04504          case SIG_FEATD:
04505          case SIG_SF:
04506          case SIG_SFWINK:
04507          case SIG_SF_FEATD:
04508          case SIG_FXSLS:
04509          case SIG_FXSGS:
04510             if (p->dialing)
04511                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04512             else
04513                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04514             break;
04515          case SIG_FEATDMF_TA:
04516             switch (p->whichwink) {
04517             case 0:
04518                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04519                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04520                break;
04521             case 1:
04522                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04523                break;
04524             case 2:
04525                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04526                return NULL;
04527             }
04528             p->whichwink++;
04529             /* Fall through */
04530          case SIG_FEATDMF:
04531          case SIG_E911:
04532          case SIG_FGC_CAMAMF:
04533          case SIG_FGC_CAMA:
04534          case SIG_FEATB:
04535          case SIG_SF_FEATDMF:
04536          case SIG_SF_FEATB:
04537             /* FGD MF *Must* wait for wink */
04538             if (!ast_strlen_zero(p->dop.dialstr)) {
04539                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04540                if (res < 0) {
04541                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04542                   p->dop.dialstr[0] = '\0';
04543                   return NULL;
04544                } else 
04545                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04546             }
04547             p->dop.dialstr[0] = '\0';
04548             break;
04549          default:
04550             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04551          }
04552          break;
04553       case DAHDI_EVENT_HOOKCOMPLETE:
04554          if (p->inalarm) break;
04555          if ((p->radio || (p->oprmode < 0))) break;
04556          switch (mysig) {
04557          case SIG_FXSLS:  /* only interesting for FXS */
04558          case SIG_FXSGS:
04559          case SIG_FXSKS:
04560          case SIG_EM:
04561          case SIG_EM_E1:
04562          case SIG_EMWINK:
04563          case SIG_FEATD:
04564          case SIG_SF:
04565          case SIG_SFWINK:
04566          case SIG_SF_FEATD:
04567             if (!ast_strlen_zero(p->dop.dialstr)) {
04568                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04569                if (res < 0) {
04570                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04571                   p->dop.dialstr[0] = '\0';
04572                   return NULL;
04573                } else 
04574                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04575             }
04576             p->dop.dialstr[0] = '\0';
04577             p->dop.op = DAHDI_DIAL_OP_REPLACE;
04578             break;
04579          case SIG_FEATDMF:
04580          case SIG_FEATDMF_TA:
04581          case SIG_E911:
04582          case SIG_FGC_CAMA:
04583          case SIG_FGC_CAMAMF:
04584          case SIG_FEATB:
04585          case SIG_SF_FEATDMF:
04586          case SIG_SF_FEATB:
04587             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04588             break;
04589          default:
04590             break;
04591          }
04592          break;
04593       case DAHDI_EVENT_POLARITY:
04594          /*
04595           * If we get a Polarity Switch event, check to see
04596           * if we should change the polarity state and
04597           * mark the channel as UP or if this is an indication
04598           * of remote end disconnect.
04599           */
04600          if (p->polarity == POLARITY_IDLE) {
04601             p->polarity = POLARITY_REV;
04602             if (p->answeronpolarityswitch &&
04603                 ((ast->_state == AST_STATE_DIALING) ||
04604                 (ast->_state == AST_STATE_RINGING))) {
04605                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04606                ast_setstate(p->owner, AST_STATE_UP);
04607                if (p->hanguponpolarityswitch) {
04608                   gettimeofday(&p->polaritydelaytv, NULL);
04609                }
04610             } else
04611                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04612          } 
04613          /* Removed else statement from here as it was preventing hangups from ever happening*/
04614          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04615          if (p->hanguponpolarityswitch &&
04616             (p->polarityonanswerdelay > 0) &&
04617                 (p->polarity == POLARITY_REV) &&
04618             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04619                                 /* Added log_debug information below to provide a better indication of what is going on */
04620             ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04621          
04622             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04623                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04624                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04625                p->polarity = POLARITY_IDLE;
04626             } else {
04627                ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
04628             }
04629          } else {
04630             p->polarity = POLARITY_IDLE;
04631             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04632          }
04633                         /* Added more log_debug information below to provide a better indication of what is going on */
04634          ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
04635          break;
04636       default:
04637          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04638    }
04639    return &p->subs[index].f;
04640 }
04641 
04642 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04643 {
04644    struct dahdi_pvt *p = ast->tech_pvt;
04645    int res;
04646    int usedindex=-1;
04647    int index;
04648    struct ast_frame *f;
04649 
04650 
04651    index = dahdi_get_index(ast, p, 1);
04652    
04653    p->subs[index].f.frametype = AST_FRAME_NULL;
04654    p->subs[index].f.datalen = 0;
04655    p->subs[index].f.samples = 0;
04656    p->subs[index].f.mallocd = 0;
04657    p->subs[index].f.offset = 0;
04658    p->subs[index].f.subclass = 0;
04659    p->subs[index].f.delivery = ast_tv(0,0);
04660    p->subs[index].f.src = "dahdi_exception";
04661    p->subs[index].f.data = NULL;
04662    
04663    
04664    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04665       /* If nobody owns us, absorb the event appropriately, otherwise
04666          we loop indefinitely.  This occurs when, during call waiting, the
04667          other end hangs up our channel so that it no longer exists, but we
04668          have neither FLASH'd nor ONHOOK'd to signify our desire to
04669          change to the other channel. */
04670       if (p->fake_event) {
04671          res = p->fake_event;
04672          p->fake_event = 0;
04673       } else
04674          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04675       /* Switch to real if there is one and this isn't something really silly... */
04676       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04677          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04678          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04679          p->owner = p->subs[SUB_REAL].owner;
04680          if (p->owner && ast_bridged_channel(p->owner))
04681             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04682          p->subs[SUB_REAL].needunhold = 1;
04683       }
04684       switch (res) {
04685       case DAHDI_EVENT_ONHOOK:
04686          dahdi_disable_ec(p);
04687          if (p->owner) {
04688             if (option_verbose > 2) 
04689                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04690             dahdi_ring_phone(p);
04691             p->callwaitingrepeat = 0;
04692             p->cidcwexpire = 0;
04693          } else
04694             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04695          update_conf(p);
04696          break;
04697       case DAHDI_EVENT_RINGOFFHOOK:
04698          dahdi_enable_ec(p);
04699          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04700          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04701             p->subs[SUB_REAL].needanswer = 1;
04702             p->dialing = 0;
04703          }
04704          break;
04705       case DAHDI_EVENT_HOOKCOMPLETE:
04706       case DAHDI_EVENT_RINGERON:
04707       case DAHDI_EVENT_RINGEROFF:
04708          /* Do nothing */
04709          break;
04710       case DAHDI_EVENT_WINKFLASH:
04711          gettimeofday(&p->flashtime, NULL);
04712          if (p->owner) {
04713             if (option_verbose > 2) 
04714                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04715             if (p->owner->_state != AST_STATE_UP) {
04716                /* Answer if necessary */
04717                usedindex = dahdi_get_index(p->owner, p, 0);
04718                if (usedindex > -1) {
04719                   p->subs[usedindex].needanswer = 1;
04720                }
04721                ast_setstate(p->owner, AST_STATE_UP);
04722             }
04723             p->callwaitingrepeat = 0;
04724             p->cidcwexpire = 0;
04725             if (ast_bridged_channel(p->owner))
04726                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04727             p->subs[SUB_REAL].needunhold = 1;
04728          } else
04729             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04730          update_conf(p);
04731          break;
04732       default:
04733          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04734       }
04735       f = &p->subs[index].f;
04736       return f;
04737    }
04738    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04739       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04740    /* If it's not us, return NULL immediately */
04741    if (ast != p->owner) {
04742       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04743       f = &p->subs[index].f;
04744       return f;
04745    }
04746    f = dahdi_handle_event(ast);
04747    return f;
04748 }
04749 
04750 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
04751 {
04752    struct dahdi_pvt *p = ast->tech_pvt;
04753    struct ast_frame *f;
04754    ast_mutex_lock(&p->lock);
04755    f = __dahdi_exception(ast);
04756    ast_mutex_unlock(&p->lock);
04757    return f;
04758 }
04759 
04760 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
04761 {
04762    struct dahdi_pvt *p = ast->tech_pvt;
04763    int res;
04764    int index;
04765    void *readbuf;
04766    struct ast_frame *f;
04767 
04768    while (ast_mutex_trylock(&p->lock)) {
04769       DEADLOCK_AVOIDANCE(&ast->lock);
04770    }
04771 
04772    index = dahdi_get_index(ast, p, 0);
04773    
04774    /* Hang up if we don't really exist */
04775    if (index < 0) {
04776       ast_log(LOG_WARNING, "We dont exist?\n");
04777       ast_mutex_unlock(&p->lock);
04778       return NULL;
04779    }
04780    
04781    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04782 
04783    p->subs[index].f.frametype = AST_FRAME_NULL;
04784    p->subs[index].f.datalen = 0;
04785    p->subs[index].f.samples = 0;
04786    p->subs[index].f.mallocd = 0;
04787    p->subs[index].f.offset = 0;
04788    p->subs[index].f.subclass = 0;
04789    p->subs[index].f.delivery = ast_tv(0,0);
04790    p->subs[index].f.src = "dahdi_read";
04791    p->subs[index].f.data = NULL;
04792    
04793    /* make sure it sends initial key state as first frame */
04794    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04795    {
04796       struct dahdi_params ps;
04797 
04798       ps.channo = p->channel;
04799       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
04800          ast_mutex_unlock(&p->lock);
04801          return NULL;
04802       }
04803       p->firstradio = 1;
04804       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04805       if (ps.rxisoffhook)
04806       {
04807          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04808       }
04809       else
04810       {
04811          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04812       }
04813       ast_mutex_unlock(&p->lock);
04814       return &p->subs[index].f;
04815    }
04816    if (p->ringt == 1) {
04817       ast_mutex_unlock(&p->lock);
04818       return NULL;
04819    }
04820    else if (p->ringt > 0) 
04821       p->ringt--;
04822 
04823    if (p->subs[index].needringing) {
04824       /* Send ringing frame if requested */
04825       p->subs[index].needringing = 0;
04826       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04827       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04828       ast_setstate(ast, AST_STATE_RINGING);
04829       ast_mutex_unlock(&p->lock);
04830       return &p->subs[index].f;
04831    }
04832 
04833    if (p->subs[index].needbusy) {
04834       /* Send busy frame if requested */
04835       p->subs[index].needbusy = 0;
04836       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04837       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04838       ast_mutex_unlock(&p->lock);
04839       return &p->subs[index].f;
04840    }
04841 
04842    if (p->subs[index].needcongestion) {
04843       /* Send congestion frame if requested */
04844       p->subs[index].needcongestion = 0;
04845       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04846       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04847       ast_mutex_unlock(&p->lock);
04848       return &p->subs[index].f;
04849    }
04850 
04851    if (p->subs[index].needcallerid) {
04852       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04853                      S_OR(p->lastcid_name, NULL),
04854                      S_OR(p->lastcid_num, NULL)
04855                      );
04856       p->subs[index].needcallerid = 0;
04857    }
04858    
04859    if (p->subs[index].needanswer) {
04860       /* Send answer frame if requested */
04861       p->subs[index].needanswer = 0;
04862       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04863       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04864       ast_mutex_unlock(&p->lock);
04865       return &p->subs[index].f;
04866    }  
04867    
04868    if (p->subs[index].needflash) {
04869       /* Send answer frame if requested */
04870       p->subs[index].needflash = 0;
04871       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04872       p->subs[index].f.subclass = AST_CONTROL_FLASH;
04873       ast_mutex_unlock(&p->lock);
04874       return &p->subs[index].f;
04875    }  
04876    
04877    if (p->subs[index].needhold) {
04878       /* Send answer frame if requested */
04879       p->subs[index].needhold = 0;
04880       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04881       p->subs[index].f.subclass = AST_CONTROL_HOLD;
04882       ast_mutex_unlock(&p->lock);
04883       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04884       return &p->subs[index].f;
04885    }  
04886    
04887    if (p->subs[index].needunhold) {
04888       /* Send answer frame if requested */
04889       p->subs[index].needunhold = 0;
04890       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04891       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04892       ast_mutex_unlock(&p->lock);
04893       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04894       return &p->subs[index].f;
04895    }  
04896    
04897    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04898       if (!p->subs[index].linear) {
04899          p->subs[index].linear = 1;
04900          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04901          if (res) 
04902             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04903       }
04904    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04905          (ast->rawreadformat == AST_FORMAT_ALAW)) {
04906       if (p->subs[index].linear) {
04907          p->subs[index].linear = 0;
04908          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04909          if (res) 
04910             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04911       }
04912    } else {
04913       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04914       ast_mutex_unlock(&p->lock);
04915       return NULL;
04916    }
04917    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04918    CHECK_BLOCKING(ast);
04919    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04920    ast_clear_flag(ast, AST_FLAG_BLOCKING);
04921    /* Check for hangup */
04922    if (res < 0) {
04923       f = NULL;
04924       if (res == -1)  {
04925          if (errno == EAGAIN) {
04926             /* Return "NULL" frame if there is nobody there */
04927             ast_mutex_unlock(&p->lock);
04928             return &p->subs[index].f;
04929          } else if (errno == ELAST) {
04930             f = __dahdi_exception(ast);
04931          } else
04932             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
04933       }
04934       ast_mutex_unlock(&p->lock);
04935       return f;
04936    }
04937    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04938       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04939       f = __dahdi_exception(ast);
04940       ast_mutex_unlock(&p->lock);
04941       return f;
04942    }
04943    if (p->tdd) { /* if in TDD mode, see if we receive that */
04944       int c;
04945 
04946       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04947       if (c < 0) {
04948          ast_log(LOG_DEBUG,"tdd_feed failed\n");
04949          ast_mutex_unlock(&p->lock);
04950          return NULL;
04951       }
04952       if (c) { /* if a char to return */
04953          p->subs[index].f.subclass = 0;
04954          p->subs[index].f.frametype = AST_FRAME_TEXT;
04955          p->subs[index].f.mallocd = 0;
04956          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04957          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04958          p->subs[index].f.datalen = 1;
04959          *((char *) p->subs[index].f.data) = c;
04960          ast_mutex_unlock(&p->lock);
04961          return &p->subs[index].f;
04962       }
04963    }
04964    /* Ensure the CW timer decrements only on a single subchannel */
04965    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
04966       p->callwaitingrepeat--;
04967    }
04968    if (p->cidcwexpire)
04969       p->cidcwexpire--;
04970    /* Repeat callwaiting */
04971    if (p->callwaitingrepeat == 1) {
04972       p->callwaitrings++;
04973       dahdi_callwait(ast);
04974    }
04975    /* Expire CID/CW */
04976    if (p->cidcwexpire == 1) {
04977       if (option_verbose > 2)
04978          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04979       restore_conference(p);
04980    }
04981    if (p->subs[index].linear) {
04982       p->subs[index].f.datalen = READ_SIZE * 2;
04983    } else 
04984       p->subs[index].f.datalen = READ_SIZE;
04985 
04986    /* Handle CallerID Transmission */
04987    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04988       send_callerid(p);
04989    }
04990 
04991    p->subs[index].f.frametype = AST_FRAME_VOICE;
04992    p->subs[index].f.subclass = ast->rawreadformat;
04993    p->subs[index].f.samples = READ_SIZE;
04994    p->subs[index].f.mallocd = 0;
04995    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04996    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04997 #if 0
04998    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04999 #endif   
05000    if (p->dialing || /* Transmitting something */
05001       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05002       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05003       ) {
05004       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05005          don't send anything */
05006       p->subs[index].f.frametype = AST_FRAME_NULL;
05007       p->subs[index].f.subclass = 0;
05008       p->subs[index].f.samples = 0;
05009       p->subs[index].f.mallocd = 0;
05010       p->subs[index].f.offset = 0;
05011       p->subs[index].f.data = NULL;
05012       p->subs[index].f.datalen= 0;
05013    }
05014    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
05015       /* Perform busy detection. etc on the dahdi line */
05016       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05017       if (f) {
05018          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05019             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05020                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05021                   a busy  */
05022                f = NULL;
05023             }
05024          } else if (f->frametype == AST_FRAME_DTMF) {
05025 #ifdef HAVE_PRI
05026             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05027                /* Don't accept in-band DTMF when in overlap dial mode */
05028                f->frametype = AST_FRAME_NULL;
05029                f->subclass = 0;
05030             }
05031 #endif            
05032             /* DSP clears us of being pulse */
05033             p->pulsedial = 0;
05034          }
05035       }
05036    } else 
05037       f = &p->subs[index].f; 
05038 
05039    if (f && (f->frametype == AST_FRAME_DTMF))
05040       dahdi_handle_dtmfup(ast, index, &f);
05041 
05042    /* If we have a fake_event, trigger exception to handle it */
05043    if (p->fake_event)
05044       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05045 
05046    ast_mutex_unlock(&p->lock);
05047    return f;
05048 }
05049 
05050 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05051 {
05052    int sent=0;
05053    int size;
05054    int res;
05055    int fd;
05056    fd = p->subs[index].dfd;
05057    while (len) {
05058       size = len;
05059       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05060          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05061       res = write(fd, buf, size);
05062       if (res != size) {
05063          if (option_debug)
05064             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05065          return sent;
05066       }
05067       len -= size;
05068       buf += size;
05069    }
05070    return sent;
05071 }
05072 
05073 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05074 {
05075    struct dahdi_pvt *p = ast->tech_pvt;
05076    int res;
05077    int index;
05078    index = dahdi_get_index(ast, p, 0);
05079    if (index < 0) {
05080       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05081       return -1;
05082    }
05083 
05084 #if 0
05085 #ifdef HAVE_PRI
05086    ast_mutex_lock(&p->lock);
05087    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05088       if (p->pri->pri) {      
05089          if (!pri_grab(p, p->pri)) {
05090                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05091                pri_rel(p->pri);
05092          } else
05093                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05094       }
05095       p->proceeding=1;
05096    }
05097    ast_mutex_unlock(&p->lock);
05098 #endif
05099 #endif
05100    /* Write a frame of (presumably voice) data */
05101    if (frame->frametype != AST_FRAME_VOICE) {
05102       if (frame->frametype != AST_FRAME_IMAGE)
05103          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05104       return 0;
05105    }
05106    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05107        (frame->subclass != AST_FORMAT_ULAW) &&
05108        (frame->subclass != AST_FORMAT_ALAW)) {
05109       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05110       return -1;
05111    }
05112    if (p->dialing) {
05113       if (option_debug)
05114          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05115       return 0;
05116    }
05117    if (!p->owner) {
05118       if (option_debug)
05119          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05120       return 0;
05121    }
05122    if (p->cidspill) {
05123       if (option_debug)
05124          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05125       return 0;
05126    }
05127    /* Return if it's not valid data */
05128    if (!frame->data || !frame->datalen)
05129       return 0;
05130 
05131    if (frame->subclass == AST_FORMAT_SLINEAR) {
05132       if (!p->subs[index].linear) {
05133          p->subs[index].linear = 1;
05134          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05135          if (res)
05136             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05137       }
05138       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05139    } else {
05140       /* x-law already */
05141       if (p->subs[index].linear) {
05142          p->subs[index].linear = 0;
05143          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05144          if (res)
05145             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05146       }
05147       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05148    }
05149    if (res < 0) {
05150       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05151       return -1;
05152    } 
05153    return 0;
05154 }
05155 
05156 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05157 {
05158    struct dahdi_pvt *p = chan->tech_pvt;
05159    int res=-1;
05160    int index;
05161    int func = DAHDI_FLASH;
05162    ast_mutex_lock(&p->lock);
05163    index = dahdi_get_index(chan, p, 0);
05164    if (option_debug)
05165       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05166    if (index == SUB_REAL) {
05167       switch (condition) {
05168       case AST_CONTROL_BUSY:
05169 #ifdef HAVE_PRI
05170          if (p->priindication_oob && p->sig == SIG_PRI) {
05171             chan->hangupcause = AST_CAUSE_USER_BUSY;
05172             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05173             res = 0;
05174          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05175             if (p->pri->pri) {      
05176                if (!pri_grab(p, p->pri)) {
05177                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05178                   pri_rel(p->pri);
05179                }
05180                else
05181                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05182             }
05183             p->progress = 1;
05184             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05185          } else
05186 #endif
05187             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05188          break;
05189       case AST_CONTROL_RINGING:
05190 #ifdef HAVE_PRI
05191          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05192             if (p->pri->pri) {      
05193                if (!pri_grab(p, p->pri)) {
05194                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05195                   pri_rel(p->pri);
05196                }
05197                else
05198                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05199             }
05200             p->alerting = 1;
05201          }
05202 #endif
05203          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05204          if (chan->_state != AST_STATE_UP) {
05205             if ((chan->_state != AST_STATE_RING) ||
05206                ((p->sig != SIG_FXSKS) &&
05207                 (p->sig != SIG_FXSLS) &&
05208                 (p->sig != SIG_FXSGS)))
05209                ast_setstate(chan, AST_STATE_RINGING);
05210          }
05211          break;
05212       case AST_CONTROL_PROCEEDING:
05213          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05214 #ifdef HAVE_PRI
05215          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05216             if (p->pri->pri) {      
05217                if (!pri_grab(p, p->pri)) {
05218                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05219                   pri_rel(p->pri);
05220                }
05221                else
05222                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05223             }
05224             p->proceeding = 1;
05225          }
05226 #endif
05227          /* don't continue in ast_indicate */
05228          res = 0;
05229          break;
05230       case AST_CONTROL_PROGRESS:
05231          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05232 #ifdef HAVE_PRI
05233          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05234          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05235             if (p->pri->pri) {      
05236                if (!pri_grab(p, p->pri)) {
05237                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05238                   pri_rel(p->pri);
05239                }
05240                else
05241                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05242             }
05243             p->progress = 1;
05244          }
05245 #endif
05246          /* don't continue in ast_indicate */
05247          res = 0;
05248          break;
05249       case AST_CONTROL_CONGESTION:
05250          chan->hangupcause = AST_CAUSE_CONGESTION;
05251 #ifdef HAVE_PRI
05252          if (p->priindication_oob && p->sig == SIG_PRI) {
05253             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05254             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05255             res = 0;
05256          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05257             if (p->pri) {     
05258                if (!pri_grab(p, p->pri)) {
05259                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05260                   pri_rel(p->pri);
05261                } else
05262                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05263             }
05264             p->progress = 1;
05265             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05266          } else
05267 #endif
05268             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05269          break;
05270       case AST_CONTROL_HOLD:
05271 #ifdef HAVE_PRI
05272          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05273             if (!pri_grab(p, p->pri)) {
05274                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05275                pri_rel(p->pri);
05276             } else
05277                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05278          } else
05279 #endif
05280             ast_moh_start(chan, data, p->mohinterpret);
05281          break;
05282       case AST_CONTROL_UNHOLD:
05283 #ifdef HAVE_PRI
05284          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05285             if (!pri_grab(p, p->pri)) {
05286                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05287                pri_rel(p->pri);
05288             } else
05289                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05290          } else
05291 #endif
05292             ast_moh_stop(chan);
05293          break;
05294       case AST_CONTROL_RADIO_KEY:
05295          if (p->radio) 
05296              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05297          res = 0;
05298          break;
05299       case AST_CONTROL_RADIO_UNKEY:
05300          if (p->radio)
05301              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05302          res = 0;
05303          break;
05304       case AST_CONTROL_FLASH:
05305          /* flash hookswitch */
05306          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05307             /* Clear out the dial buffer */
05308             p->dop.dialstr[0] = '\0';
05309             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05310                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05311                   chan->name, strerror(errno));
05312             } else
05313                res = 0;
05314          } else
05315             res = 0;
05316          break;
05317       case AST_CONTROL_SRCUPDATE:
05318          res = 0;
05319          break;
05320       case -1:
05321          res = tone_zone_play_tone(p->subs[index].dfd, -1);
05322          break;
05323       }
05324    } else
05325       res = 0;
05326    ast_mutex_unlock(&p->lock);
05327    return res;
05328 }
05329 
05330 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05331 {
05332    struct ast_channel *tmp;
05333    int deflaw;
05334    int res;
05335    int x,y;
05336    int features;
05337    char *b2 = NULL;
05338    struct dahdi_params ps;
05339    char chanprefix[*dahdi_chan_name_len + 4];
05340 
05341    if (i->subs[index].owner) {
05342       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05343       return NULL;
05344    }
05345    y = 1;
05346    do {
05347       if (b2)
05348          free(b2);
05349 #ifdef HAVE_PRI
05350       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05351          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05352       else
05353 #endif
05354       if (i->channel == CHAN_PSEUDO)
05355          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05356       else  
05357          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05358       for (x = 0; x < 3; x++) {
05359          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05360             break;
05361       }
05362       y++;
05363    } while (x < 3);
05364    strcpy(chanprefix, dahdi_chan_name);
05365    strcat(chanprefix, "/%s");
05366    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05367    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05368       free(b2);
05369    if (!tmp)
05370       return NULL;
05371    tmp->tech = chan_tech;
05372    ps.channo = i->channel;
05373    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05374    if (res) {
05375       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05376       ps.curlaw = DAHDI_LAW_MULAW;
05377    }
05378    if (ps.curlaw == DAHDI_LAW_ALAW)
05379       deflaw = AST_FORMAT_ALAW;
05380    else
05381       deflaw = AST_FORMAT_ULAW;
05382    if (law) {
05383       if (law == DAHDI_LAW_ALAW)
05384          deflaw = AST_FORMAT_ALAW;
05385       else
05386          deflaw = AST_FORMAT_ULAW;
05387    }
05388    tmp->fds[0] = i->subs[index].dfd;
05389    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05390    /* Start out assuming ulaw since it's smaller :) */
05391    tmp->rawreadformat = deflaw;
05392    tmp->readformat = deflaw;
05393    tmp->rawwriteformat = deflaw;
05394    tmp->writeformat = deflaw;
05395    i->subs[index].linear = 0;
05396    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05397    features = 0;
05398    if (index == SUB_REAL) {
05399       if (i->busydetect && CANBUSYDETECT(i))
05400          features |= DSP_FEATURE_BUSY_DETECT;
05401       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05402          features |= DSP_FEATURE_CALL_PROGRESS;
05403       if ((!i->outgoing && (i->callprogress & 4)) || 
05404           (i->outgoing && (i->callprogress & 2))) {
05405          features |= DSP_FEATURE_FAX_DETECT;
05406       }
05407 #ifdef DAHDI_TONEDETECT
05408       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05409       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05410 #endif      
05411          i->hardwaredtmf = 0;
05412          features |= DSP_FEATURE_DTMF_DETECT;
05413 #ifdef DAHDI_TONEDETECT
05414       } else if (NEED_MFDETECT(i)) {
05415          i->hardwaredtmf = 1;
05416          features |= DSP_FEATURE_DTMF_DETECT;
05417       }
05418 #endif
05419    }
05420    if (features) {
05421       if (i->dsp) {
05422          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05423       } else {
05424          if (i->channel != CHAN_PSEUDO)
05425             i->dsp = ast_dsp_new();
05426          else
05427             i->dsp = NULL;
05428          if (i->dsp) {
05429             i->dsp_features = features;
05430 #ifdef HAVE_PRI
05431             /* We cannot do progress detection until receives PROGRESS message */
05432             if (i->outgoing && (i->sig == SIG_PRI)) {
05433                /* Remember requested DSP features, don't treat
05434                   talking as ANSWER */
05435                i->dsp_features = features & ~DSP_PROGRESS_TALK;
05436                features = 0;
05437             }
05438 #endif
05439             ast_dsp_set_features(i->dsp, features);
05440             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05441             if (!ast_strlen_zero(progzone))
05442                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05443             if (i->busydetect && CANBUSYDETECT(i)) {
05444                if(i->silencethreshold > 0)
05445                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05446                ast_dsp_set_busy_count(i->dsp, i->busycount);
05447                if(i->busytonelength > 0)
05448                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05449                if((i->busytonelength == i->busyquietlength) && i->busycompare)
05450                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05451             }
05452          }
05453       }
05454    }
05455       
05456    if (state == AST_STATE_RING)
05457       tmp->rings = 1;
05458    tmp->tech_pvt = i;
05459    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05460       /* Only FXO signalled stuff can be picked up */
05461       tmp->callgroup = i->callgroup;
05462       tmp->pickupgroup = i->pickupgroup;
05463    }
05464    if (!ast_strlen_zero(i->language))
05465       ast_string_field_set(tmp, language, i->language);
05466    if (!i->owner)
05467       i->owner = tmp;
05468    if (!ast_strlen_zero(i->accountcode))
05469       ast_string_field_set(tmp, accountcode, i->accountcode);
05470    if (i->amaflags)
05471       tmp->amaflags = i->amaflags;
05472    i->subs[index].owner = tmp;
05473    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05474    ast_string_field_set(tmp, call_forward, i->call_forward);
05475    /* If we've been told "no ADSI" then enforce it */
05476    if (!i->adsi)
05477       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05478    if (!ast_strlen_zero(i->exten))
05479       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05480    if (!ast_strlen_zero(i->rdnis))
05481       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05482    if (!ast_strlen_zero(i->dnid))
05483       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05484 
05485    /* Don't use ast_set_callerid() here because it will
05486     * generate a needless NewCallerID event */
05487 #ifdef PRI_ANI
05488    if (!ast_strlen_zero(i->cid_ani))
05489       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05490    else  
05491       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05492 #else
05493    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05494 #endif
05495    tmp->cid.cid_pres = i->callingpres;
05496    tmp->cid.cid_ton = i->cid_ton;
05497 #ifdef HAVE_PRI
05498    tmp->transfercapability = transfercapability;
05499    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05500    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05501       i->digital = 1;
05502    /* Assume calls are not idle calls unless we're told differently */
05503    i->isidlecall = 0;
05504    i->alreadyhungup = 0;
05505 #endif
05506    /* clear the fake event in case we posted one before we had ast_channel */
05507    i->fake_event = 0;
05508    /* Assure there is no confmute on this channel */
05509    dahdi_confmute(i, 0);
05510    /* Configure the new channel jb */
05511    ast_jb_configure(tmp, &global_jbconf);
05512    if (startpbx) {
05513       if (ast_pbx_start(tmp)) {
05514          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05515          ast_hangup(tmp);
05516          i->owner = NULL;
05517          return NULL;
05518       }
05519    }
05520 
05521    ast_module_ref(ast_module_info->self);
05522    
05523    return tmp;
05524 }
05525 
05526 
05527 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05528 {
05529    char c;
05530 
05531    *str = 0; /* start with empty output buffer */
05532    for (;;)
05533    {
05534       /* Wait for the first digit (up to specified ms). */
05535       c = ast_waitfordigit(chan, ms);
05536       /* if timeout, hangup or error, return as such */
05537       if (c < 1)
05538          return c;
05539       *str++ = c;
05540       *str = 0;
05541       if (strchr(term, c))
05542          return 1;
05543    }
05544 }
05545 
05546 static int dahdi_wink(struct dahdi_pvt *p, int index)
05547 {
05548    int j;
05549    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05550    for (;;)
05551    {
05552          /* set bits of interest */
05553       j = DAHDI_IOMUX_SIGEVENT;
05554           /* wait for some happening */
05555       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05556          /* exit loop if we have it */
05557       if (j & DAHDI_IOMUX_SIGEVENT) break;
05558    }
05559      /* get the event info */
05560    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05561    return 0;
05562 }
05563 
05564 static void *ss_thread(void *data)
05565 {
05566    struct ast_channel *chan = data;
05567    struct dahdi_pvt *p = chan->tech_pvt;
05568    char exten[AST_MAX_EXTENSION] = "";
05569    char exten2[AST_MAX_EXTENSION] = "";
05570    unsigned char buf[256];
05571    char dtmfcid[300];
05572    char dtmfbuf[300];
05573    struct callerid_state *cs = NULL;
05574    char *name = NULL, *number = NULL;
05575    int distMatches;
05576    int curRingData[3];
05577    int receivedRingT;
05578    int counter1;
05579    int counter;
05580    int samples = 0;
05581    struct ast_smdi_md_message *smdi_msg = NULL;
05582    int flags;
05583    int i;
05584    int timeout;
05585    int getforward = 0;
05586    char *s1, *s2;
05587    int len = 0;
05588    int res;
05589    int index;
05590 
05591    ast_mutex_lock(&ss_thread_lock);
05592    ss_thread_count++;
05593    ast_mutex_unlock(&ss_thread_lock);
05594    /* in the bizarre case where the channel has become a zombie before we
05595       even get started here, abort safely
05596    */
05597    if (!p) {
05598       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05599       ast_hangup(chan);
05600       goto quit;
05601    }
05602    if (option_verbose > 2) 
05603       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05604    index = dahdi_get_index(chan, p, 1);
05605    if (index < 0) {
05606       ast_log(LOG_WARNING, "Huh?\n");
05607       ast_hangup(chan);
05608       goto quit;
05609    }
05610    if (p->dsp)
05611       ast_dsp_digitreset(p->dsp);
05612    switch (p->sig) {
05613 #ifdef HAVE_PRI
05614    case SIG_PRI:
05615       /* Now loop looking for an extension */
05616       ast_copy_string(exten, p->exten, sizeof(exten));
05617       len = strlen(exten);
05618       res = 0;
05619       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05620          if (len && !ast_ignore_pattern(chan->context, exten))
05621             tone_zone_play_tone(p->subs[index].dfd, -1);
05622          else
05623             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05624          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05625             timeout = matchdigittimeout;
05626          else
05627             timeout = gendigittimeout;
05628          res = ast_waitfordigit(chan, timeout);
05629          if (res < 0) {
05630             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05631             ast_hangup(chan);
05632             goto quit;
05633          } else if (res) {
05634             exten[len++] = res;
05635             exten[len] = '\0';
05636          } else
05637             break;
05638       }
05639       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05640       if (ast_strlen_zero(exten)) {
05641          if (option_verbose > 2)
05642             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05643          exten[0] = 's';
05644          exten[1] = '\0';
05645       }
05646       tone_zone_play_tone(p->subs[index].dfd, -1);
05647       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05648          /* Start the real PBX */
05649          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05650          if (p->dsp) ast_dsp_digitreset(p->dsp);
05651          dahdi_enable_ec(p);
05652          ast_setstate(chan, AST_STATE_RING);
05653          res = ast_pbx_run(chan);
05654          if (res) {
05655             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05656          }
05657       } else {
05658          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05659          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05660          ast_hangup(chan);
05661          p->exten[0] = '\0';
05662          /* Since we send release complete here, we won't get one */
05663          p->call = NULL;
05664       }
05665       goto quit;
05666       break;
05667 #endif
05668    case SIG_FEATD:
05669    case SIG_FEATDMF:
05670    case SIG_FEATDMF_TA:
05671    case SIG_E911:
05672    case SIG_FGC_CAMAMF:
05673    case SIG_FEATB:
05674    case SIG_EMWINK:
05675    case SIG_SF_FEATD:
05676    case SIG_SF_FEATDMF:
05677    case SIG_SF_FEATB:
05678    case SIG_SFWINK:
05679       if (dahdi_wink(p, index))  
05680          goto quit;
05681       /* Fall through */
05682    case SIG_EM:
05683    case SIG_EM_E1:
05684    case SIG_SF:
05685    case SIG_FGC_CAMA:
05686       res = tone_zone_play_tone(p->subs[index].dfd, -1);
05687       if (p->dsp)
05688          ast_dsp_digitreset(p->dsp);
05689       /* set digit mode appropriately */
05690       if (p->dsp) {
05691          if (NEED_MFDETECT(p))
05692             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
05693          else 
05694             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05695       }
05696       memset(dtmfbuf, 0, sizeof(dtmfbuf));
05697       /* Wait for the first digit only if immediate=no */
05698       if (!p->immediate)
05699          /* Wait for the first digit (up to 5 seconds). */
05700          res = ast_waitfordigit(chan, 5000);
05701       else
05702          res = 0;
05703       if (res > 0) {
05704          /* save first char */
05705          dtmfbuf[0] = res;
05706          switch (p->sig) {
05707          case SIG_FEATD:
05708          case SIG_SF_FEATD:
05709             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05710             if (res > 0)
05711                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05712             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05713             break;
05714          case SIG_FEATDMF_TA:
05715             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05716             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05717             if (dahdi_wink(p, index)) goto quit;
05718             dtmfbuf[0] = 0;
05719             /* Wait for the first digit (up to 5 seconds). */
05720             res = ast_waitfordigit(chan, 5000);
05721             if (res <= 0) break;
05722             dtmfbuf[0] = res;
05723             /* fall through intentionally */
05724          case SIG_FEATDMF:
05725          case SIG_E911:
05726          case SIG_FGC_CAMAMF:
05727          case SIG_SF_FEATDMF:
05728             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05729             /* if international caca, do it again to get real ANO */
05730             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05731             {
05732                if (dahdi_wink(p, index)) goto quit;
05733                dtmfbuf[0] = 0;
05734                /* Wait for the first digit (up to 5 seconds). */
05735                res = ast_waitfordigit(chan, 5000);
05736                if (res <= 0) break;
05737                dtmfbuf[0] = res;
05738                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05739             }
05740             if (res > 0) {
05741                /* if E911, take off hook */
05742                if (p->sig == SIG_E911)
05743                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05744                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05745             }
05746             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05747             break;
05748          case SIG_FEATB:
05749          case SIG_SF_FEATB:
05750             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05751             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05752             break;
05753          case SIG_EMWINK:
05754             /* if we received a '*', we are actually receiving Feature Group D
05755                dial syntax, so use that mode; otherwise, fall through to normal
05756                mode
05757             */
05758             if (res == '*') {
05759                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05760                if (res > 0)
05761                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05762                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05763                break;
05764             }
05765          default:
05766             /* If we got the first digit, get the rest */
05767             len = 1;
05768             dtmfbuf[len] = '\0';
05769             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05770                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05771                   timeout = matchdigittimeout;
05772                } else {
05773                   timeout = gendigittimeout;
05774                }
05775                res = ast_waitfordigit(chan, timeout);
05776                if (res < 0) {
05777                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05778                   ast_hangup(chan);
05779                   goto quit;
05780                } else if (res) {
05781                   dtmfbuf[len++] = res;
05782                   dtmfbuf[len] = '\0';
05783                } else {
05784                   break;
05785                }
05786             }
05787             break;
05788          }
05789       }
05790       if (res == -1) {
05791          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05792          ast_hangup(chan);
05793          goto quit;
05794       } else if (res < 0) {
05795          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05796          ast_hangup(chan);
05797          goto quit;
05798       }
05799 
05800       if (p->sig == SIG_FGC_CAMA) {
05801          char anibuf[100];
05802 
05803          if (ast_safe_sleep(chan,1000) == -1) {
05804                            ast_hangup(chan);
05805                            goto quit;
05806          }
05807                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05808                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05809                         res = my_getsigstr(chan, anibuf, "#", 10000);
05810                         if ((res > 0) && (strlen(anibuf) > 2)) {
05811             if (anibuf[strlen(anibuf) - 1] == '#')
05812                anibuf[strlen(anibuf) - 1] = 0;
05813             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05814          }
05815                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05816       }
05817 
05818       ast_copy_string(exten, dtmfbuf, sizeof(exten));
05819       if (ast_strlen_zero(exten))
05820          ast_copy_string(exten, "s", sizeof(exten));
05821       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05822          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
05823          if (exten[0] == '*') {
05824             char *stringp=NULL;
05825             ast_copy_string(exten2, exten, sizeof(exten2));
05826             /* Parse out extension and callerid */
05827             stringp=exten2 +1;
05828             s1 = strsep(&stringp, "*");
05829             s2 = strsep(&stringp, "*");
05830             if (s2) {
05831                if (!ast_strlen_zero(p->cid_num))
05832                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05833                else
05834                   ast_set_callerid(chan, s1, NULL, s1);
05835                ast_copy_string(exten, s2, sizeof(exten));
05836             } else
05837                ast_copy_string(exten, s1, sizeof(exten));
05838          } else if (p->sig == SIG_FEATD)
05839             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05840       }
05841       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05842          if (exten[0] == '*') {
05843             char *stringp=NULL;
05844             ast_copy_string(exten2, exten, sizeof(exten2));
05845             /* Parse out extension and callerid */
05846             stringp=exten2 +1;
05847             s1 = strsep(&stringp, "#");
05848             s2 = strsep(&stringp, "#");
05849             if (s2) {
05850                if (!ast_strlen_zero(p->cid_num))
05851                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05852                else
05853                   if (*(s1 + 2))
05854                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05855                ast_copy_string(exten, s2 + 1, sizeof(exten));
05856             } else
05857                ast_copy_string(exten, s1 + 2, sizeof(exten));
05858          } else
05859             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05860       }
05861       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05862          if (exten[0] == '*') {
05863             char *stringp=NULL;
05864             ast_copy_string(exten2, exten, sizeof(exten2));
05865             /* Parse out extension and callerid */
05866             stringp=exten2 +1;
05867             s1 = strsep(&stringp, "#");
05868             s2 = strsep(&stringp, "#");
05869             if (s2 && (*(s2 + 1) == '0')) {
05870                if (*(s2 + 2))
05871                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05872             }
05873             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
05874             else ast_copy_string(exten, "911", sizeof(exten));
05875          } else
05876             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05877       }
05878       if (p->sig == SIG_FEATB) {
05879          if (exten[0] == '*') {
05880             char *stringp=NULL;
05881             ast_copy_string(exten2, exten, sizeof(exten2));
05882             /* Parse out extension and callerid */
05883             stringp=exten2 +1;
05884             s1 = strsep(&stringp, "#");
05885             ast_copy_string(exten, exten2 + 1, sizeof(exten));
05886          } else
05887             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05888       }
05889       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05890          dahdi_wink(p, index);
05891                         /* some switches require a minimum guard time between
05892                            the last FGD wink and something that answers
05893                            immediately. This ensures it */
05894                         if (ast_safe_sleep(chan,100)) goto quit;
05895       }
05896       dahdi_enable_ec(p);
05897       if (NEED_MFDETECT(p)) {
05898          if (p->dsp) {
05899             if (!p->hardwaredtmf)
05900                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
05901             else {
05902                ast_dsp_free(p->dsp);
05903                p->dsp = NULL;
05904             }
05905          }
05906       }
05907 
05908       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05909          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05910          if (p->dsp) ast_dsp_digitreset(p->dsp);
05911          res = ast_pbx_run(chan);
05912          if (res) {
05913             ast_log(LOG_WARNING, "PBX exited non-zero\n");
05914             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05915          }
05916          goto quit;
05917       } else {
05918          if (option_verbose > 2)
05919             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05920          sleep(2);
05921          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
05922          if (res < 0)
05923             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05924          else
05925             sleep(1);
05926          res = ast_streamfile(chan, "ss-noservice", chan->language);
05927          if (res >= 0)
05928             ast_waitstream(chan, "");
05929          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05930          ast_hangup(chan);
05931          goto quit;
05932       }
05933       break;
05934    case SIG_FXOLS:
05935    case SIG_FXOGS:
05936    case SIG_FXOKS:
05937       /* Read the first digit */
05938       timeout = firstdigittimeout;
05939       /* If starting a threeway call, never timeout on the first digit so someone
05940          can use flash-hook as a "hold" feature */
05941       if (p->subs[SUB_THREEWAY].owner) 
05942          timeout = 999999;
05943       while (len < AST_MAX_EXTENSION-1) {
05944          /* Read digit unless it's supposed to be immediate, in which case the
05945             only answer is 's' */
05946          if (p->immediate) 
05947             res = 's';
05948          else
05949             res = ast_waitfordigit(chan, timeout);
05950          timeout = 0;
05951          if (res < 0) {
05952             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05953             res = tone_zone_play_tone(p->subs[index].dfd, -1);
05954             ast_hangup(chan);
05955             goto quit;
05956          } else if (res)  {
05957             exten[len++]=res;
05958             exten[len] = '\0';
05959          }
05960          if (!ast_ignore_pattern(chan->context, exten))
05961             tone_zone_play_tone(p->subs[index].dfd, -1);
05962          else
05963             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05964          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05965             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05966                if (getforward) {
05967                   /* Record this as the forwarding extension */
05968                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
05969                   if (option_verbose > 2)
05970                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05971                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
05972                   if (res)
05973                      break;
05974                   usleep(500000);
05975                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05976                   sleep(1);
05977                   memset(exten, 0, sizeof(exten));
05978                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05979                   len = 0;
05980                   getforward = 0;
05981                } else  {
05982                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05983                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05984                   if (!ast_strlen_zero(p->cid_num)) {
05985                      if (!p->hidecallerid)
05986                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
05987                      else
05988                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
05989                   }
05990                   if (!ast_strlen_zero(p->cid_name)) {
05991                      if (!p->hidecallerid)
05992                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
05993                   }
05994                   ast_setstate(chan, AST_STATE_RING);
05995                   dahdi_enable_ec(p);
05996                   res = ast_pbx_run(chan);
05997                   if (res) {
05998                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
05999                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06000                   }
06001                   goto quit;
06002                }
06003             } else {
06004                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06005                   so just set the timeout to matchdigittimeout and wait some more */
06006                timeout = matchdigittimeout;
06007             }
06008          } else if (res == 0) {
06009             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06010             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06011             dahdi_wait_event(p->subs[index].dfd);
06012             ast_hangup(chan);
06013             goto quit;
06014          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06015             if (option_verbose > 2) 
06016                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06017             /* Disable call waiting if enabled */
06018             p->callwaiting = 0;
06019             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06020             if (res) {
06021                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06022                   chan->name, strerror(errno));
06023             }
06024             len = 0;
06025             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06026             memset(exten, 0, sizeof(exten));
06027             timeout = firstdigittimeout;
06028                
06029          } else if (!strcmp(exten,ast_pickup_ext())) {
06030             /* Scan all channels and see if there are any
06031              * ringing channels that have call groups
06032              * that equal this channels pickup group  
06033              */
06034             if (index == SUB_REAL) {
06035                /* Switch us from Third call to Call Wait */
06036                if (p->subs[SUB_THREEWAY].owner) {
06037                   /* If you make a threeway call and the *8# a call, it should actually 
06038                      look like a callwait */
06039                   alloc_sub(p, SUB_CALLWAIT);   
06040                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06041                   unalloc_sub(p, SUB_THREEWAY);
06042                }
06043                dahdi_enable_ec(p);
06044                if (ast_pickup_call(chan)) {
06045                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
06046                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06047                   dahdi_wait_event(p->subs[index].dfd);
06048                }
06049                ast_hangup(chan);
06050                goto quit;
06051             } else {
06052                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
06053                ast_hangup(chan);
06054                goto quit;
06055             }
06056             
06057          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06058             if (option_verbose > 2) 
06059                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06060             /* Disable Caller*ID if enabled */
06061             p->hidecallerid = 1;
06062             if (chan->cid.cid_num)
06063                free(chan->cid.cid_num);
06064             chan->cid.cid_num = NULL;
06065             if (chan->cid.cid_name)
06066                free(chan->cid.cid_name);
06067             chan->cid.cid_name = NULL;
06068             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06069             if (res) {
06070                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06071                   chan->name, strerror(errno));
06072             }
06073             len = 0;
06074             memset(exten, 0, sizeof(exten));
06075             timeout = firstdigittimeout;
06076          } else if (p->callreturn && !strcmp(exten, "*69")) {
06077             res = 0;
06078             if (!ast_strlen_zero(p->lastcid_num)) {
06079                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06080             }
06081             if (!res)
06082                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06083             break;
06084          } else if (!strcmp(exten, "*78")) {
06085             /* Do not disturb */
06086             if (option_verbose > 2)
06087                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06088             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06089                      "Channel: %s/%d\r\n"
06090                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
06091             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06092             p->dnd = 1;
06093             getforward = 0;
06094             memset(exten, 0, sizeof(exten));
06095             len = 0;
06096          } else if (!strcmp(exten, "*79")) {
06097             /* Do not disturb */
06098             if (option_verbose > 2)
06099                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06100             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06101                      "Channel: %s/%d\r\n"
06102                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
06103             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06104             p->dnd = 0;
06105             getforward = 0;
06106             memset(exten, 0, sizeof(exten));
06107             len = 0;
06108          } else if (p->cancallforward && !strcmp(exten, "*72")) {
06109             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06110             getforward = 1;
06111             memset(exten, 0, sizeof(exten));
06112             len = 0;
06113          } else if (p->cancallforward && !strcmp(exten, "*73")) {
06114             if (option_verbose > 2)
06115                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06116             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06117             memset(p->call_forward, 0, sizeof(p->call_forward));
06118             getforward = 0;
06119             memset(exten, 0, sizeof(exten));
06120             len = 0;
06121          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
06122                   p->subs[SUB_THREEWAY].owner &&
06123                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06124             /* This is a three way call, the main call being a real channel, 
06125                and we're parking the first call. */
06126             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06127             if (option_verbose > 2)
06128                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06129             break;
06130          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06131             if (option_verbose > 2)
06132                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06133             res = ast_db_put("blacklist", p->lastcid_num, "1");
06134             if (!res) {
06135                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06136                memset(exten, 0, sizeof(exten));
06137                len = 0;
06138             }
06139          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06140             if (option_verbose > 2) 
06141                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06142             /* Enable Caller*ID if enabled */
06143             p->hidecallerid = 0;
06144             if (chan->cid.cid_num)
06145                free(chan->cid.cid_num);
06146             chan->cid.cid_num = NULL;
06147             if (chan->cid.cid_name)
06148                free(chan->cid.cid_name);
06149             chan->cid.cid_name = NULL;
06150             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06151             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06152             if (res) {
06153                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06154                   chan->name, strerror(errno));
06155             }
06156             len = 0;
06157             memset(exten, 0, sizeof(exten));
06158             timeout = firstdigittimeout;
06159          } else if (!strcmp(exten, "*0")) {
06160             struct ast_channel *nbridge = 
06161                p->subs[SUB_THREEWAY].owner;
06162             struct dahdi_pvt *pbridge = NULL;
06163               /* set up the private struct of the bridged one, if any */
06164             if (nbridge && ast_bridged_channel(nbridge)) 
06165                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06166             if (nbridge && pbridge && 
06167                 (nbridge->tech == chan_tech) && 
06168                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06169                 ISTRUNK(pbridge)) {
06170                int func = DAHDI_FLASH;
06171                /* Clear out the dial buffer */
06172                p->dop.dialstr[0] = '\0';
06173                /* flash hookswitch */
06174                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06175                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06176                      nbridge->name, strerror(errno));
06177                }
06178                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06179                unalloc_sub(p, SUB_THREEWAY);
06180                p->owner = p->subs[SUB_REAL].owner;
06181                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06182                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06183                ast_hangup(chan);
06184                goto quit;
06185             } else {
06186                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06187                dahdi_wait_event(p->subs[index].dfd);
06188                tone_zone_play_tone(p->subs[index].dfd, -1);
06189                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06190                unalloc_sub(p, SUB_THREEWAY);
06191                p->owner = p->subs[SUB_REAL].owner;
06192                ast_hangup(chan);
06193                goto quit;
06194             }              
06195          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06196                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06197             if (option_debug)
06198                ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
06199             break;
06200          }
06201          if (!timeout)
06202             timeout = gendigittimeout;
06203          if (len && !ast_ignore_pattern(chan->context, exten))
06204             tone_zone_play_tone(p->subs[index].dfd, -1);
06205       }
06206       break;
06207    case SIG_FXSLS:
06208    case SIG_FXSGS:
06209    case SIG_FXSKS:
06210 #ifdef HAVE_PRI
06211       if (p->pri) {
06212          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06213          struct ast_frame *f;
06214          int res;
06215          time_t start;
06216 
06217          time(&start);
06218          ast_setstate(chan, AST_STATE_RING);
06219          while (time(NULL) < start + 3) {
06220             res = ast_waitfor(chan, 1000);
06221             if (res) {
06222                f = ast_read(chan);
06223                if (!f) {
06224                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06225                   ast_hangup(chan);
06226                   goto quit;
06227                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06228                   res = 1;
06229                } else
06230                   res = 0;
06231                ast_frfree(f);
06232                if (res) {
06233                   ast_log(LOG_DEBUG, "Got ring!\n");
06234                   res = 0;
06235                   break;
06236                }
06237             }
06238          }
06239       }
06240 #endif
06241       /* check for SMDI messages */
06242       if (p->use_smdi && p->smdi_iface) {
06243          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06244 
06245          if (smdi_msg != NULL) {
06246             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06247 
06248             if (smdi_msg->type == 'B')
06249                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06250             else if (smdi_msg->type == 'N')
06251                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06252 
06253             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06254          } else {
06255             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06256          }
06257       }
06258 
06259       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06260             number = smdi_msg->calling_st;
06261 
06262       /* If we want caller id, we're in a prering state due to a polarity reversal
06263        * and we're set to use a polarity reversal to trigger the start of caller id,
06264        * grab the caller id and wait for ringing to start... */
06265       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06266          /* If set to use DTMF CID signalling, listen for DTMF */
06267          if (p->cid_signalling == CID_SIG_DTMF) {
06268             int i = 0;
06269             cs = NULL;
06270             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06271                "channel %s\n", chan->name);
06272             dahdi_setlinear(p->subs[index].dfd, 0);
06273             res = 2000;
06274             for (;;) {
06275                struct ast_frame *f;
06276                res = ast_waitfor(chan, res);
06277                if (res <= 0) {
06278                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06279                      "Exiting simple switch\n");
06280                   ast_hangup(chan);
06281                   goto quit;
06282                } 
06283                f = ast_read(chan);
06284                if (!f)
06285                   break;
06286                if (f->frametype == AST_FRAME_DTMF) {
06287                   dtmfbuf[i++] = f->subclass;
06288                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06289                   res = 2000;
06290                }
06291                ast_frfree(f);
06292                if (chan->_state == AST_STATE_RING ||
06293                    chan->_state == AST_STATE_RINGING) 
06294                   break; /* Got ring */
06295             }
06296             dtmfbuf[i] = '\0';
06297             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06298             /* Got cid and ring. */
06299             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06300             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06301             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06302                dtmfcid, flags);
06303             /* If first byte is NULL, we have no cid */
06304             if (!ast_strlen_zero(dtmfcid)) 
06305                number = dtmfcid;
06306             else
06307                number = NULL;
06308          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06309          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06310             cs = callerid_new(p->cid_signalling);
06311             if (cs) {
06312                samples = 0;
06313 #if 1
06314                bump_gains(p);
06315 #endif            
06316                /* Take out of linear mode for Caller*ID processing */
06317                dahdi_setlinear(p->subs[index].dfd, 0);
06318                
06319                /* First we wait and listen for the Caller*ID */
06320                for (;;) {  
06321                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06322                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06323                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06324                      callerid_free(cs);
06325                      ast_hangup(chan);
06326                      goto quit;
06327                   }
06328                   if (i & DAHDI_IOMUX_SIGEVENT) {
06329                      res = dahdi_get_event(p->subs[index].dfd);
06330                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06331 
06332                      if (p->cid_signalling == CID_SIG_V23_JP) {
06333 #ifdef DAHDI_EVENT_RINGBEGIN
06334                         if (res == DAHDI_EVENT_RINGBEGIN) {
06335                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06336                            usleep(1);
06337                         }
06338 #endif
06339                      } else {
06340                         res = 0;
06341                         break;
06342                      }
06343                   } else if (i & DAHDI_IOMUX_READ) {
06344                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06345                      if (res < 0) {
06346                         if (errno != ELAST) {
06347                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06348                            callerid_free(cs);
06349                            ast_hangup(chan);
06350                            goto quit;
06351                         }
06352                         break;
06353                      }
06354                      samples += res;
06355 
06356                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06357                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06358                      } else {
06359                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06360                      }
06361 
06362                      if (res < 0) {
06363                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06364                         break;
06365                      } else if (res)
06366                         break;
06367                      else if (samples > (8000 * 10))
06368                         break;
06369                   }
06370                }
06371                if (res == 1) {
06372                   callerid_get(cs, &name, &number, &flags);
06373                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06374                }
06375 
06376                if (p->cid_signalling == CID_SIG_V23_JP) {
06377                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06378                   usleep(1);
06379                   res = 4000;
06380                } else {
06381 
06382                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06383                   res = 2000;
06384                }
06385 
06386                for (;;) {
06387                   struct ast_frame *f;
06388                   res = ast_waitfor(chan, res);
06389                   if (res <= 0) {
06390                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06391                         "Exiting simple switch\n");
06392                      ast_hangup(chan);
06393                      goto quit;
06394                   } 
06395                   if (!(f = ast_read(chan))) {
06396                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06397                      ast_hangup(chan);
06398                      goto quit;
06399                   }
06400                   ast_frfree(f);
06401                   if (chan->_state == AST_STATE_RING ||
06402                       chan->_state == AST_STATE_RINGING) 
06403                      break; /* Got ring */
06404                }
06405    
06406                /* We must have a ring by now, so, if configured, lets try to listen for
06407                 * distinctive ringing */ 
06408                if (p->usedistinctiveringdetection == 1) {
06409                   len = 0;
06410                   distMatches = 0;
06411                   /* Clear the current ring data array so we dont have old data in it. */
06412                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06413                      curRingData[receivedRingT] = 0;
06414                   receivedRingT = 0;
06415                   counter = 0;
06416                   counter1 = 0;
06417                   /* Check to see if context is what it should be, if not set to be. */
06418                   if (strcmp(p->context,p->defcontext) != 0) {
06419                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06420                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06421                   }
06422       
06423                   for (;;) {  
06424                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06425                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06426                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06427                         callerid_free(cs);
06428                         ast_hangup(chan);
06429                         goto quit;
06430                      }
06431                      if (i & DAHDI_IOMUX_SIGEVENT) {
06432                         res = dahdi_get_event(p->subs[index].dfd);
06433                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06434                         res = 0;
06435                         /* Let us detect distinctive ring */
06436       
06437                         curRingData[receivedRingT] = p->ringt;
06438       
06439                         if (p->ringt < p->ringt_base/2)
06440                            break;
06441                         /* Increment the ringT counter so we can match it against
06442                            values in chan_dahdi.conf for distinctive ring */
06443                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06444                            break;
06445                      } else if (i & DAHDI_IOMUX_READ) {
06446                         res = read(p->subs[index].dfd, buf, sizeof(buf));
06447                         if (res < 0) {
06448                            if (errno != ELAST) {
06449                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06450                               callerid_free(cs);
06451                               ast_hangup(chan);
06452                               goto quit;
06453                            }
06454                            break;
06455                         }
06456                         if (p->ringt) 
06457                            p->ringt--;
06458                         if (p->ringt == 1) {
06459                            res = -1;
06460                            break;
06461                         }
06462                      }
06463                   }
06464                   if (option_verbose > 2)
06465                      /* this only shows up if you have n of the dring patterns filled in */
06466                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06467    
06468                   for (counter = 0; counter < 3; counter++) {
06469                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06470                      channel */
06471                      distMatches = 0;
06472                      for (counter1 = 0; counter1 < 3; counter1++) {
06473                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06474                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06475                            distMatches++;
06476                         }
06477                      }
06478                      if (distMatches == 3) {
06479                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06480                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06481                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06482                         if (option_verbose > 2)
06483                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06484                         break;
06485                      }
06486                   }
06487                }
06488                /* Restore linear mode (if appropriate) for Caller*ID processing */
06489                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06490 #if 1
06491                restore_gains(p);
06492 #endif            
06493             } else
06494                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06495          } else {
06496             ast_log(LOG_WARNING, "Channel %s in prering "
06497                "state, but I have nothing to do. "
06498                "Terminating simple switch, should be "
06499                "restarted by the actual ring.\n", 
06500                chan->name);
06501             ast_hangup(chan);
06502             goto quit;
06503          }
06504       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06505          /* FSK Bell202 callerID */
06506          cs = callerid_new(p->cid_signalling);
06507          if (cs) {
06508 #if 1
06509             bump_gains(p);
06510 #endif            
06511             samples = 0;
06512             len = 0;
06513             distMatches = 0;
06514             /* Clear the current ring data array so we dont have old data in it. */
06515             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06516                curRingData[receivedRingT] = 0;
06517             receivedRingT = 0;
06518             counter = 0;
06519             counter1 = 0;
06520             /* Check to see if context is what it should be, if not set to be. */
06521             if (strcmp(p->context,p->defcontext) != 0) {
06522                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06523                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06524             }
06525 
06526             /* Take out of linear mode for Caller*ID processing */
06527             dahdi_setlinear(p->subs[index].dfd, 0);
06528             for (;;) {  
06529                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06530                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06531                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06532                   callerid_free(cs);
06533                   ast_hangup(chan);
06534                   goto quit;
06535                }
06536                if (i & DAHDI_IOMUX_SIGEVENT) {
06537                   res = dahdi_get_event(p->subs[index].dfd);
06538                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06539                   /* If we get a PR event, they hung up while processing calerid */
06540                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06541                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06542                      p->polarity = POLARITY_IDLE;
06543                      callerid_free(cs);
06544                      ast_hangup(chan);
06545                      goto quit;
06546                   }
06547                   res = 0;
06548                   /* Let us detect callerid when the telco uses distinctive ring */
06549 
06550                   curRingData[receivedRingT] = p->ringt;
06551 
06552                   if (p->ringt < p->ringt_base/2)
06553                      break;
06554                   /* Increment the ringT counter so we can match it against
06555                      values in chan_dahdi.conf for distinctive ring */
06556                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06557                      break;
06558                } else if (i & DAHDI_IOMUX_READ) {
06559                   res = read(p->subs[index].dfd, buf, sizeof(buf));
06560                   if (res < 0) {
06561                      if (errno != ELAST) {
06562                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06563                         callerid_free(cs);
06564                         ast_hangup(chan);
06565                         goto quit;
06566                      }
06567                      break;
06568                   }
06569                   if (p->ringt) 
06570                      p->ringt--;
06571                   if (p->ringt == 1) {
06572                      res = -1;
06573                      break;
06574                   }
06575                   samples += res;
06576                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06577                   if (res < 0) {
06578                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06579                      break;
06580                   } else if (res)
06581                      break;
06582                   else if (samples > (8000 * 10))
06583                      break;
06584                }
06585             }
06586             if (res == 1) {
06587                callerid_get(cs, &name, &number, &flags);
06588                if (option_debug)
06589                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06590             }
06591             if (distinctiveringaftercid == 1) {
06592                /* Clear the current ring data array so we dont have old data in it. */
06593                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06594                   curRingData[receivedRingT] = 0;
06595                }
06596                receivedRingT = 0;
06597                if (option_verbose > 2)
06598                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06599                for (;;) {
06600                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06601                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
06602                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06603                      callerid_free(cs);
06604                      ast_hangup(chan);
06605                      goto quit;
06606                   }
06607                   if (i & DAHDI_IOMUX_SIGEVENT) {
06608                      res = dahdi_get_event(p->subs[index].dfd);
06609                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06610                      res = 0;
06611                      /* Let us detect callerid when the telco uses distinctive ring */
06612 
06613                      curRingData[receivedRingT] = p->ringt;
06614 
06615                      if (p->ringt < p->ringt_base/2)
06616                         break;
06617                      /* Increment the ringT counter so we can match it against
06618                         values in chan_dahdi.conf for distinctive ring */
06619                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06620                         break;
06621                   } else if (i & DAHDI_IOMUX_READ) {
06622                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06623                      if (res < 0) {
06624                         if (errno != ELAST) {
06625                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06626                            callerid_free(cs);
06627                            ast_hangup(chan);
06628                            goto quit;
06629                         }
06630                         break;
06631                      }
06632                   if (p->ringt)
06633                      p->ringt--;
06634                      if (p->ringt == 1) {
06635                         res = -1;
06636                         break;
06637                      }
06638                   }
06639                }
06640             }
06641             if (p->usedistinctiveringdetection == 1) {
06642                if (option_verbose > 2)
06643                   /* this only shows up if you have n of the dring patterns filled in */
06644                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06645 
06646                for (counter = 0; counter < 3; counter++) {
06647                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06648                   channel */
06649                   if (option_verbose > 2)
06650                      /* this only shows up if you have n of the dring patterns filled in */
06651                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06652                         p->drings.ringnum[counter].ring[0],
06653                         p->drings.ringnum[counter].ring[1],
06654                         p->drings.ringnum[counter].ring[2]);
06655                   distMatches = 0;
06656                   for (counter1 = 0; counter1 < 3; counter1++) {
06657                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06658                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06659                         distMatches++;
06660                      }
06661                   }
06662                   if (distMatches == 3) {
06663                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06664                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06665                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06666                      if (option_verbose > 2)
06667                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06668                      break;
06669                   }
06670                }
06671             }
06672             /* Restore linear mode (if appropriate) for Caller*ID processing */
06673             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06674 #if 1
06675             restore_gains(p);
06676 #endif            
06677             if (res < 0) {
06678                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06679             }
06680          } else
06681             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06682       }
06683       else
06684          cs = NULL;
06685 
06686       if (number)
06687          ast_shrink_phone_number(number);
06688       ast_set_callerid(chan, number, name, number);
06689 
06690       if (smdi_msg)
06691          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06692 
06693       if (cs)
06694          callerid_free(cs);
06695 
06696       ast_setstate(chan, AST_STATE_RING);
06697       chan->rings = 1;
06698       p->ringt = p->ringt_base;
06699       res = ast_pbx_run(chan);
06700       if (res) {
06701          ast_hangup(chan);
06702          ast_log(LOG_WARNING, "PBX exited non-zero\n");
06703       }
06704       goto quit;
06705    default:
06706       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06707       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06708       if (res < 0)
06709             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06710    }
06711    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06712    if (res < 0)
06713          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06714    ast_hangup(chan);
06715 quit:
06716    ast_mutex_lock(&ss_thread_lock);
06717    ss_thread_count--;
06718    ast_cond_signal(&ss_thread_complete);
06719    ast_mutex_unlock(&ss_thread_lock);
06720    return NULL;
06721 }
06722 
06723 /* destroy a DAHDI channel, identified by its number */
06724 static int dahdi_destroy_channel_bynum(int channel)
06725 {
06726    struct dahdi_pvt *tmp = NULL;
06727    struct dahdi_pvt *prev = NULL;
06728 
06729    tmp = iflist;
06730    while (tmp) {
06731       if (tmp->channel == channel) {
06732          int x = DAHDI_FLASH;
06733          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
06734          destroy_channel(prev, tmp, 1);
06735          ast_module_unref(ast_module_info->self);
06736          return RESULT_SUCCESS;
06737       }
06738       prev = tmp;
06739       tmp = tmp->next;
06740    }
06741    return RESULT_FAILURE;
06742 }
06743 
06744 static int handle_init_event(struct dahdi_pvt *i, int event)
06745 {
06746    int res;
06747    pthread_t threadid;
06748    pthread_attr_t attr;
06749    struct ast_channel *chan;
06750    pthread_attr_init(&attr);
06751    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06752    /* Handle an event on a given channel for the monitor thread. */
06753    switch (event) {
06754    case DAHDI_EVENT_NONE:
06755    case DAHDI_EVENT_BITSCHANGED:
06756       break;
06757    case DAHDI_EVENT_WINKFLASH:
06758    case DAHDI_EVENT_RINGOFFHOOK:
06759       if (i->inalarm) break;
06760       if (i->radio) break;
06761       /* Got a ring/answer.  What kind of channel are we? */
06762       switch (i->sig) {
06763       case SIG_FXOLS:
06764       case SIG_FXOGS:
06765       case SIG_FXOKS:
06766          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06767          if (res && (errno == EBUSY))
06768             break;
06769          if (i->cidspill) {
06770             /* Cancel VMWI spill */
06771             free(i->cidspill);
06772             i->cidspill = NULL;
06773          }
06774          if (i->immediate) {
06775             dahdi_enable_ec(i);
06776             /* The channel is immediately up.  Start right away */
06777             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06778             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06779             if (!chan) {
06780                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06781                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06782                if (res < 0)
06783                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06784             }
06785          } else {
06786             /* Check for callerid, digits, etc */
06787             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06788             if (chan) {
06789                if (has_voicemail(i))
06790                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06791                else
06792                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06793                if (res < 0) 
06794                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06795                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06796                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06797                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06798                   if (res < 0)
06799                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06800                   ast_hangup(chan);
06801                }
06802             } else
06803                ast_log(LOG_WARNING, "Unable to create channel\n");
06804          }
06805          break;
06806       case SIG_FXSLS:
06807       case SIG_FXSGS:
06808       case SIG_FXSKS:
06809             i->ringt = i->ringt_base;
06810             /* Fall through */
06811       case SIG_EMWINK:
06812       case SIG_FEATD:
06813       case SIG_FEATDMF:
06814       case SIG_FEATDMF_TA:
06815       case SIG_E911:
06816       case SIG_FGC_CAMA:
06817       case SIG_FGC_CAMAMF:
06818       case SIG_FEATB:
06819       case SIG_EM:
06820       case SIG_EM_E1:
06821       case SIG_SFWINK:
06822       case SIG_SF_FEATD:
06823       case SIG_SF_FEATDMF:
06824       case SIG_SF_FEATB:
06825       case SIG_SF:
06826             /* Check for callerid, digits, etc */
06827             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06828             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06829                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06830                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06831                if (res < 0)
06832                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06833                ast_hangup(chan);
06834             } else if (!chan) {
06835                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06836             }
06837             break;
06838       default:
06839          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06840          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06841          if (res < 0)
06842                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06843          return -1;
06844       }
06845       break;
06846    case DAHDI_EVENT_NOALARM:
06847       i->inalarm = 0;
06848       if (!i->unknown_alarm) {
06849          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06850          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06851                   "Channel: %d\r\n", i->channel);
06852       } else {
06853          i->unknown_alarm = 0;
06854       }
06855       break;
06856    case DAHDI_EVENT_ALARM:
06857       i->inalarm = 1;
06858       res = get_alarms(i);
06859       handle_alarms(i, res);
06860       /* fall thru intentionally */
06861    case DAHDI_EVENT_ONHOOK:
06862       if (i->radio)
06863          break;
06864       /* Back on hook.  Hang up. */
06865       switch (i->sig) {
06866       case SIG_FXOLS:
06867       case SIG_FXOGS:
06868       case SIG_FEATD:
06869       case SIG_FEATDMF:
06870       case SIG_FEATDMF_TA:
06871       case SIG_E911:
06872       case SIG_FGC_CAMA:
06873       case SIG_FGC_CAMAMF:
06874       case SIG_FEATB:
06875       case SIG_EM:
06876       case SIG_EM_E1:
06877       case SIG_EMWINK:
06878       case SIG_SF_FEATD:
06879       case SIG_SF_FEATDMF:
06880       case SIG_SF_FEATB:
06881       case SIG_SF:
06882       case SIG_SFWINK:
06883       case SIG_FXSLS:
06884       case SIG_FXSGS:
06885       case SIG_FXSKS:
06886       case SIG_GR303FXSKS:
06887          dahdi_disable_ec(i);
06888          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06889          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06890          break;
06891       case SIG_GR303FXOKS:
06892       case SIG_FXOKS:
06893          dahdi_disable_ec(i);
06894          /* Diddle the battery for the zhone */
06895 #ifdef ZHONE_HACK
06896          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06897          usleep(1);
06898 #endif         
06899          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06900          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06901          break;
06902       case SIG_PRI:
06903          dahdi_disable_ec(i);
06904          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06905          break;
06906       default:
06907          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06908          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06909          return -1;
06910       }
06911       break;
06912    case DAHDI_EVENT_POLARITY:
06913       switch (i->sig) {
06914       case SIG_FXSLS:
06915       case SIG_FXSKS:
06916       case SIG_FXSGS:
06917          /* We have already got a PR before the channel was 
06918             created, but it wasn't handled. We need polarity 
06919             to be REV for remote hangup detection to work. 
06920             At least in Spain */
06921          if (i->hanguponpolarityswitch)
06922             i->polarity = POLARITY_REV;
06923 
06924          if (i->cid_start == CID_START_POLARITY) {
06925             i->polarity = POLARITY_REV;
06926             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06927                    "CID detection on channel %d\n",
06928                    i->channel);
06929             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06930             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06931                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06932             }
06933          }
06934          break;
06935       default:
06936          ast_log(LOG_WARNING, "handle_init_event detected "
06937             "polarity reversal on non-FXO (SIG_FXS) "
06938             "interface %d\n", i->channel);
06939       }
06940       break;
06941    case DAHDI_EVENT_REMOVED: /* destroy channel */
06942       ast_log(LOG_NOTICE, 
06943             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
06944             i->channel);
06945       dahdi_destroy_channel_bynum(i->channel);
06946       break;
06947    }
06948    pthread_attr_destroy(&attr);
06949    return 0;
06950 }
06951 
06952 static void *do_monitor(void *data)
06953 {
06954    int count, res, res2, spoint, pollres=0;
06955    struct dahdi_pvt *i;
06956    struct dahdi_pvt *last = NULL;
06957    time_t thispass = 0, lastpass = 0;
06958    int found;
06959    char buf[1024];
06960    struct pollfd *pfds=NULL;
06961    int lastalloc = -1;
06962    /* This thread monitors all the frame relay interfaces which are not yet in use
06963       (and thus do not have a separate thread) indefinitely */
06964    /* From here on out, we die whenever asked */
06965 #if 0
06966    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06967       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06968       return NULL;
06969    }
06970    ast_log(LOG_DEBUG, "Monitor starting...\n");
06971 #endif
06972    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
06973 
06974    for (;;) {
06975       /* Lock the interface list */
06976       ast_mutex_lock(&iflock);
06977       if (!pfds || (lastalloc != ifcount)) {
06978          if (pfds) {
06979             free(pfds);
06980             pfds = NULL;
06981          }
06982          if (ifcount) {
06983             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06984                ast_mutex_unlock(&iflock);
06985                return NULL;
06986             }
06987          }
06988          lastalloc = ifcount;
06989       }
06990       /* Build the stuff we're going to poll on, that is the socket of every
06991          dahdi_pvt that does not have an associated owner channel */
06992       count = 0;
06993       i = iflist;
06994       while (i) {
06995          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
06996             if (!i->owner && !i->subs[SUB_REAL].owner) {
06997                /* This needs to be watched, as it lacks an owner */
06998                pfds[count].fd = i->subs[SUB_REAL].dfd;
06999                pfds[count].events = POLLPRI;
07000                pfds[count].revents = 0;
07001                /* Message waiting or r2 channels also get watched for reading */
07002                if (i->cidspill)
07003                   pfds[count].events |= POLLIN;
07004                count++;
07005             }
07006          }
07007          i = i->next;
07008       }
07009       /* Okay, now that we know what to do, release the interface lock */
07010       ast_mutex_unlock(&iflock);
07011       
07012       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07013       pthread_testcancel();
07014       /* Wait at least a second for something to happen */
07015       res = poll(pfds, count, 1000);
07016       pthread_testcancel();
07017       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07018 
07019       /* Okay, poll has finished.  Let's see what happened.  */
07020       if (res < 0) {
07021          if ((errno != EAGAIN) && (errno != EINTR))
07022             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07023          continue;
07024       }
07025       /* Alright, lock the interface list again, and let's look and see what has
07026          happened */
07027       ast_mutex_lock(&iflock);
07028       found = 0;
07029       spoint = 0;
07030       lastpass = thispass;
07031       thispass = time(NULL);
07032       i = iflist;
07033       while (i) {
07034          if (thispass != lastpass) {
07035             if (!found && ((i == last) || ((i == iflist) && !last))) {
07036                last = i;
07037                if (last) {
07038                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07039                      (last->sig & __DAHDI_SIG_FXO)) {
07040                      res = ast_app_has_voicemail(last->mailbox, NULL);
07041                      if (last->msgstate != res) {
07042                         int x;
07043                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07044                         x = DAHDI_FLUSH_BOTH;
07045                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07046                         if (res2)
07047                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07048                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07049                            /* Turn on on hook transfer for 4 seconds */
07050                            x = 4000;
07051                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07052                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07053                            last->cidpos = 0;
07054                            last->msgstate = res;
07055                            last->onhooktime = thispass;
07056                         }
07057                         found ++;
07058                      }
07059                   }
07060                   last = last->next;
07061                }
07062             }
07063          }
07064          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07065             if (i->radio && !i->owner)
07066             {
07067                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07068                if (res)
07069                {
07070                   if (option_debug)
07071                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07072                   /* Don't hold iflock while handling init events */
07073                   ast_mutex_unlock(&iflock);
07074                   handle_init_event(i, res);
07075                   ast_mutex_lock(&iflock);   
07076                }
07077                i = i->next;
07078                continue;
07079             }              
07080             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07081             if (pollres & POLLIN) {
07082                if (i->owner || i->subs[SUB_REAL].owner) {
07083 #ifdef HAVE_PRI
07084                   if (!i->pri)
07085 #endif                  
07086                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07087                   i = i->next;
07088                   continue;
07089                }
07090                if (!i->cidspill) {
07091                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07092                   i = i->next;
07093                   continue;
07094                }
07095                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07096                if (res > 0) {
07097                   /* We read some number of bytes.  Write an equal amount of data */
07098                   if (res > i->cidlen - i->cidpos) 
07099                      res = i->cidlen - i->cidpos;
07100                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07101                   if (res2 > 0) {
07102                      i->cidpos += res2;
07103                      if (i->cidpos >= i->cidlen) {
07104                         free(i->cidspill);
07105                         i->cidspill = 0;
07106                         i->cidpos = 0;
07107                         i->cidlen = 0;
07108                      }
07109                   } else {
07110                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07111                      i->msgstate = -1;
07112                   }
07113                } else {
07114                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07115                }
07116             }
07117             if (pollres & POLLPRI) {
07118                if (i->owner || i->subs[SUB_REAL].owner) {
07119 #ifdef HAVE_PRI
07120                   if (!i->pri)
07121 #endif                  
07122                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07123                   i = i->next;
07124                   continue;
07125                }
07126                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07127                if (option_debug)
07128                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07129                /* Don't hold iflock while handling init events */
07130                ast_mutex_unlock(&iflock);
07131                handle_init_event(i, res);
07132                ast_mutex_lock(&iflock);   
07133             }
07134          }
07135          i=i->next;
07136       }
07137       ast_mutex_unlock(&iflock);
07138    }
07139    /* Never reached */
07140    return NULL;
07141    
07142 }
07143 
07144 static int restart_monitor(void)
07145 {
07146    pthread_attr_t attr;
07147    pthread_attr_init(&attr);
07148    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07149    /* If we're supposed to be stopped -- stay stopped */
07150    if (monitor_thread == AST_PTHREADT_STOP)
07151       return 0;
07152    ast_mutex_lock(&monlock);
07153    if (monitor_thread == pthread_self()) {
07154       ast_mutex_unlock(&monlock);
07155       ast_log(LOG_WARNING, "Cannot kill myself\n");
07156       return -1;
07157    }
07158    if (monitor_thread != AST_PTHREADT_NULL) {
07159       /* Wake up the thread */
07160       pthread_kill(monitor_thread, SIGURG);
07161    } else {
07162       /* Start a new monitor */
07163       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07164          ast_mutex_unlock(&monlock);
07165          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07166          pthread_attr_destroy(&attr);
07167          return -1;
07168       }
07169    }
07170    ast_mutex_unlock(&monlock);
07171    pthread_attr_destroy(&attr);
07172    return 0;
07173 }
07174 
07175 #ifdef HAVE_PRI
07176 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07177 {
07178    int x;
07179    int trunkgroup;
07180    /* Get appropriate trunk group if there is one */
07181    trunkgroup = pris[*span].mastertrunkgroup;
07182    if (trunkgroup) {
07183       /* Select a specific trunk group */
07184       for (x = 0; x < NUM_SPANS; x++) {
07185          if (pris[x].trunkgroup == trunkgroup) {
07186             *span = x;
07187             return 0;
07188          }
07189       }
07190       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07191       *span = -1;
07192    } else {
07193       if (pris[*span].trunkgroup) {
07194          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07195          *span = -1;
07196       } else if (pris[*span].mastertrunkgroup) {
07197          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07198          *span = -1;
07199       } else {
07200          if (si->totalchans == 31) {
07201             /* E1 */
07202             pris[*span].dchannels[0] = 16 + offset;
07203          } else if (si->totalchans == 24) {
07204             /* T1 or J1 */
07205             pris[*span].dchannels[0] = 24 + offset;
07206          } else if (si->totalchans == 3) {
07207             /* BRI */
07208             pris[*span].dchannels[0] = 3 + offset;
07209          } else {
07210             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
07211             *span = -1;
07212             return 0;
07213          }
07214          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07215          pris[*span].offset = offset;
07216          pris[*span].span = *span + 1;
07217       }
07218    }
07219    return 0;
07220 }
07221 
07222 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07223 {
07224    struct dahdi_spaninfo si;
07225    struct dahdi_params p;
07226    int fd;
07227    int span;
07228    int ospan=0;
07229    int x,y;
07230    for (x = 0; x < NUM_SPANS; x++) {
07231       if (pris[x].trunkgroup == trunkgroup) {
07232          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07233          return -1;
07234       }
07235    }
07236    for (y = 0; y < NUM_DCHANS; y++) {
07237       if (!channels[y]) 
07238          break;
07239       memset(&si, 0, sizeof(si));
07240       memset(&p, 0, sizeof(p));
07241       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07242       if (fd < 0) {
07243          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07244          return -1;
07245       }
07246       x = channels[y];
07247       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07248          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07249          close(fd);
07250          return -1;
07251       }
07252       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07253          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07254          return -1;
07255       }
07256       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07257          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07258          close(fd);
07259          return -1;
07260       }
07261       span = p.spanno - 1;
07262       if (pris[span].trunkgroup) {
07263          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07264          close(fd);
07265          return -1;
07266       }
07267       if (pris[span].pvts[0]) {
07268          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07269          close(fd);
07270          return -1;
07271       }
07272       if (!y) {
07273          pris[span].trunkgroup = trunkgroup;
07274          pris[span].offset = channels[y] - p.chanpos;
07275          ospan = span;
07276       }
07277       pris[ospan].dchannels[y] = channels[y];
07278       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07279       pris[span].span = span + 1;
07280       close(fd);
07281    }
07282    return 0;   
07283 }
07284 
07285 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07286 {
07287    if (pris[span].mastertrunkgroup) {
07288       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
07289       return -1;
07290    }
07291    pris[span].mastertrunkgroup = trunkgroup;
07292    pris[span].prilogicalspan = logicalspan;
07293    return 0;
07294 }
07295 
07296 #endif
07297 
07298 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07299 {
07300    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
07301    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07302    char fn[80];
07303 #if 1
07304    struct dahdi_bufferinfo bi;
07305 #endif
07306    int res;
07307    int span=0;
07308    int here = 0;
07309    int x;
07310    struct dahdi_pvt **wlist;
07311    struct dahdi_pvt **wend;
07312    struct dahdi_params p;
07313 
07314    wlist = &iflist;
07315    wend = &ifend;
07316 
07317 #ifdef HAVE_PRI
07318    if (pri) {
07319       wlist = &pri->crvs;
07320       wend = &pri->crvend;
07321    }
07322 #endif
07323 
07324    tmp2 = *wlist;
07325    prev = NULL;
07326 
07327    while (tmp2) {
07328       if (!tmp2->destroy) {
07329          if (tmp2->channel == channel) {
07330             tmp = tmp2;
07331             here = 1;
07332             break;
07333          }
07334          if (tmp2->channel > channel) {
07335             break;
07336          }
07337       }
07338       prev = tmp2;
07339       tmp2 = tmp2->next;
07340    }
07341 
07342    if (!here && reloading != 1) {
07343       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07344          if (tmp)
07345             free(tmp);
07346          return NULL;
07347       }
07348       ast_mutex_init(&tmp->lock);
07349       ifcount++;
07350       for (x = 0; x < 3; x++)
07351          tmp->subs[x].dfd = -1;
07352       tmp->channel = channel;
07353    }
07354 
07355    if (tmp) {
07356       int chan_sig = conf->chan.sig;
07357       if (!here) {
07358          if ((channel != CHAN_PSEUDO) && !pri) {
07359             int count = 0;
07360             snprintf(fn, sizeof(fn), "%d", channel);
07361             /* Open non-blocking */
07362             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07363             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
07364                usleep(1);
07365                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07366                count++;
07367             }
07368             /* Allocate a DAHDI structure */
07369             if (tmp->subs[SUB_REAL].dfd < 0) {
07370                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
07371                destroy_dahdi_pvt(&tmp);
07372                return NULL;
07373             }
07374             memset(&p, 0, sizeof(p));
07375             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07376             if (res < 0) {
07377                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07378                destroy_dahdi_pvt(&tmp);
07379                return NULL;
07380             }
07381             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07382                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
07383                destroy_dahdi_pvt(&tmp);
07384                return NULL;
07385             }
07386             tmp->law = p.curlaw;
07387             tmp->span = p.spanno;
07388             span = p.spanno - 1;
07389          } else {
07390             if (channel == CHAN_PSEUDO)
07391                chan_sig = 0;
07392             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07393                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07394                return NULL;
07395             }
07396          }
07397 #ifdef HAVE_PRI
07398          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07399             int offset;
07400             int myswitchtype;
07401             int matchesdchan;
07402             int x,y;
07403             offset = 0;
07404             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07405                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07406                destroy_dahdi_pvt(&tmp);
07407                return NULL;
07408             }
07409             if (span >= NUM_SPANS) {
07410                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07411                destroy_dahdi_pvt(&tmp);
07412                return NULL;
07413             } else {
07414                struct dahdi_spaninfo si;
07415                si.spanno = 0;
07416                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07417                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07418                   destroy_dahdi_pvt(&tmp);
07419                   return NULL;
07420                }
07421                /* Store the logical span first based upon the real span */
07422                tmp->logicalspan = pris[span].prilogicalspan;
07423                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07424                if (span < 0) {
07425                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07426                   destroy_dahdi_pvt(&tmp);
07427                   return NULL;
07428                }
07429                if (chan_sig == SIG_PRI)
07430                   myswitchtype = conf->pri.switchtype;
07431                else
07432                   myswitchtype = PRI_SWITCH_GR303_TMC;
07433                /* Make sure this isn't a d-channel */
07434                matchesdchan=0;
07435                for (x = 0; x < NUM_SPANS; x++) {
07436                   for (y = 0; y < NUM_DCHANS; y++) {
07437                      if (pris[x].dchannels[y] == tmp->channel) {
07438                         matchesdchan = 1;
07439                         break;
07440                      }
07441                   }
07442                }
07443                offset = p.chanpos;
07444                if (!matchesdchan) {
07445                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07446                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07447                      destroy_dahdi_pvt(&tmp);
07448                      return NULL;
07449                   }
07450                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07451                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07452                      destroy_dahdi_pvt(&tmp);
07453                      return NULL;
07454                   }
07455                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07456                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07457                      destroy_dahdi_pvt(&tmp);
07458                      return NULL;
07459                   }
07460                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07461                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07462                      destroy_dahdi_pvt(&tmp);
07463                      return NULL;
07464                   }
07465                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07466                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07467                      destroy_dahdi_pvt(&tmp);
07468                      return NULL;
07469                   }
07470                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07471                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07472                      destroy_dahdi_pvt(&tmp);
07473                      return NULL;
07474                   }
07475                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07476                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07477                      destroy_dahdi_pvt(&tmp);
07478                      return NULL;
07479                   }
07480                   if (pris[span].numchans >= MAX_CHANNELS) {
07481                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07482                         pris[span].trunkgroup);
07483                      destroy_dahdi_pvt(&tmp);
07484                      return NULL;
07485                   }
07486                   pris[span].nodetype = conf->pri.nodetype;
07487                   pris[span].switchtype = myswitchtype;
07488                   pris[span].nsf = conf->pri.nsf;
07489                   pris[span].dialplan = conf->pri.dialplan;
07490                   pris[span].localdialplan = conf->pri.localdialplan;
07491                   pris[span].pvts[pris[span].numchans++] = tmp;
07492                   pris[span].minunused = conf->pri.minunused;
07493                   pris[span].minidle = conf->pri.minidle;
07494                   pris[span].overlapdial = conf->pri.overlapdial;
07495 #ifdef HAVE_PRI_INBANDDISCONNECT
07496                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07497 #endif
07498                   pris[span].facilityenable = conf->pri.facilityenable;
07499                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07500                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07501                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07502                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07503                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07504                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07505                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07506                   pris[span].resetinterval = conf->pri.resetinterval;
07507                   
07508                   tmp->pri = &pris[span];
07509                   tmp->prioffset = offset;
07510                   tmp->call = NULL;
07511                } else {
07512                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07513                   destroy_dahdi_pvt(&tmp);
07514                   return NULL;
07515                }
07516             }
07517          } else {
07518             tmp->prioffset = 0;
07519          }
07520 #endif
07521       } else {
07522          chan_sig = tmp->sig;
07523          memset(&p, 0, sizeof(p));
07524          if (tmp->subs[SUB_REAL].dfd > -1)
07525             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07526       }
07527       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07528       switch (chan_sig) {
07529       case SIG_FXSKS:
07530       case SIG_FXSLS:
07531       case SIG_EM:
07532       case SIG_EM_E1:
07533       case SIG_EMWINK:
07534       case SIG_FEATD:
07535       case SIG_FEATDMF:
07536       case SIG_FEATDMF_TA:
07537       case SIG_FEATB:
07538       case SIG_E911:
07539       case SIG_SF:
07540       case SIG_SFWINK:
07541       case SIG_FGC_CAMA:
07542       case SIG_FGC_CAMAMF:
07543       case SIG_SF_FEATD:
07544       case SIG_SF_FEATDMF:
07545       case SIG_SF_FEATB:
07546          p.starttime = 250;
07547          break;
07548       }
07549 
07550       if (tmp->radio) {
07551          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07552          p.channo = channel;
07553          p.rxwinktime = 1;
07554          p.rxflashtime = 1;
07555          p.starttime = 1;
07556          p.debouncetime = 5;
07557       }
07558       if (!tmp->radio) {
07559          p.channo = channel;
07560          /* Override timing settings based on config file */
07561          if (conf->timing.prewinktime >= 0)
07562             p.prewinktime = conf->timing.prewinktime;
07563          if (conf->timing.preflashtime >= 0)
07564             p.preflashtime = conf->timing.preflashtime;
07565          if (conf->timing.winktime >= 0)
07566             p.winktime = conf->timing.winktime;
07567          if (conf->timing.flashtime >= 0)
07568             p.flashtime = conf->timing.flashtime;
07569          if (conf->timing.starttime >= 0)
07570             p.starttime = conf->timing.starttime;
07571          if (conf->timing.rxwinktime >= 0)
07572             p.rxwinktime = conf->timing.rxwinktime;
07573          if (conf->timing.rxflashtime >= 0)
07574             p.rxflashtime = conf->timing.rxflashtime;
07575          if (conf->timing.debouncetime >= 0)
07576             p.debouncetime = conf->timing.debouncetime;
07577       }
07578       
07579       /* dont set parms on a pseudo-channel (or CRV) */
07580       if (tmp->subs[SUB_REAL].dfd >= 0)
07581       {
07582          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07583          if (res < 0) {
07584             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07585             destroy_dahdi_pvt(&tmp);
07586             return NULL;
07587          }
07588       }
07589 #if 1
07590       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07591          memset(&bi, 0, sizeof(bi));
07592          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07593          if (!res) {
07594             bi.txbufpolicy = conf->chan.buf_policy;
07595             bi.rxbufpolicy = conf->chan.buf_policy;
07596             bi.numbufs = conf->chan.buf_no;
07597             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07598             if (res < 0) {
07599                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07600             }
07601          } else
07602             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07603       }
07604 #endif
07605       tmp->immediate = conf->chan.immediate;
07606       tmp->transfertobusy = conf->chan.transfertobusy;
07607       tmp->sig = chan_sig;
07608       tmp->outsigmod = conf->chan.outsigmod;
07609       tmp->ringt_base = ringt_base;
07610       tmp->firstradio = 0;
07611       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07612          tmp->permcallwaiting = conf->chan.callwaiting;
07613       else
07614          tmp->permcallwaiting = 0;
07615       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07616       tmp->destroy = 0;
07617       tmp->drings = drings;
07618       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07619       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07620       tmp->threewaycalling = conf->chan.threewaycalling;
07621       tmp->adsi = conf->chan.adsi;
07622       tmp->use_smdi = conf->chan.use_smdi;
07623       tmp->permhidecallerid = conf->chan.hidecallerid;
07624       tmp->callreturn = conf->chan.callreturn;
07625       tmp->echocancel = conf->chan.echocancel;
07626       tmp->echotraining = conf->chan.echotraining;
07627       tmp->pulse = conf->chan.pulse;
07628       if (tmp->echocancel)
07629          tmp->echocanbridged = conf->chan.echocanbridged;
07630       else {
07631          if (conf->chan.echocanbridged)
07632             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07633          tmp->echocanbridged = 0;
07634       }
07635       tmp->busydetect = conf->chan.busydetect;
07636       tmp->busycount = conf->chan.busycount;
07637       tmp->busycompare = conf->chan.busycompare;
07638       tmp->busytonelength = conf->chan.busytonelength;
07639       tmp->busyquietlength = conf->chan.busyquietlength;
07640       tmp->busyfuzziness = conf->chan.busyfuzziness;
07641       tmp->silencethreshold = conf->chan.silencethreshold;
07642       tmp->callprogress = conf->chan.callprogress;
07643       tmp->cancallforward = conf->chan.cancallforward;
07644       tmp->dtmfrelax = conf->chan.dtmfrelax;
07645       tmp->callwaiting = tmp->permcallwaiting;
07646       tmp->hidecallerid = tmp->permhidecallerid;
07647       tmp->channel = channel;
07648       tmp->stripmsd = conf->chan.stripmsd;
07649       tmp->use_callerid = conf->chan.use_callerid;
07650       tmp->cid_signalling = conf->chan.cid_signalling;
07651       tmp->cid_start = conf->chan.cid_start;
07652       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07653       tmp->restrictcid = conf->chan.restrictcid;
07654       tmp->use_callingpres = conf->chan.use_callingpres;
07655       tmp->priindication_oob = conf->chan.priindication_oob;
07656       tmp->priexclusive = conf->chan.priexclusive;
07657       if (tmp->usedistinctiveringdetection) {
07658          if (!tmp->use_callerid) {
07659             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07660             tmp->use_callerid = 1;
07661          }
07662       }
07663 
07664       if (tmp->cid_signalling == CID_SIG_SMDI) {
07665          if (!tmp->use_smdi) {
07666             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07667             tmp->use_smdi = 1;
07668          }
07669       }
07670       if (tmp->use_smdi) {
07671          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07672          if (!(tmp->smdi_iface)) {
07673             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07674             tmp->use_smdi = 0;
07675          }
07676       }
07677 
07678       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07679       tmp->amaflags = conf->chan.amaflags;
07680       if (!here) {
07681          tmp->confno = -1;
07682          tmp->propconfno = -1;
07683       }
07684       tmp->canpark = conf->chan.canpark;
07685       tmp->transfer = conf->chan.transfer;
07686       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07687       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07688       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07689       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07690       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07691       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07692       tmp->cid_ton = 0;
07693       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07694       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07695       tmp->msgstate = -1;
07696       tmp->group = conf->chan.group;
07697       tmp->callgroup = conf->chan.callgroup;
07698       tmp->pickupgroup= conf->chan.pickupgroup;
07699       tmp->rxgain = conf->chan.rxgain;
07700       tmp->txgain = conf->chan.txgain;
07701       tmp->tonezone = conf->chan.tonezone;
07702       tmp->onhooktime = time(NULL);
07703       if (tmp->subs[SUB_REAL].dfd > -1) {
07704          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07705          if (tmp->dsp)
07706             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07707          update_conf(tmp);
07708          if (!here) {
07709             if (chan_sig != SIG_PRI)
07710                /* Hang it up to be sure it's good */
07711                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07712          }
07713          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
07714 #ifdef HAVE_PRI
07715          /* the dchannel is down so put the channel in alarm */
07716          if (tmp->pri && !pri_is_up(tmp->pri)) {
07717             tmp->inalarm = 1;
07718          }
07719 #endif            
07720          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
07721             tmp->inalarm = 1;
07722             handle_alarms(tmp, res);
07723          } else {
07724             /* yes, this looks strange... the unknown_alarm flag is only used to
07725                control whether an 'alarm cleared' message gets generated when we
07726                get an indication that the channel is no longer in alarm status.
07727                however, the channel *could* be in an alarm status that we aren't
07728                aware of (since get_alarms() only reports span alarms, not channel
07729                alarms). setting this flag will cause any potential 'alarm cleared'
07730                message to be suppressed, but if a real alarm occurs before that
07731                happens, this flag will get cleared by it and the situation will
07732                be normal.
07733             */
07734             tmp->unknown_alarm = 1;
07735          }
07736       }
07737 
07738       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07739       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07740       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07741       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07742 
07743    }
07744    if (tmp && !here) {
07745       /* nothing on the iflist */
07746       if (!*wlist) {
07747          *wlist = tmp;
07748          tmp->prev = NULL;
07749          tmp->next = NULL;
07750          *wend = tmp;
07751       } else {
07752          /* at least one member on the iflist */
07753          struct dahdi_pvt *working = *wlist;
07754 
07755          /* check if we maybe have to put it on the begining */
07756          if (working->channel > tmp->channel) {
07757             tmp->next = *wlist;
07758             tmp->prev = NULL;
07759             (*wlist)->prev = tmp;
07760             *wlist = tmp;
07761          } else {
07762          /* go through all the members and put the member in the right place */
07763             while (working) {
07764                /* in the middle */
07765                if (working->next) {
07766                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07767                      tmp->next = working->next;
07768                      tmp->prev = working;
07769                      working->next->prev = tmp;
07770                      working->next = tmp;
07771                      break;
07772                   }
07773                } else {
07774                /* the last */
07775                   if (working->channel < tmp->channel) {
07776                      working->next = tmp;
07777                      tmp->next = NULL;
07778                      tmp->prev = working;
07779                      *wend = tmp;
07780                      break;
07781                   }
07782                }
07783                working = working->next;
07784             }
07785          }
07786       }
07787    }
07788    return tmp;
07789 }
07790 
07791 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
07792 {
07793    int res;
07794    struct dahdi_params par;
07795 
07796    /* First, check group matching */
07797    if (groupmatch) {
07798       if ((p->group & groupmatch) != groupmatch)
07799          return 0;
07800       *groupmatched = 1;
07801    }
07802    /* Check to see if we have a channel match */
07803    if (channelmatch != -1) {
07804       if (p->channel != channelmatch)
07805          return 0;
07806       *channelmatched = 1;
07807    }
07808    /* We're at least busy at this point */
07809    if (busy) {
07810       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07811          *busy = 1;
07812    }
07813    /* If do not disturb, definitely not */
07814    if (p->dnd)
07815       return 0;
07816    /* If guard time, definitely not */
07817    if (p->guardtime && (time(NULL) < p->guardtime)) 
07818       return 0;
07819       
07820    /* If no owner definitely available */
07821    if (!p->owner) {
07822 #ifdef HAVE_PRI
07823       /* Trust PRI */
07824       if (p->pri) {
07825          if (p->resetting || p->call)
07826             return 0;
07827          else
07828             return 1;
07829       }
07830 #endif
07831       if (!(p->radio || (p->oprmode < 0)))
07832       {
07833          if (!p->sig || (p->sig == SIG_FXSLS))
07834             return 1;
07835          /* Check hook state */
07836          if (p->subs[SUB_REAL].dfd > -1)
07837             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
07838          else {
07839             /* Assume not off hook on CVRS */
07840             res = 0;
07841             par.rxisoffhook = 0;
07842          }
07843          if (res) {
07844             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
07845          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07846             /* When "onhook" that means no battery on the line, and thus
07847               it is out of service..., if it's on a TDM card... If it's a channel
07848               bank, there is no telling... */
07849             if (par.rxbits > -1)
07850                return 1;
07851             if (par.rxisoffhook)
07852                return 1;
07853             else
07854 #ifdef DAHDI_CHECK_HOOKSTATE
07855                return 0;
07856 #else
07857                return 1;
07858 #endif
07859          } else if (par.rxisoffhook) {
07860             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07861             /* Not available when the other end is off hook */
07862             return 0;
07863          }
07864       }
07865       return 1;
07866    }
07867 
07868    /* If it's not an FXO, forget about call wait */
07869    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07870       return 0;
07871 
07872    if (!p->callwaiting) {
07873       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07874       return 0;
07875    }
07876 
07877    if (p->subs[SUB_CALLWAIT].dfd > -1) {
07878       /* If there is already a call waiting call, then we can't take a second one */
07879       return 0;
07880    }
07881    
07882    if ((p->owner->_state != AST_STATE_UP) &&
07883        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07884       /* If the current call is not up, then don't allow the call */
07885       return 0;
07886    }
07887    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07888       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07889       return 0;
07890    }
07891    /* We're cool */
07892    return 1;
07893 }
07894 
07895 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
07896 {
07897    struct dahdi_pvt *p;
07898    struct dahdi_bufferinfo bi;
07899    int res;
07900    
07901    if ((p = ast_malloc(sizeof(*p)))) {
07902       memcpy(p, src, sizeof(struct dahdi_pvt));
07903       ast_mutex_init(&p->lock);
07904       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
07905       /* Allocate a DAHDI structure */
07906       if (p->subs[SUB_REAL].dfd < 0) {
07907          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07908          destroy_dahdi_pvt(&p);
07909          return NULL;
07910       }
07911       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07912       if (!res) {
07913          bi.txbufpolicy = p->buf_policy;
07914          bi.rxbufpolicy = p->buf_policy;
07915          bi.numbufs = p->buf_no;
07916          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07917          if (res < 0) {
07918             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
07919          }
07920       } else
07921          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
07922    }
07923    p->destroy = 1;
07924    p->next = iflist;
07925    p->prev = NULL;
07926    iflist = p;
07927    if (iflist->next)
07928       iflist->next->prev = p;
07929    return p;
07930 }
07931    
07932 
07933 #ifdef HAVE_PRI
07934 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
07935 {
07936    int x;
07937    if (backwards)
07938       x = pri->numchans;
07939    else
07940       x = 0;
07941    for (;;) {
07942       if (backwards && (x < 0))
07943          break;
07944       if (!backwards && (x >= pri->numchans))
07945          break;
07946       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
07947          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
07948             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
07949          return x;
07950       }
07951       if (backwards)
07952          x--;
07953       else
07954          x++;
07955    }
07956    return -1;
07957 }
07958 #endif
07959 
07960 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
07961 {
07962    ast_group_t groupmatch = 0;
07963    int channelmatch = -1;
07964    int roundrobin = 0;
07965    int callwait = 0;
07966    int busy = 0;
07967    struct dahdi_pvt *p;
07968    struct ast_channel *tmp = NULL;
07969    char *dest=NULL;
07970    int x;
07971    char *s;
07972    char opt=0;
07973    int res=0, y=0;
07974    int backwards = 0;
07975 #ifdef HAVE_PRI
07976    int crv;
07977    int bearer = -1;
07978    int trunkgroup;
07979    struct dahdi_pri *pri=NULL;
07980 #endif   
07981    struct dahdi_pvt *exit, *start, *end;
07982    ast_mutex_t *lock;
07983    int channelmatched = 0;
07984    int groupmatched = 0;
07985    
07986    /* Assume we're locking the iflock */
07987    lock = &iflock;
07988    start = iflist;
07989    end = ifend;
07990    if (data) {
07991       dest = ast_strdupa((char *)data);
07992    } else {
07993       ast_log(LOG_WARNING, "Channel requested with no data\n");
07994       return NULL;
07995    }
07996    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
07997       /* Retrieve the group number */
07998       char *stringp=NULL;
07999       stringp=dest + 1;
08000       s = strsep(&stringp, "/");
08001       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08002          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08003          return NULL;
08004       }
08005       groupmatch = ((ast_group_t) 1 << x);
08006       if (toupper(dest[0]) == 'G') {
08007          if (dest[0] == 'G') {
08008             backwards = 1;
08009             p = ifend;
08010          } else
08011             p = iflist;
08012       } else {
08013          if (dest[0] == 'R') {
08014             backwards = 1;
08015             p = round_robin[x]?round_robin[x]->prev:ifend;
08016             if (!p)
08017                p = ifend;
08018          } else {
08019             p = round_robin[x]?round_robin[x]->next:iflist;
08020             if (!p)
08021                p = iflist;
08022          }
08023          roundrobin = 1;
08024       }
08025    } else {
08026       char *stringp=NULL;
08027       stringp=dest;
08028       s = strsep(&stringp, "/");
08029       p = iflist;
08030       if (!strcasecmp(s, "pseudo")) {
08031          /* Special case for pseudo */
08032          x = CHAN_PSEUDO;
08033          channelmatch = x;
08034       } 
08035 #ifdef HAVE_PRI
08036       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08037          if ((trunkgroup < 1) || (crv < 1)) {
08038             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08039             return NULL;
08040          }
08041          res--;
08042          for (x = 0; x < NUM_SPANS; x++) {
08043             if (pris[x].trunkgroup == trunkgroup) {
08044                pri = pris + x;
08045                lock = &pri->lock;
08046                start = pri->crvs;
08047                end = pri->crvend;
08048                break;
08049             }
08050          }
08051          if (!pri) {
08052             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08053             return NULL;
08054          }
08055          channelmatch = crv;
08056          p = pris[x].crvs;
08057       }
08058 #endif   
08059       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08060          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08061          return NULL;
08062       } else {
08063          channelmatch = x;
08064       }
08065    }
08066    /* Search for an unowned channel */
08067    ast_mutex_lock(lock);
08068    exit = p;
08069    while (p && !tmp) {
08070       if (roundrobin)
08071          round_robin[x] = p;
08072 #if 0
08073       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08074 #endif
08075 
08076       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08077          if (option_debug)
08078             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08079             if (p->inalarm) 
08080                goto next;
08081 
08082          callwait = (p->owner != NULL);
08083 #ifdef HAVE_PRI
08084          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08085             if (p->sig != SIG_FXSKS) {
08086                /* Gotta find an actual channel to use for this
08087                   CRV if this isn't a callwait */
08088                bearer = pri_find_empty_chan(pri, 0);
08089                if (bearer < 0) {
08090                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08091                   p = NULL;
08092                   break;
08093                }
08094                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08095             } else {
08096                if (alloc_sub(p, 0)) {
08097                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08098                   p = NULL;
08099                   break;
08100                } else
08101                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08102                p->pri = pri;
08103             }
08104          }
08105 #endif         
08106          if (p->channel == CHAN_PSEUDO) {
08107             p = chandup(p);
08108             if (!p) {
08109                break;
08110             }
08111          }
08112          if (p->owner) {
08113             if (alloc_sub(p, SUB_CALLWAIT)) {
08114                p = NULL;
08115                break;
08116             }
08117          }
08118          p->outgoing = 1;
08119          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08120 #ifdef HAVE_PRI
08121          if (p->bearer) {
08122             /* Log owner to bearer channel, too */
08123             p->bearer->owner = tmp;
08124          }
08125 #endif         
08126          /* Make special notes */
08127          if (res > 1) {
08128             if (opt == 'c') {
08129                /* Confirm answer */
08130                p->confirmanswer = 1;
08131             } else if (opt == 'r') {
08132                /* Distinctive ring */
08133                if (res < 3)
08134                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08135                else
08136                   p->distinctivering = y;
08137             } else if (opt == 'd') {
08138                /* If this is an ISDN call, make it digital */
08139                p->digital = 1;
08140                if (tmp)
08141                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08142             } else {
08143                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08144             }
08145          }
08146          /* Note if the call is a call waiting call */
08147          if (tmp && callwait)
08148             tmp->cdrflags |= AST_CDR_CALLWAIT;
08149          break;
08150       }
08151 next:
08152       if (backwards) {
08153          p = p->prev;
08154          if (!p)
08155             p = end;
08156       } else {
08157          p = p->next;
08158          if (!p)
08159             p = start;
08160       }
08161       /* stop when you roll to the one that we started from */
08162       if (p == exit)
08163          break;
08164    }
08165    ast_mutex_unlock(lock);
08166    restart_monitor();
08167    if (callwait)
08168       *cause = AST_CAUSE_BUSY;
08169    else if (!tmp) {
08170       if (channelmatched) {
08171          if (busy)
08172             *cause = AST_CAUSE_BUSY;
08173       } else if (groupmatched) {
08174          *cause = AST_CAUSE_CONGESTION;
08175       }
08176    }
08177       
08178    return tmp;
08179 }
08180 
08181 
08182 #ifdef HAVE_PRI
08183 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08184 {
08185    struct dahdi_pvt *p;
08186    p = pri->crvs;
08187    while (p) {
08188       if (p->channel == crv)
08189          return p;
08190       p = p->next;
08191    }
08192    return NULL;
08193 }
08194 
08195 
08196 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08197 {
08198    int x;
08199    int span = PRI_SPAN(channel);
08200    int spanfd;
08201    struct dahdi_params param;
08202    int principle = -1;
08203    int explicit = PRI_EXPLICIT(channel);
08204    channel = PRI_CHANNEL(channel);
08205 
08206    if (!explicit) {
08207       spanfd = pri_active_dchan_fd(pri);
08208       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
08209          return -1;
08210       span = pris[param.spanno - 1].prilogicalspan;
08211    }
08212 
08213    for (x = 0; x < pri->numchans; x++) {
08214       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08215          principle = x;
08216          break;
08217       }
08218    }
08219    
08220    return principle;
08221 }
08222 
08223 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08224 {
08225    int x;
08226    struct dahdi_pvt *crv;
08227    if (!c) {
08228       if (principle < 0)
08229          return -1;
08230       return principle;
08231    }
08232    if ((principle > -1) && 
08233       (principle < pri->numchans) && 
08234       (pri->pvts[principle]) && 
08235       (pri->pvts[principle]->call == c))
08236       return principle;
08237    /* First, check for other bearers */
08238    for (x = 0; x < pri->numchans; x++) {
08239       if (!pri->pvts[x])
08240          continue;
08241       if (pri->pvts[x]->call == c) {
08242          /* Found our call */
08243          if (principle != x) {
08244             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08245 
08246             if (option_verbose > 2)
08247                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08248                   old->channel, new->channel);
08249             if (new->owner) {
08250                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08251                   old->channel, new->channel, new->channel);
08252                return -1;
08253             }
08254             /* Fix it all up now */
08255             new->owner = old->owner;
08256             old->owner = NULL;
08257             if (new->owner) {
08258                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08259                new->owner->tech_pvt = new;
08260                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08261                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08262                old->subs[SUB_REAL].owner = NULL;
08263             } else
08264                ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
08265             new->call = old->call;
08266             old->call = NULL;
08267 
08268             /* Copy any DSP that may be present */
08269             new->dsp = old->dsp;
08270             new->dsp_features = old->dsp_features;
08271             old->dsp = NULL;
08272             old->dsp_features = 0;
08273          }
08274          return principle;
08275       }
08276    }
08277    /* Now check for a CRV with no bearer */
08278    crv = pri->crvs;
08279    while (crv) {
08280       if (crv->call == c) {
08281          /* This is our match...  Perform some basic checks */
08282          if (crv->bearer)
08283             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08284          else if (pri->pvts[principle]->owner) 
08285             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08286          else {
08287             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
08288                wakeup the potential sleeper */
08289             dahdi_close_sub(crv, SUB_REAL);
08290             pri->pvts[principle]->call = crv->call;
08291             pri_assign_bearer(crv, pri, pri->pvts[principle]);
08292             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08293                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08294                            pri->trunkgroup, crv->channel);
08295             wakeup_sub(crv, SUB_REAL, pri);
08296          }
08297          return principle;
08298       }
08299       crv = crv->next;
08300    }
08301    ast_log(LOG_WARNING, "Call specified, but not found?\n");
08302    return -1;
08303 }
08304 
08305 static void *do_idle_thread(void *vchan)
08306 {
08307    struct ast_channel *chan = vchan;
08308    struct dahdi_pvt *pvt = chan->tech_pvt;
08309    struct ast_frame *f;
08310    char ex[80];
08311    /* Wait up to 30 seconds for an answer */
08312    int newms, ms = 30000;
08313    if (option_verbose > 2) 
08314       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08315    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08316    if (ast_call(chan, ex, 0)) {
08317       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08318       ast_hangup(chan);
08319       return NULL;
08320    }
08321    while ((newms = ast_waitfor(chan, ms)) > 0) {
08322       f = ast_read(chan);
08323       if (!f) {
08324          /* Got hangup */
08325          break;
08326       }
08327       if (f->frametype == AST_FRAME_CONTROL) {
08328          switch (f->subclass) {
08329          case AST_CONTROL_ANSWER:
08330             /* Launch the PBX */
08331             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08332             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08333             chan->priority = 1;
08334             if (option_verbose > 3) 
08335                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08336             ast_pbx_run(chan);
08337             /* It's already hungup, return immediately */
08338             return NULL;
08339          case AST_CONTROL_BUSY:
08340             if (option_verbose > 3) 
08341                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08342             break;
08343          case AST_CONTROL_CONGESTION:
08344             if (option_verbose > 3) 
08345                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08346             break;
08347          };
08348       }
08349       ast_frfree(f);
08350       ms = newms;
08351    }
08352    /* Hangup the channel since nothing happend */
08353    ast_hangup(chan);
08354    return NULL;
08355 }
08356 
08357 #ifndef PRI_RESTART
08358 #error "Upgrade your libpri"
08359 #endif
08360 static void dahdi_pri_message(struct pri *pri, char *s)
08361 {
08362    int x, y;
08363    int dchan = -1, span = -1;
08364    int dchancount = 0;
08365 
08366    if (pri) {
08367       for (x = 0; x < NUM_SPANS; x++) {
08368          for (y = 0; y < NUM_DCHANS; y++) {
08369             if (pris[x].dchans[y])
08370                dchancount++;
08371 
08372             if (pris[x].dchans[y] == pri)
08373                dchan = y;
08374          }
08375          if (dchan >= 0) {
08376             span = x;
08377             break;
08378          }
08379          dchancount = 0;
08380       }
08381       if ((dchan >= 0) && (span >= 0)) {
08382          if (dchancount > 1)
08383             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08384          else
08385             ast_verbose("%s", s);
08386       } else
08387          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08388    } else
08389       ast_verbose("%s", s);
08390 
08391    ast_mutex_lock(&pridebugfdlock);
08392 
08393    if (pridebugfd >= 0) {
08394       if (write(pridebugfd, s, strlen(s)) < 0) {
08395          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08396       }
08397    }
08398 
08399    ast_mutex_unlock(&pridebugfdlock);
08400 }
08401 
08402 static void dahdi_pri_error(struct pri *pri, char *s)
08403 {
08404    int x, y;
08405    int dchan = -1, span = -1;
08406    int dchancount = 0;
08407 
08408    if (pri) {
08409       for (x = 0; x < NUM_SPANS; x++) {
08410          for (y = 0; y < NUM_DCHANS; y++) {
08411             if (pris[x].dchans[y])
08412                dchancount++;
08413 
08414             if (pris[x].dchans[y] == pri)
08415                dchan = y;
08416          }
08417          if (dchan >= 0) {
08418             span = x;
08419             break;
08420          }
08421          dchancount = 0;
08422       }
08423       if ((dchan >= 0) && (span >= 0)) {
08424          if (dchancount > 1)
08425             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08426          else
08427             ast_log(LOG_ERROR, "%s", s);
08428       } else
08429          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08430    } else
08431       ast_log(LOG_ERROR, "%s", s);
08432 
08433    ast_mutex_lock(&pridebugfdlock);
08434 
08435    if (pridebugfd >= 0) {
08436       if (write(pridebugfd, s, strlen(s)) < 0) {
08437          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08438       }
08439    }
08440 
08441    ast_mutex_unlock(&pridebugfdlock);
08442 }
08443 
08444 static int pri_check_restart(struct dahdi_pri *pri)
08445 {
08446    do {
08447       pri->resetpos++;
08448    } while ((pri->resetpos < pri->numchans) &&
08449        (!pri->pvts[pri->resetpos] ||
08450         pri->pvts[pri->resetpos]->call ||
08451         pri->pvts[pri->resetpos]->resetting));
08452    if (pri->resetpos < pri->numchans) {
08453       /* Mark the channel as resetting and restart it */
08454       pri->pvts[pri->resetpos]->resetting = 1;
08455       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08456    } else {
08457       pri->resetting = 0;
08458       time(&pri->lastreset);
08459    }
08460    return 0;
08461 }
08462 
08463 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08464 {
08465    int x;
08466    int redo;
08467    ast_mutex_unlock(&pri->lock);
08468    ast_mutex_lock(&p->lock);
08469    do {
08470       redo = 0;
08471       for (x = 0; x < 3; x++) {
08472          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08473             redo++;
08474             DEADLOCK_AVOIDANCE(&p->lock);
08475          }
08476          if (p->subs[x].owner) {
08477             ast_queue_hangup(p->subs[x].owner);
08478             ast_mutex_unlock(&p->subs[x].owner->lock);
08479          }
08480       }
08481    } while (redo);
08482    ast_mutex_unlock(&p->lock);
08483    ast_mutex_lock(&pri->lock);
08484    return 0;
08485 }
08486 
08487 static char * redirectingreason2str(int redirectingreason)
08488 {
08489    switch (redirectingreason) {
08490    case 0:
08491       return "UNKNOWN";
08492    case 1:
08493       return "BUSY";
08494    case 2:
08495       return "NO_REPLY";
08496    case 0xF:
08497       return "UNCONDITIONAL";
08498    default:
08499       return "NOREDIRECT";
08500    }
08501 }
08502 
08503 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08504 {
08505    switch (plan) {
08506    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
08507       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08508       break;
08509    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
08510       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08511       break;
08512    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
08513       snprintf(buf, size, "%s%s", pri->localprefix, number);
08514       break;
08515    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
08516       snprintf(buf, size, "%s%s", pri->privateprefix, number);
08517       break;
08518    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
08519       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08520       break;
08521    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
08522       snprintf(buf, size, "%s", number);
08523       break;
08524    }
08525 }
08526 
08527 static int dahdi_setlaw(int dfd, int law)
08528 {
08529    int res;
08530    res = ioctl(dfd, DAHDI_SETLAW, &law);
08531    if (res)
08532       return res;
08533    return 0;
08534 }
08535 
08536 static void *pri_dchannel(void *vpri)
08537 {
08538    struct dahdi_pri *pri = vpri;
08539    pri_event *e;
08540    struct pollfd fds[NUM_DCHANS];
08541    int res;
08542    int chanpos = 0;
08543    int x;
08544    int haveidles;
08545    int activeidles;
08546    int nextidle = -1;
08547    struct ast_channel *c;
08548    struct timeval tv, lowest, *next;
08549    struct timeval lastidle = { 0, 0 };
08550    int doidling=0;
08551    char *cc;
08552    char idlen[80];
08553    struct ast_channel *idle;
08554    pthread_t p;
08555    time_t t;
08556    int i, which=-1;
08557    int numdchans;
08558    int cause=0;
08559    struct dahdi_pvt *crv;
08560    pthread_t threadid;
08561    pthread_attr_t attr;
08562    char ani2str[6];
08563    char plancallingnum[256];
08564    char plancallingani[256];
08565    char calledtonstr[10];
08566    
08567    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08568 
08569    gettimeofday(&lastidle, NULL);
08570    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08571       /* Need to do idle dialing, check to be sure though */
08572       cc = strchr(pri->idleext, '@');
08573       if (cc) {
08574          *cc = '\0';
08575          cc++;
08576          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08577 #if 0
08578          /* Extensions may not be loaded yet */
08579          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08580             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08581          else
08582 #endif
08583             doidling = 1;
08584       } else
08585          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08586    }
08587    for (;;) {
08588       for (i = 0; i < NUM_DCHANS; i++) {
08589          if (!pri->dchannels[i])
08590             break;
08591          fds[i].fd = pri->fds[i];
08592          fds[i].events = POLLIN | POLLPRI;
08593          fds[i].revents = 0;
08594       }
08595       numdchans = i;
08596       time(&t);
08597       ast_mutex_lock(&pri->lock);
08598       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08599          if (pri->resetting && pri_is_up(pri)) {
08600             if (pri->resetpos < 0)
08601                pri_check_restart(pri);
08602          } else {
08603             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
08604                pri->resetting = 1;
08605                pri->resetpos = -1;
08606             }
08607          }
08608       }
08609       /* Look for any idle channels if appropriate */
08610       if (doidling && pri_is_up(pri)) {
08611          nextidle = -1;
08612          haveidles = 0;
08613          activeidles = 0;
08614          for (x = pri->numchans; x >= 0; x--) {
08615             if (pri->pvts[x] && !pri->pvts[x]->owner && 
08616                 !pri->pvts[x]->call) {
08617                if (haveidles < pri->minunused) {
08618                   haveidles++;
08619                } else if (!pri->pvts[x]->resetting) {
08620                   nextidle = x;
08621                   break;
08622                }
08623             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08624                activeidles++;
08625          }
08626          if (nextidle > -1) {
08627             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08628                /* Don't create a new idle call more than once per second */
08629                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08630                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08631                if (idle) {
08632                   pri->pvts[nextidle]->isidlecall = 1;
08633                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08634                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08635                      dahdi_hangup(idle);
08636                   }
08637                } else
08638                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08639                gettimeofday(&lastidle, NULL);
08640             }
08641          } else if ((haveidles < pri->minunused) &&
08642                (activeidles > pri->minidle)) {
08643             /* Mark something for hangup if there is something 
08644                that can be hungup */
08645             for (x = pri->numchans; x >= 0; x--) {
08646                /* find a candidate channel */
08647                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08648                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08649                   haveidles++;
08650                   /* Stop if we have enough idle channels or
08651                     can't spare any more active idle ones */
08652                   if ((haveidles >= pri->minunused) ||
08653                       (activeidles <= pri->minidle))
08654                      break;
08655                } 
08656             }
08657          }
08658       }
08659       /* Start with reasonable max */
08660       lowest = ast_tv(60, 0);
08661       for (i = 0; i < NUM_DCHANS; i++) {
08662          /* Find lowest available d-channel */
08663          if (!pri->dchannels[i])
08664             break;
08665          if ((next = pri_schedule_next(pri->dchans[i]))) {
08666             /* We need relative time here */
08667             tv = ast_tvsub(*next, ast_tvnow());
08668             if (tv.tv_sec < 0) {
08669                tv = ast_tv(0,0);
08670             }
08671             if (doidling || pri->resetting) {
08672                if (tv.tv_sec > 1) {
08673                   tv = ast_tv(1, 0);
08674                }
08675             } else {
08676                if (tv.tv_sec > 60) {
08677                   tv = ast_tv(60, 0);
08678                }
08679             }
08680          } else if (doidling || pri->resetting) {
08681             /* Make sure we stop at least once per second if we're
08682                monitoring idle channels */
08683             tv = ast_tv(1,0);
08684          } else {
08685             /* Don't poll for more than 60 seconds */
08686             tv = ast_tv(60, 0);
08687          }
08688          if (!i || ast_tvcmp(tv, lowest) < 0) {
08689             lowest = tv;
08690          }
08691       }
08692       ast_mutex_unlock(&pri->lock);
08693 
08694       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08695       pthread_testcancel();
08696       e = NULL;
08697       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
08698       pthread_testcancel();
08699       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08700 
08701       ast_mutex_lock(&pri->lock);
08702       if (!res) {
08703          for (which = 0; which < NUM_DCHANS; which++) {
08704             if (!pri->dchans[which])
08705                break;
08706             /* Just a timeout, run the scheduler */
08707             e = pri_schedule_run(pri->dchans[which]);
08708             if (e)
08709                break;
08710          }
08711       } else if (res > -1) {
08712          for (which = 0; which < NUM_DCHANS; which++) {
08713             if (!pri->dchans[which])
08714                break;
08715             if (fds[which].revents & POLLPRI) {
08716                /* Check for an event */
08717                x = 0;
08718                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
08719                if (x) 
08720                   ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
08721                /* Keep track of alarm state */  
08722                if (x == DAHDI_EVENT_ALARM) {
08723                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
08724                   pri_find_dchan(pri);
08725                } else if (x == DAHDI_EVENT_NOALARM) {
08726                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
08727                   pri_restart(pri->dchans[which]);
08728                }
08729             
08730                if (option_debug)
08731                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
08732             } else if (fds[which].revents & POLLIN) {
08733                e = pri_check_event(pri->dchans[which]);
08734             }
08735             if (e)
08736                break;
08737          }
08738       } else if (errno != EINTR)
08739          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
08740 
08741       if (e) {
08742          if (pri->debug)
08743             pri_dump_event(pri->dchans[which], e);
08744 
08745          if (e->e != PRI_EVENT_DCHAN_DOWN) {
08746             if (!(pri->dchanavail[which] & DCHAN_UP)) {
08747                if (option_verbose > 1) 
08748                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
08749             }
08750             pri->dchanavail[which] |= DCHAN_UP;
08751          } else {
08752             if (pri->dchanavail[which] & DCHAN_UP) {
08753                if (option_verbose > 1) 
08754                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
08755             }
08756             pri->dchanavail[which] &= ~DCHAN_UP;
08757          }
08758 
08759          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
08760             /* Must be an NFAS group that has the secondary dchan active */
08761             pri->pri = pri->dchans[which];
08762 
08763          switch (e->e) {
08764          case PRI_EVENT_DCHAN_UP:
08765             if (!pri->pri) pri_find_dchan(pri);
08766 
08767             /* Note presense of D-channel */
08768             time(&pri->lastreset);
08769 
08770             /* Restart in 5 seconds */
08771             if (pri->resetinterval > -1) {
08772                pri->lastreset -= pri->resetinterval;
08773                pri->lastreset += 5;
08774             }
08775             pri->resetting = 0;
08776             /* Take the channels from inalarm condition */
08777             for (i = 0; i < pri->numchans; i++)
08778                if (pri->pvts[i]) {
08779                   pri->pvts[i]->inalarm = 0;
08780                }
08781             break;
08782          case PRI_EVENT_DCHAN_DOWN:
08783             pri_find_dchan(pri);
08784             if (!pri_is_up(pri)) {
08785                pri->resetting = 0;
08786                /* Hangup active channels and put them in alarm mode */
08787                for (i = 0; i < pri->numchans; i++) {
08788                   struct dahdi_pvt *p = pri->pvts[i];
08789                   if (p) {
08790                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08791                         /* T309 is not enabled : hangup calls when alarm occurs */
08792                         if (p->call) {
08793                            if (p->pri && p->pri->pri) {
08794                               pri_hangup(p->pri->pri, p->call, -1);
08795                               pri_destroycall(p->pri->pri, p->call);
08796                               p->call = NULL;
08797                            } else
08798                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
08799                         }
08800                         if (p->realcall) {
08801                            pri_hangup_all(p->realcall, pri);
08802                         } else if (p->owner)
08803                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08804                      }
08805                      p->inalarm = 1;
08806                   }
08807                }
08808             }
08809             break;
08810          case PRI_EVENT_RESTART:
08811             if (e->restart.channel > -1) {
08812                chanpos = pri_find_principle(pri, e->restart.channel);
08813                if (chanpos < 0)
08814                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
08815                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08816                else {
08817                   if (option_verbose > 2)
08818                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
08819                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08820                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08821                   if (pri->pvts[chanpos]->call) {
08822                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
08823                      pri->pvts[chanpos]->call = NULL;
08824                   }
08825                   /* Force soft hangup if appropriate */
08826                   if (pri->pvts[chanpos]->realcall) 
08827                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08828                   else if (pri->pvts[chanpos]->owner)
08829                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08830                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08831                }
08832             } else {
08833                if (option_verbose > 2)
08834                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
08835                for (x = 0; x < pri->numchans; x++)
08836                   if (pri->pvts[x]) {
08837                      ast_mutex_lock(&pri->pvts[x]->lock);
08838                      if (pri->pvts[x]->call) {
08839                         pri_destroycall(pri->pri, pri->pvts[x]->call);
08840                         pri->pvts[x]->call = NULL;
08841                      }
08842                      if (pri->pvts[chanpos]->realcall) 
08843                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08844                      else if (pri->pvts[x]->owner)
08845                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08846                      ast_mutex_unlock(&pri->pvts[x]->lock);
08847                   }
08848             }
08849             break;
08850          case PRI_EVENT_KEYPAD_DIGIT:
08851             chanpos = pri_find_principle(pri, e->digit.channel);
08852             if (chanpos < 0) {
08853                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
08854                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
08855             } else {
08856                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
08857                if (chanpos > -1) {
08858                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08859                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
08860                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
08861                      /* how to do that */
08862                      int digitlen = strlen(e->digit.digits);
08863                      char digit;
08864                      int i;               
08865                      for (i = 0; i < digitlen; i++) { 
08866                         digit = e->digit.digits[i];
08867                         {
08868                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
08869                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08870                         }
08871                      }
08872                   }
08873                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08874                }
08875             }
08876             break;
08877             
08878          case PRI_EVENT_INFO_RECEIVED:
08879             chanpos = pri_find_principle(pri, e->ring.channel);
08880             if (chanpos < 0) {
08881                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
08882                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08883             } else {
08884                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
08885                if (chanpos > -1) {
08886                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08887                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
08888                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
08889                      /* how to do that */
08890                      int digitlen = strlen(e->ring.callednum);
08891                      char digit;
08892                      int i;               
08893                      for (i = 0; i < digitlen; i++) { 
08894                         digit = e->ring.callednum[i];
08895                         {
08896                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
08897                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08898                         }
08899                      }
08900                   }
08901                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08902                }
08903             }
08904             break;
08905          case PRI_EVENT_RING:
08906             crv = NULL;
08907             if (e->ring.channel == -1)
08908                chanpos = pri_find_empty_chan(pri, 1);
08909             else
08910                chanpos = pri_find_principle(pri, e->ring.channel);
08911             /* if no channel specified find one empty */
08912             if (chanpos < 0) {
08913                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
08914                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08915             } else {
08916                ast_mutex_lock(&pri->pvts[chanpos]->lock);
08917                if (pri->pvts[chanpos]->owner) {
08918                   if (pri->pvts[chanpos]->call == e->ring.call) {
08919                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
08920                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08921                      break;
08922                   } else {
08923                      /* This is where we handle initial glare */
08924                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
08925                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08926                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08927                      chanpos = -1;
08928                   }
08929                }
08930                if (chanpos > -1)
08931                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08932             }
08933             if ((chanpos < 0) && (e->ring.flexible))
08934                chanpos = pri_find_empty_chan(pri, 1);
08935             if (chanpos > -1) {
08936                ast_mutex_lock(&pri->pvts[chanpos]->lock);
08937                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
08938                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
08939                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
08940                   if (crv)
08941                      ast_mutex_lock(&crv->lock);
08942                   if (!crv || crv->owner) {
08943                      pri->pvts[chanpos]->call = NULL;
08944                      if (crv) {
08945                         if (crv->owner)
08946                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08947                         ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
08948                      } else
08949                         ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
08950                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
08951                      if (crv)
08952                         ast_mutex_unlock(&crv->lock);
08953                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08954                      break;
08955                   }
08956                }
08957                pri->pvts[chanpos]->call = e->ring.call;
08958                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
08959                if (pri->pvts[chanpos]->use_callerid) {
08960                   ast_shrink_phone_number(plancallingnum);
08961                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
08962 #ifdef PRI_ANI
08963                   if (!ast_strlen_zero(e->ring.callingani)) {
08964                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
08965                      ast_shrink_phone_number(plancallingani);
08966                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
08967                   } else {
08968                      pri->pvts[chanpos]->cid_ani[0] = '\0';
08969                   }
08970 #endif
08971                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
08972                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
08973                } else {
08974                   pri->pvts[chanpos]->cid_num[0] = '\0';
08975                   pri->pvts[chanpos]->cid_ani[0] = '\0';
08976                   pri->pvts[chanpos]->cid_name[0] = '\0';
08977                   pri->pvts[chanpos]->cid_ton = 0;
08978                }
08979                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
08980                           e->ring.redirectingnum, e->ring.callingplanrdnis);
08981                /* If immediate=yes go to s|1 */
08982                if (pri->pvts[chanpos]->immediate) {
08983                   if (option_verbose > 2)
08984                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
08985                   pri->pvts[chanpos]->exten[0] = 's';
08986                   pri->pvts[chanpos]->exten[1] = '\0';
08987                }
08988                /* Get called number */
08989                else if (!ast_strlen_zero(e->ring.callednum)) {
08990                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
08991                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
08992                } else if (pri->overlapdial)
08993                   pri->pvts[chanpos]->exten[0] = '\0';
08994                else {
08995                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
08996                   pri->pvts[chanpos]->exten[0] = 's';
08997                   pri->pvts[chanpos]->exten[1] = '\0';
08998                }
08999                /* Set DNID on all incoming calls -- even immediate */
09000                if (!ast_strlen_zero(e->ring.callednum))
09001                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09002                /* No number yet, but received "sending complete"? */
09003                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09004                   if (option_verbose > 2)
09005                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09006                   pri->pvts[chanpos]->exten[0] = 's';
09007                   pri->pvts[chanpos]->exten[1] = '\0';
09008                }
09009                /* Make sure extension exists (or in overlap dial mode, can exist) */
09010                if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09011                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09012                   /* Setup law */
09013                   int law;
09014                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09015                      /* Set to audio mode at this point */
09016                      law = 1;
09017                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09018                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09019                   }
09020                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09021                      law = DAHDI_LAW_ALAW;
09022                   else
09023                      law = DAHDI_LAW_MULAW;
09024                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09025                   if (res < 0) 
09026                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09027                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09028                   if (res < 0)
09029                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09030                   if (e->ring.complete || !pri->overlapdial) {
09031                      /* Just announce proceeding */
09032                      pri->pvts[chanpos]->proceeding = 1;
09033                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09034                   } else {
09035                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
09036                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09037                      else
09038                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09039                   }
09040                   /* Get the use_callingpres state */
09041                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09042                
09043                   /* Start PBX */
09044                   if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09045                      /* Release the PRI lock while we create the channel */
09046                      ast_mutex_unlock(&pri->lock);
09047                      if (crv) {
09048                         /* Set bearer and such */
09049                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09050                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09051                         pri->pvts[chanpos]->owner = &inuse;
09052                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09053                      } else {
09054                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09055                      }
09056 
09057                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09058 
09059                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09060                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09061                      }
09062                      if (e->ring.ani2 >= 0) {
09063                         snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09064                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09065                      }
09066 
09067 #ifdef SUPPORT_USERUSER
09068                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
09069                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09070                      }
09071 #endif
09072 
09073                      snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09074                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09075                      if (e->ring.redirectingreason >= 0)
09076                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09077                   
09078                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09079                      ast_mutex_lock(&pri->lock);
09080 
09081                      pthread_attr_init(&attr);
09082                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09083                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09084                         if (option_verbose > 2)
09085                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09086                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09087                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09088                      } else {
09089                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09090                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09091                         if (c)
09092                            ast_hangup(c);
09093                         else {
09094                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09095                            pri->pvts[chanpos]->call = NULL;
09096                         }
09097                      }
09098                      pthread_attr_destroy(&attr);
09099                   } else  {
09100                      ast_mutex_unlock(&pri->lock);
09101                      /* Release PRI lock while we create the channel */
09102                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09103                      if (c) {
09104                         char calledtonstr[10];
09105 
09106                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09107 
09108                         if (e->ring.ani2 >= 0) {
09109                            snprintf(ani2str, 5, "%d", e->ring.ani2);
09110                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09111                         }
09112 
09113 #ifdef SUPPORT_USERUSER
09114                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
09115                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09116                         }
09117 #endif
09118 
09119                         if (e->ring.redirectingreason >= 0)
09120                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09121                      
09122                         snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09123                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09124 
09125                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
09126                         ast_mutex_lock(&pri->lock);
09127 
09128                         if (option_verbose > 2)
09129                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09130                               plancallingnum, pri->pvts[chanpos]->exten, 
09131                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09132                         dahdi_enable_ec(pri->pvts[chanpos]);
09133                      } else {
09134 
09135                         ast_mutex_lock(&pri->lock);
09136 
09137                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09138                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09139                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09140                         pri->pvts[chanpos]->call = NULL;
09141                      }
09142                   }
09143                } else {
09144                   if (option_verbose > 2)
09145                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
09146                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
09147                            pri->pvts[chanpos]->prioffset, pri->span);
09148                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09149                   pri->pvts[chanpos]->call = NULL;
09150                   pri->pvts[chanpos]->exten[0] = '\0';
09151                }
09152                if (crv)
09153                   ast_mutex_unlock(&crv->lock);
09154                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09155             } else {
09156                if (e->ring.flexible)
09157                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09158                else
09159                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09160             }
09161             break;
09162          case PRI_EVENT_RINGING:
09163             chanpos = pri_find_principle(pri, e->ringing.channel);
09164             if (chanpos < 0) {
09165                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
09166                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09167             } else {
09168                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09169                if (chanpos < 0) {
09170                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
09171                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09172                } else {
09173                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09174                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09175                      dahdi_enable_ec(pri->pvts[chanpos]);
09176                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09177                      pri->pvts[chanpos]->alerting = 1;
09178                   } else
09179                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09180 #ifdef PRI_PROGRESS_MASK
09181                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09182 #else
09183                   if (e->ringing.progress == 8) {
09184 #endif
09185                      /* Now we can do call progress detection */
09186                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09187                         /* RINGING detection isn't required because we got ALERTING signal */
09188                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09189                         pri->pvts[chanpos]->dsp_features = 0;
09190                      }
09191                   }
09192 
09193 #ifdef SUPPORT_USERUSER
09194                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09195                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09196                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09197                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09198                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09199                   }
09200 #endif
09201 
09202                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09203                }
09204             }
09205             break;
09206          case PRI_EVENT_PROGRESS:
09207             /* Get chan value if e->e is not PRI_EVNT_RINGING */
09208             chanpos = pri_find_principle(pri, e->proceeding.channel);
09209             if (chanpos > -1) {
09210 #ifdef PRI_PROGRESS_MASK
09211                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09212 #else
09213                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09214 #endif
09215                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09216 
09217                   if (e->proceeding.cause > -1) {
09218                      if (option_verbose > 2)
09219                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09220 
09221                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
09222                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09223                         if (pri->pvts[chanpos]->owner) {
09224                            if (option_verbose > 2)
09225                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09226 
09227                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09228                            f.subclass = AST_CONTROL_BUSY;
09229                         }
09230                      }
09231                   }
09232                   
09233                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09234                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09235                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09236                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09237 #ifdef PRI_PROGRESS_MASK
09238                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09239 #else
09240                   if (e->proceeding.progress == 8) {
09241 #endif
09242                      /* Now we can do call progress detection */
09243                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09244                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09245                         pri->pvts[chanpos]->dsp_features = 0;
09246                      }
09247                   }
09248                   pri->pvts[chanpos]->progress = 1;
09249                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09250                }
09251             }
09252             break;
09253          case PRI_EVENT_PROCEEDING:
09254             chanpos = pri_find_principle(pri, e->proceeding.channel);
09255             if (chanpos > -1) {
09256                if (!pri->pvts[chanpos]->proceeding) {
09257                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09258                   
09259                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09260                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09261                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09262                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09263 #ifdef PRI_PROGRESS_MASK
09264                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09265 #else
09266                   if (e->proceeding.progress == 8) {
09267 #endif
09268                      /* Now we can do call progress detection */
09269                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09270                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09271                         pri->pvts[chanpos]->dsp_features = 0;
09272                      }
09273                      /* Bring voice path up */
09274                      f.subclass = AST_CONTROL_PROGRESS;
09275                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09276                   }
09277                   pri->pvts[chanpos]->proceeding = 1;
09278                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09279                }
09280             }
09281             break;
09282          case PRI_EVENT_FACNAME:
09283             chanpos = pri_find_principle(pri, e->facname.channel);
09284             if (chanpos < 0) {
09285                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
09286                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09287             } else {
09288                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09289                if (chanpos < 0) {
09290                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
09291                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09292                } else {
09293                   /* Re-use *69 field for PRI */
09294                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09295                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09296                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09297                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09298                   dahdi_enable_ec(pri->pvts[chanpos]);
09299                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09300                }
09301             }
09302             break;            
09303          case PRI_EVENT_ANSWER:
09304             chanpos = pri_find_principle(pri, e->answer.channel);
09305             if (chanpos < 0) {
09306                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
09307                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09308             } else {
09309                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09310                if (chanpos < 0) {
09311                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
09312                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09313                } else {
09314                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09315                   /* Now we can do call progress detection */
09316 
09317                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
09318                    * By this time, we need DTMF detection and other features that were previously disabled
09319                    * -- Matt F */
09320                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09321                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09322                      pri->pvts[chanpos]->dsp_features = 0;
09323                   }
09324                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09325                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09326                      x = DAHDI_START;
09327                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09328                      if (res < 0) {
09329                         if (errno != EINPROGRESS) {
09330                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09331                         }
09332                      }
09333                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09334                      pri->pvts[chanpos]->dialing = 1;
09335                      /* Send any "w" waited stuff */
09336                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09337                      if (res < 0) {
09338                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09339                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09340                      } else 
09341                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09342                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09343                   } else if (pri->pvts[chanpos]->confirmanswer) {
09344                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09345                   } else {
09346                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09347                      /* Enable echo cancellation if it's not on already */
09348                      dahdi_enable_ec(pri->pvts[chanpos]);
09349                   }
09350 
09351 #ifdef SUPPORT_USERUSER
09352                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
09353                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09354                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09355                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09356                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09357                   }
09358 #endif
09359 
09360                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09361                }
09362             }
09363             break;            
09364          case PRI_EVENT_HANGUP:
09365             chanpos = pri_find_principle(pri, e->hangup.channel);
09366             if (chanpos < 0) {
09367                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
09368                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09369             } else {
09370                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09371                if (chanpos > -1) {
09372                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09373                   if (!pri->pvts[chanpos]->alreadyhungup) {
09374                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
09375                      pri->pvts[chanpos]->alreadyhungup = 1;
09376                      if (pri->pvts[chanpos]->realcall) 
09377                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09378                      else if (pri->pvts[chanpos]->owner) {
09379                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
09380                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09381                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09382                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09383                         else {
09384                            switch (e->hangup.cause) {
09385                               case PRI_CAUSE_USER_BUSY:
09386                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09387                                  break;
09388                               case PRI_CAUSE_CALL_REJECTED:
09389                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09390                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09391                               case PRI_CAUSE_SWITCH_CONGESTION:
09392                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09393                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09394                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09395                                  break;
09396                               default:
09397                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09398                            }
09399                         }
09400                      }
09401                      if (option_verbose > 2) 
09402                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
09403                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09404                   } else {
09405                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09406                      pri->pvts[chanpos]->call = NULL;
09407                   }
09408                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09409                      if (option_verbose > 2)
09410                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
09411                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09412                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09413                      pri->pvts[chanpos]->resetting = 1;
09414                   }
09415                   if (e->hangup.aoc_units > -1)
09416                      if (option_verbose > 2)
09417                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09418                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09419 
09420 #ifdef SUPPORT_USERUSER
09421                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09422                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09423                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09424                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09425                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09426                   }
09427 #endif
09428 
09429                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09430                } else {
09431                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
09432                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09433                }
09434             } 
09435             break;
09436 #ifndef PRI_EVENT_HANGUP_REQ
09437 #error please update libpri
09438 #endif
09439          case PRI_EVENT_HANGUP_REQ:
09440             chanpos = pri_find_principle(pri, e->hangup.channel);
09441             if (chanpos < 0) {
09442                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
09443                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09444             } else {
09445                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09446                if (chanpos > -1) {
09447                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09448                   if (pri->pvts[chanpos]->realcall) 
09449                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09450                   else if (pri->pvts[chanpos]->owner) {
09451                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09452                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09453                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09454                      else {
09455                         switch (e->hangup.cause) {
09456                            case PRI_CAUSE_USER_BUSY:
09457                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09458                               break;
09459                            case PRI_CAUSE_CALL_REJECTED:
09460                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09461                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09462                            case PRI_CAUSE_SWITCH_CONGESTION:
09463                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09464                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09465                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09466                               break;
09467                            default:
09468                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09469                         }
09470                      }
09471                      if (option_verbose > 2) 
09472                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
09473                      if (e->hangup.aoc_units > -1)
09474                         if (option_verbose > 2)
09475                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09476                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09477                   } else {
09478                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09479                      pri->pvts[chanpos]->call = NULL;
09480                   }
09481                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09482                      if (option_verbose > 2)
09483                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
09484                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09485                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09486                      pri->pvts[chanpos]->resetting = 1;
09487                   }
09488 
09489 #ifdef SUPPORT_USERUSER
09490                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09491                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09492                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09493                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09494                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09495                   }
09496 #endif
09497 
09498                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09499                } else {
09500                   ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09501                }
09502             } 
09503             break;
09504          case PRI_EVENT_HANGUP_ACK:
09505             chanpos = pri_find_principle(pri, e->hangup.channel);
09506             if (chanpos < 0) {
09507                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
09508                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09509             } else {
09510                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09511                if (chanpos > -1) {
09512                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09513                   pri->pvts[chanpos]->call = NULL;
09514                   pri->pvts[chanpos]->resetting = 0;
09515                   if (pri->pvts[chanpos]->owner) {
09516                      if (option_verbose > 2) 
09517                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09518                   }
09519 
09520 #ifdef SUPPORT_USERUSER
09521                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09522                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09523                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09524                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09525                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09526                   }
09527 #endif
09528 
09529                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09530                }
09531             }
09532             break;
09533          case PRI_EVENT_CONFIG_ERR:
09534             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09535             break;
09536          case PRI_EVENT_RESTART_ACK:
09537             chanpos = pri_find_principle(pri, e->restartack.channel);
09538             if (chanpos < 0) {
09539                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
09540                   channel number, so we have to figure it out...  This must be why
09541                   everybody resets exactly a channel at a time. */
09542                for (x = 0; x < pri->numchans; x++) {
09543                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
09544                      chanpos = x;
09545                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09546                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
09547                            pri->pvts[chanpos]->prioffset, pri->span);
09548                      if (pri->pvts[chanpos]->realcall) 
09549                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09550                      else if (pri->pvts[chanpos]->owner) {
09551                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
09552                            pri->pvts[chanpos]->prioffset, pri->span);
09553                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09554                      }
09555                      pri->pvts[chanpos]->resetting = 0;
09556                      if (option_verbose > 2)
09557                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09558                            pri->pvts[chanpos]->prioffset, pri->span);
09559                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09560                      if (pri->resetting)
09561                         pri_check_restart(pri);
09562                      break;
09563                   }
09564                }
09565                if (chanpos < 0) {
09566                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
09567                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09568                }
09569             } else {
09570                if (pri->pvts[chanpos]) {
09571                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09572                   if (pri->pvts[chanpos]->realcall) 
09573                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09574                   else if (pri->pvts[chanpos]->owner) {
09575                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09576                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09577                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09578                   }
09579                   pri->pvts[chanpos]->resetting = 0;
09580                   if (option_verbose > 2)
09581                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09582                            pri->pvts[chanpos]->prioffset, pri->span);
09583                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09584                   if (pri->resetting)
09585                      pri_check_restart(pri);
09586                }
09587             }
09588             break;
09589          case PRI_EVENT_SETUP_ACK:
09590             chanpos = pri_find_principle(pri, e->setup_ack.channel);
09591             if (chanpos < 0) {
09592                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
09593                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09594             } else {
09595                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09596                if (chanpos > -1) {
09597                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09598                   pri->pvts[chanpos]->setup_ack = 1;
09599                   /* Send any queued digits */
09600                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09601                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09602                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
09603                         pri->pvts[chanpos]->dialdest[x]);
09604                   }
09605                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09606                } else
09607                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09608             }
09609             break;
09610          case PRI_EVENT_NOTIFY:
09611             chanpos = pri_find_principle(pri, e->notify.channel);
09612             if (chanpos < 0) {
09613                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09614                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09615             } else {
09616                struct ast_frame f = { AST_FRAME_CONTROL, };
09617                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09618                switch (e->notify.info) {
09619                case PRI_NOTIFY_REMOTE_HOLD:
09620                   f.subclass = AST_CONTROL_HOLD;
09621                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09622                   break;
09623                case PRI_NOTIFY_REMOTE_RETRIEVAL:
09624                   f.subclass = AST_CONTROL_UNHOLD;
09625                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09626                   break;
09627                }
09628                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09629             }
09630             break;
09631          default:
09632             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09633          }
09634       }  
09635       ast_mutex_unlock(&pri->lock);
09636    }
09637    /* Never reached */
09638    return NULL;
09639 }
09640 
09641 static int start_pri(struct dahdi_pri *pri)
09642 {
09643    int res, x;
09644    struct dahdi_params p;
09645    struct dahdi_bufferinfo bi;
09646    struct dahdi_spaninfo si;
09647    int i;
09648    
09649    for (i = 0; i < NUM_DCHANS; i++) {
09650       if (!pri->dchannels[i])
09651          break;
09652       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
09653       x = pri->dchannels[i];
09654       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09655          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09656          return -1;
09657       }
09658       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09659       if (res) {
09660          dahdi_close_pri_fd(pri, i);
09661          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09662          return -1;
09663       }
09664       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
09665          dahdi_close_pri_fd(pri, i);
09666          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
09667          return -1;
09668       }
09669       memset(&si, 0, sizeof(si));
09670       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
09671       if (res) {
09672          dahdi_close_pri_fd(pri, i);
09673          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
09674       }
09675       if (!si.alarms)
09676          pri->dchanavail[i] |= DCHAN_NOTINALARM;
09677       else
09678          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
09679       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
09680       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
09681       bi.numbufs = 32;
09682       bi.bufsize = 1024;
09683       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
09684          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
09685          dahdi_close_pri_fd(pri, i);
09686          return -1;
09687       }
09688       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
09689       /* Force overlap dial if we're doing GR-303! */
09690       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
09691          pri->overlapdial = 1;
09692       pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
09693 #ifdef HAVE_PRI_INBANDDISCONNECT
09694       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
09695 #endif
09696       /* Enslave to master if appropriate */
09697       if (i)
09698          pri_enslave(pri->dchans[0], pri->dchans[i]);
09699       if (!pri->dchans[i]) {
09700          dahdi_close_pri_fd(pri, i);
09701          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
09702          return -1;
09703       }
09704       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
09705       pri_set_nsf(pri->dchans[i], pri->nsf);
09706 #ifdef PRI_GETSET_TIMERS
09707       for (x = 0; x < PRI_MAX_TIMERS; x++) {
09708          if (pritimers[x] != 0)
09709             pri_set_timer(pri->dchans[i], x, pritimers[x]);
09710       }
09711 #endif
09712    }
09713    /* Assume primary is the one we use */
09714    pri->pri = pri->dchans[0];
09715    pri->resetpos = -1;
09716    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
09717       for (i = 0; i < NUM_DCHANS; i++) {
09718          if (!pri->dchannels[i])
09719             break;
09720          dahdi_close_pri_fd(pri, i);
09721       }
09722       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
09723       return -1;
09724    }
09725    return 0;
09726 }
09727 
09728 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
09729 {
09730    int which, span;
09731    char *ret = NULL;
09732 
09733    if (pos != rpos)
09734       return ret;
09735 
09736    for (which = span = 0; span < NUM_SPANS; span++) {
09737       if (pris[span].pri && ++which > state) {
09738          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
09739             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
09740          }
09741          break;
09742       }
09743    }
09744    return ret;
09745 }
09746 
09747 static char *complete_span_4(const char *line, const char *word, int pos, int state)
09748 {
09749    return complete_span_helper(line,word,pos,state,3);
09750 }
09751 
09752 static char *complete_span_5(const char *line, const char *word, int pos, int state)
09753 {
09754    return complete_span_helper(line,word,pos,state,4);
09755 }
09756 
09757 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
09758 {
09759    int myfd;
09760 
09761    if (!strncasecmp(argv[1], "set", 3)) {
09762       if (argc < 5) 
09763          return RESULT_SHOWUSAGE;
09764 
09765       if (ast_strlen_zero(argv[4]))
09766          return RESULT_SHOWUSAGE;
09767 
09768       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
09769       if (myfd < 0) {
09770          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
09771          return RESULT_SUCCESS;
09772       }
09773 
09774       ast_mutex_lock(&pridebugfdlock);
09775 
09776       if (pridebugfd >= 0)
09777          close(pridebugfd);
09778 
09779       pridebugfd = myfd;
09780       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
09781       
09782       ast_mutex_unlock(&pridebugfdlock);
09783 
09784       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
09785    } else {
09786       /* Assume it is unset */
09787       ast_mutex_lock(&pridebugfdlock);
09788       close(pridebugfd);
09789       pridebugfd = -1;
09790       ast_cli(fd, "PRI debug output to file disabled\n");
09791       ast_mutex_unlock(&pridebugfdlock);
09792    }
09793 
09794    return RESULT_SUCCESS;
09795 }
09796 
09797 #ifdef HAVE_PRI_VERSION
09798 static int handle_pri_version(int fd, int agc, char *argv[]) {
09799    ast_cli(fd, "libpri version: %s\n", pri_get_version());
09800    return RESULT_SUCCESS;
09801 }
09802 #endif
09803 
09804 static int handle_pri_debug(int fd, int argc, char *argv[])
09805 {
09806    int span;
09807    int x;
09808    if (argc < 4) {
09809       return RESULT_SHOWUSAGE;
09810    }
09811    span = atoi(argv[3]);
09812    if ((span < 1) || (span > NUM_SPANS)) {
09813       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
09814       return RESULT_SUCCESS;
09815    }
09816    if (!pris[span-1].pri) {
09817       ast_cli(fd, "No PRI running on span %d\n", span);
09818       return RESULT_SUCCESS;
09819    }
09820    for (x = 0; x < NUM_DCHANS; x++) {
09821       if (pris[span-1].dchans[x])
09822          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09823                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09824                                                PRI_DEBUG_Q921_STATE);
09825    }
09826    ast_cli(fd, "Enabled debugging on span %d\n", span);
09827    return RESULT_SUCCESS;
09828 }
09829 
09830 
09831 
09832 static int handle_pri_no_debug(int fd, int argc, char *argv[])
09833 {
09834    int span;
09835    int x;
09836    if (argc < 5)
09837       return RESULT_SHOWUSAGE;
09838    span = atoi(argv[4]);
09839    if ((span < 1) || (span > NUM_SPANS)) {
09840       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09841       return RESULT_SUCCESS;
09842    }
09843    if (!pris[span-1].pri) {
09844       ast_cli(fd, "No PRI running on span %d\n", span);
09845       return RESULT_SUCCESS;
09846    }
09847    for (x = 0; x < NUM_DCHANS; x++) {
09848       if (pris[span-1].dchans[x])
09849          pri_set_debug(pris[span-1].dchans[x], 0);
09850    }
09851    ast_cli(fd, "Disabled debugging on span %d\n", span);
09852    return RESULT_SUCCESS;
09853 }
09854 
09855 static int handle_pri_really_debug(int fd, int argc, char *argv[])
09856 {
09857    int span;
09858    int x;
09859    if (argc < 5)
09860       return RESULT_SHOWUSAGE;
09861    span = atoi(argv[4]);
09862    if ((span < 1) || (span > NUM_SPANS)) {
09863       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09864       return RESULT_SUCCESS;
09865    }
09866    if (!pris[span-1].pri) {
09867       ast_cli(fd, "No PRI running on span %d\n", span);
09868       return RESULT_SUCCESS;
09869    }
09870    for (x = 0; x < NUM_DCHANS; x++) {
09871       if (pris[span-1].dchans[x])
09872          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09873                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09874                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
09875    }
09876    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
09877    return RESULT_SUCCESS;
09878 }
09879 
09880 static void build_status(char *s, size_t len, int status, int active)
09881 {
09882    if (!s || len < 1) {
09883       return;
09884    }
09885    s[0] = '\0';
09886    if (status & DCHAN_PROVISIONED)
09887       strncat(s, "Provisioned, ", len - strlen(s) - 1);
09888    if (!(status & DCHAN_NOTINALARM))
09889       strncat(s, "In Alarm, ", len - strlen(s) - 1);
09890    if (status & DCHAN_UP)
09891       strncat(s, "Up", len - strlen(s) - 1);
09892    else
09893       strncat(s, "Down", len - strlen(s) - 1);
09894    if (active)
09895       strncat(s, ", Active", len - strlen(s) - 1);
09896    else
09897       strncat(s, ", Standby", len - strlen(s) - 1);
09898    s[len - 1] = '\0';
09899 }
09900 
09901 static int handle_pri_show_spans(int fd, int argc, char *argv[])
09902 {
09903    int span;
09904    int x;
09905    char status[256];
09906    if (argc != 3)
09907       return RESULT_SHOWUSAGE;
09908 
09909    for (span = 0; span < NUM_SPANS; span++) {
09910       if (pris[span].pri) {
09911          for (x = 0; x < NUM_DCHANS; x++) {
09912             if (pris[span].dchannels[x]) {
09913                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
09914                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
09915             }
09916          }
09917       }
09918    }
09919    return RESULT_SUCCESS;
09920 }
09921 
09922 static int handle_pri_show_span(int fd, int argc, char *argv[])
09923 {
09924    int span;
09925    int x;
09926    char status[256];
09927    if (argc < 4)
09928       return RESULT_SHOWUSAGE;
09929    span = atoi(argv[3]);
09930    if ((span < 1) || (span > NUM_SPANS)) {
09931       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
09932       return RESULT_SUCCESS;
09933    }
09934    if (!pris[span-1].pri) {
09935       ast_cli(fd, "No PRI running on span %d\n", span);
09936       return RESULT_SUCCESS;
09937    }
09938    for (x = 0; x < NUM_DCHANS; x++) {
09939       if (pris[span-1].dchannels[x]) {
09940 #ifdef PRI_DUMP_INFO_STR
09941          char *info_str = NULL;
09942 #endif
09943          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
09944          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
09945          ast_cli(fd, "Status: %s\n", status);
09946 #ifdef PRI_DUMP_INFO_STR
09947          info_str = pri_dump_info_str(pris[span-1].pri);
09948          if (info_str) {
09949             ast_cli(fd, "%s", info_str);
09950             free(info_str);
09951          }
09952 #else
09953          pri_dump_info(pris[span-1].pri);
09954 #endif
09955          ast_cli(fd, "\n");
09956       }
09957    }
09958    return RESULT_SUCCESS;
09959 }
09960 
09961 static int handle_pri_show_debug(int fd, int argc, char *argv[])
09962 {
09963    int x;
09964    int span;
09965    int count=0;
09966    int debug=0;
09967 
09968    for (span = 0; span < NUM_SPANS; span++) {
09969            if (pris[span].pri) {
09970          for (x = 0; x < NUM_DCHANS; x++) {
09971             debug = 0;
09972                if (pris[span].dchans[x]) {
09973                   debug = pri_get_debug(pris[span].dchans[x]);
09974                ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
09975                count++;
09976             }
09977          }
09978       }
09979 
09980    }
09981    ast_mutex_lock(&pridebugfdlock);
09982    if (pridebugfd >= 0) 
09983       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
09984    ast_mutex_unlock(&pridebugfdlock);
09985        
09986    if (!count) 
09987       ast_cli(fd, "No debug set or no PRI running\n");
09988    return RESULT_SUCCESS;
09989 }
09990 
09991 static const char pri_debug_help[] = 
09992    "Usage: pri debug span <span>\n"
09993    "       Enables debugging on a given PRI span\n";
09994    
09995 static const char pri_no_debug_help[] = 
09996    "Usage: pri no debug span <span>\n"
09997    "       Disables debugging on a given PRI span\n";
09998 
09999 static const char pri_really_debug_help[] = 
10000    "Usage: pri intensive debug span <span>\n"
10001    "       Enables debugging down to the Q.921 level\n";
10002 
10003 static const char pri_show_span_help[] = 
10004    "Usage: pri show span <span>\n"
10005    "       Displays PRI Information on a given PRI span\n";
10006 
10007 static const char pri_show_spans_help[] = 
10008    "Usage: pri show spans\n"
10009    "       Displays PRI Information\n";
10010 
10011 static struct ast_cli_entry dahdi_pri_cli[] = {
10012    { { "pri", "debug", "span", NULL },
10013    handle_pri_debug, "Enables PRI debugging on a span",
10014    pri_debug_help, complete_span_4 },
10015 
10016    { { "pri", "no", "debug", "span", NULL },
10017    handle_pri_no_debug, "Disables PRI debugging on a span",
10018    pri_no_debug_help, complete_span_5 },
10019 
10020    { { "pri", "intense", "debug", "span", NULL },
10021    handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10022    pri_really_debug_help, complete_span_5 },
10023 
10024    { { "pri", "show", "spans", NULL },
10025    handle_pri_show_spans, "Displays PRI Information",
10026    pri_show_spans_help },
10027 
10028    { { "pri", "show", "span", NULL },
10029    handle_pri_show_span, "Displays PRI Information",
10030    pri_show_span_help, complete_span_4 },
10031 
10032    { { "pri", "show", "debug", NULL },
10033    handle_pri_show_debug, "Displays current PRI debug settings" },
10034 
10035    { { "pri", "set", "debug", "file", NULL },
10036    handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10037 
10038    { { "pri", "unset", "debug", "file", NULL },
10039    handle_pri_set_debug_file, "Ends PRI debug output to file" },
10040 
10041 #ifdef HAVE_PRI_VERSION
10042    { { "pri", "show", "version", NULL },
10043    handle_pri_version, "Displays version of libpri" },
10044 #endif
10045 };
10046 
10047 #endif /* HAVE_PRI */
10048 
10049 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10050 {
10051    int channel;
10052    
10053    if (argc != 4)
10054       return RESULT_SHOWUSAGE;
10055    
10056    channel = atoi(argv[3]);
10057 
10058    return dahdi_destroy_channel_bynum(channel);
10059 }
10060 
10061 static void dahdi_softhangup_all(void)
10062 {
10063    struct dahdi_pvt *p;
10064 retry:
10065    ast_mutex_lock(&iflock);
10066     for (p = iflist; p; p = p->next) {
10067       ast_mutex_lock(&p->lock);
10068         if (p->owner && !p->restartpending) {
10069          if (ast_channel_trylock(p->owner)) {
10070             if (option_debug > 2)
10071                ast_verbose("Avoiding deadlock\n");
10072             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10073             ast_mutex_unlock(&p->lock);
10074             ast_mutex_unlock(&iflock);
10075             goto retry;
10076          }
10077          if (option_debug > 2)
10078             ast_verbose("Softhanging up on %s\n", p->owner->name);
10079          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10080          p->restartpending = 1;
10081          num_restart_pending++;
10082          ast_channel_unlock(p->owner);
10083       }
10084       ast_mutex_unlock(&p->lock);
10085     }
10086    ast_mutex_unlock(&iflock);
10087 }
10088 
10089 static int setup_dahdi(int reload);
10090 static int dahdi_restart(void)
10091 {
10092 #if defined(HAVE_PRI)
10093    int i, j;
10094 #endif
10095    int cancel_code;
10096    struct dahdi_pvt *p;
10097 
10098    ast_mutex_lock(&restart_lock);
10099  
10100    if (option_verbose)
10101       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10102    dahdi_softhangup_all();
10103    if (option_verbose > 3)
10104       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10105 
10106    #if defined(HAVE_PRI)
10107    for (i = 0; i < NUM_SPANS; i++) {
10108       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10109          cancel_code = pthread_cancel(pris[i].master);
10110          pthread_kill(pris[i].master, SIGURG);
10111          if (option_debug > 3)
10112             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10113             pthread_join(pris[i].master, NULL);
10114          if (option_debug > 3)
10115             ast_verbose("Joined thread of span %d\n", i);
10116       }
10117     }
10118    #endif
10119 
10120     ast_mutex_lock(&monlock);
10121     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10122       cancel_code = pthread_cancel(monitor_thread);
10123       pthread_kill(monitor_thread, SIGURG);
10124       if (option_debug > 3)
10125          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10126         pthread_join(monitor_thread, NULL);
10127       if (option_debug > 3)
10128          ast_verbose("Joined monitor thread\n");
10129     }
10130    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10131 
10132    ast_mutex_lock(&ss_thread_lock);
10133    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10134       int x = DAHDI_FLASH;
10135       if (option_debug > 2)
10136          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10137 
10138       for (p = iflist; p; p = p->next) {
10139          if (p->owner)
10140             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */    
10141       }
10142       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10143    }
10144 
10145    /* ensure any created channels before monitor threads were stopped are hungup */
10146    dahdi_softhangup_all();
10147    if (option_verbose > 3)
10148       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10149    destroy_all_channels();
10150    if (option_debug)
10151       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10152 
10153     ast_mutex_unlock(&monlock);
10154 
10155    #ifdef HAVE_PRI
10156    for (i = 0; i < NUM_SPANS; i++) {
10157       for (j = 0; j < NUM_DCHANS; j++)
10158             dahdi_close_pri_fd(&(pris[i]), j);
10159    }
10160 
10161    memset(pris, 0, sizeof(pris));
10162    for (i = 0; i < NUM_SPANS; i++) {
10163       ast_mutex_init(&pris[i].lock);
10164       pris[i].offset = -1;
10165       pris[i].master = AST_PTHREADT_NULL;
10166       for (j = 0; j < NUM_DCHANS; j++)
10167          pris[i].fds[j] = -1;
10168    }
10169    pri_set_error(dahdi_pri_error);
10170    pri_set_message(dahdi_pri_message);
10171    #endif
10172 
10173    if (setup_dahdi(2) != 0) {
10174       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10175       ast_mutex_unlock(&ss_thread_lock);
10176       return 1;
10177    }
10178    ast_mutex_unlock(&ss_thread_lock);
10179    ast_mutex_unlock(&restart_lock);
10180    return 0;
10181 }
10182 
10183 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10184 {
10185    if (argc != 2) {
10186       return RESULT_SHOWUSAGE;
10187    }
10188 
10189    if (dahdi_restart() != 0)
10190       return RESULT_FAILURE;
10191    return RESULT_SUCCESS;
10192 }
10193 
10194 static int dahdi_show_channels(int fd, int argc, char **argv)
10195 {
10196 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10197 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10198    struct dahdi_pvt *tmp = NULL;
10199    char tmps[20] = "";
10200    ast_mutex_t *lock;
10201    struct dahdi_pvt *start;
10202 #ifdef HAVE_PRI
10203    int trunkgroup;
10204    struct dahdi_pri *pri = NULL;
10205    int x;
10206 #endif
10207 
10208    lock = &iflock;
10209    start = iflist;
10210 
10211 #ifdef HAVE_PRI
10212    if (argc == 4) {
10213       if ((trunkgroup = atoi(argv[3])) < 1)
10214          return RESULT_SHOWUSAGE;
10215       for (x = 0; x < NUM_SPANS; x++) {
10216          if (pris[x].trunkgroup == trunkgroup) {
10217             pri = pris + x;
10218             break;
10219          }
10220       }
10221       if (pri) {
10222          start = pri->crvs;
10223          lock = &pri->lock;
10224       } else {
10225          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10226          return RESULT_FAILURE;
10227       }
10228    } else
10229 #endif
10230    if (argc != 3)
10231       return RESULT_SHOWUSAGE;
10232 
10233    ast_mutex_lock(lock);
10234 #ifdef HAVE_PRI
10235    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10236 #else
10237    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10238 #endif   
10239    
10240    tmp = start;
10241    while (tmp) {
10242       if (tmp->channel > 0) {
10243          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10244       } else
10245          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10246       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10247       tmp = tmp->next;
10248    }
10249    ast_mutex_unlock(lock);
10250    return RESULT_SUCCESS;
10251 #undef FORMAT
10252 #undef FORMAT2
10253 }
10254 
10255 static int dahdi_show_channel(int fd, int argc, char **argv)
10256 {
10257    int channel;
10258    struct dahdi_pvt *tmp = NULL;
10259    struct dahdi_confinfo ci;
10260    struct dahdi_params ps;
10261    int x;
10262    ast_mutex_t *lock;
10263    struct dahdi_pvt *start;
10264 #ifdef HAVE_PRI
10265    char *c;
10266    int trunkgroup;
10267    struct dahdi_pri *pri=NULL;
10268 #endif
10269 
10270    lock = &iflock;
10271    start = iflist;
10272 
10273    if (argc != 4)
10274       return RESULT_SHOWUSAGE;
10275 #ifdef HAVE_PRI
10276    if ((c = strchr(argv[3], ':'))) {
10277       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10278          return RESULT_SHOWUSAGE;
10279       if ((trunkgroup < 1) || (channel < 1))
10280          return RESULT_SHOWUSAGE;
10281       for (x = 0; x < NUM_SPANS; x++) {
10282          if (pris[x].trunkgroup == trunkgroup) {
10283             pri = pris + x;
10284             break;
10285          }
10286       }
10287       if (pri) {
10288          start = pri->crvs;
10289          lock = &pri->lock;
10290       } else {
10291          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10292          return RESULT_FAILURE;
10293       }
10294    } else
10295 #endif
10296       channel = atoi(argv[3]);
10297 
10298    ast_mutex_lock(lock);
10299    tmp = start;
10300    while (tmp) {
10301       if (tmp->channel == channel) {
10302 #ifdef HAVE_PRI
10303          if (pri) 
10304             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10305          else
10306 #endif         
10307          ast_cli(fd, "Channel: %d\n", tmp->channel);
10308          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10309          ast_cli(fd, "Span: %d\n", tmp->span);
10310          ast_cli(fd, "Extension: %s\n", tmp->exten);
10311          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10312          ast_cli(fd, "Context: %s\n", tmp->context);
10313          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10314          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10315          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10316          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10317          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10318          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10319          ast_cli(fd, "Radio: %d\n", tmp->radio);
10320          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10321          ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
10322          ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
10323          ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
10324          ast_cli(fd, "Confno: %d\n", tmp->confno);
10325          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10326          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10327          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10328          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10329          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10330          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10331          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10332          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10333          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10334          if (tmp->master)
10335             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10336          for (x = 0; x < MAX_SLAVES; x++) {
10337             if (tmp->slaves[x])
10338                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10339          }
10340 #ifdef HAVE_PRI
10341          if (tmp->pri) {
10342             ast_cli(fd, "PRI Flags: ");
10343             if (tmp->resetting)
10344                ast_cli(fd, "Resetting ");
10345             if (tmp->call)
10346                ast_cli(fd, "Call ");
10347             if (tmp->bearer)
10348                ast_cli(fd, "Bearer ");
10349             ast_cli(fd, "\n");
10350             if (tmp->logicalspan) 
10351                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10352             else
10353                ast_cli(fd, "PRI Logical Span: Implicit\n");
10354          }
10355             
10356 #endif
10357          memset(&ci, 0, sizeof(ci));
10358          ps.channo = tmp->channel;
10359          if (tmp->subs[SUB_REAL].dfd > -1) {
10360             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10361                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10362             }
10363 #ifdef DAHDI_GETCONFMUTE
10364             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10365                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10366             }
10367 #endif
10368             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10369                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10370             } else {
10371                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10372             }
10373          }
10374          if (ISTRUNK(tmp)) {
10375             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10376             if (!ast_strlen_zero(progzone))
10377                ast_cli(fd, "Progress Zone: %s\n", progzone);
10378             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10379             if(tmp->busydetect) {
10380                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10381                if(tmp->busytonelength > 0) {
10382                   ast_cli(fd, "Busy Pattern:\n");
10383                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10384                   if (tmp->busyquietlength > 0) 
10385                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10386                   else 
10387                      ast_cli(fd, " -- Detect Tone Only\n");
10388                   if(tmp->busyfuzziness > 0)
10389                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10390                }
10391             }
10392          }
10393          ast_mutex_unlock(lock);
10394          return RESULT_SUCCESS;
10395       }
10396       tmp = tmp->next;
10397    }
10398    
10399    ast_cli(fd, "Unable to find given channel %d\n", channel);
10400    ast_mutex_unlock(lock);
10401    return RESULT_FAILURE;
10402 }
10403 
10404 static char dahdi_show_cadences_usage[] =
10405 "Usage: dahdi show cadences\n"
10406 "       Shows all cadences currently defined\n";
10407 
10408 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10409 {
10410    int i, j;
10411    for (i = 0; i < num_cadence; i++) {
10412       char output[1024];
10413       char tmp[16], tmp2[64];
10414       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10415       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10416 
10417       for (j = 0; j < 16; j++) {
10418          if (cadences[i].ringcadence[j] == 0)
10419             break;
10420          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10421          if (cidrings[i] * 2 - 1 == j)
10422             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10423          else
10424             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10425          if (j != 0)
10426             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10427          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10428       }
10429       ast_cli(fd,"%s\n",output);
10430    }
10431    return 0;
10432 }
10433 
10434 /* Based on irqmiss.c */
10435 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10436    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10437    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10438 
10439    int span;
10440    int res;
10441    char alarms[50];
10442 
10443    int ctl;
10444    struct dahdi_spaninfo s;
10445 
10446    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10447       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10448       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10449       return RESULT_FAILURE;
10450    }
10451    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10452 
10453    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10454       s.spanno = span;
10455       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10456       if (res) {
10457          continue;
10458       }
10459       alarms[0] = '\0';
10460       if (s.alarms > 0) {
10461          if (s.alarms & DAHDI_ALARM_BLUE)
10462             strcat(alarms, "BLU/");
10463          if (s.alarms & DAHDI_ALARM_YELLOW)
10464             strcat(alarms, "YEL/");
10465          if (s.alarms & DAHDI_ALARM_RED)
10466             strcat(alarms, "RED/");
10467          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10468             strcat(alarms, "LB/");
10469          if (s.alarms & DAHDI_ALARM_RECOVER)
10470             strcat(alarms, "REC/");
10471          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10472             strcat(alarms, "NOP/");
10473          if (!strlen(alarms))
10474             strcat(alarms, "UUU/");
10475          if (strlen(alarms)) {
10476             /* Strip trailing / */
10477             alarms[strlen(alarms) - 1] = '\0';
10478          }
10479       } else {
10480          if (s.numchans)
10481             strcpy(alarms, "OK");
10482          else
10483             strcpy(alarms, "UNCONFIGURED");
10484       }
10485 
10486       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10487    }
10488    close(ctl);
10489 
10490    return RESULT_SUCCESS;
10491 #undef FORMAT
10492 #undef FORMAT2
10493 }
10494 
10495 static char show_channels_usage[] =
10496    "Usage: dahdi show channels\n"
10497    "  Shows a list of available channels\n";
10498 
10499 static char show_channel_usage[] =
10500    "Usage: dahdi show channel <chan num>\n"
10501    "  Detailed information about a given channel\n";
10502 
10503 static char dahdi_show_status_usage[] =
10504    "Usage: dahdi show status\n"
10505    "       Shows a list of DAHDI cards with status\n";
10506 
10507 static char destroy_channel_usage[] =
10508    "Usage: dahdi destroy channel <chan num>\n"
10509    "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
10510 
10511 static char dahdi_restart_usage[] =
10512    "Usage: dahdi restart\n"
10513    "  Restarts the DAHDI channels: destroys them all and then\n"
10514    "  re-reads them from chan_dahdi.conf.\n"
10515    "  Note that this will STOP any running CALL on DAHDI channels.\n"
10516    "";
10517 
10518 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10519    { "zap", "show", "cadences", NULL },
10520    handle_dahdi_show_cadences, NULL,
10521    NULL };
10522 
10523 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10524    { "zap", "show", "channels", NULL },
10525    dahdi_show_channels, NULL,
10526    NULL };
10527 
10528 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10529    { "zap", "show", "channel", NULL },
10530    dahdi_show_channel, NULL,
10531    NULL };
10532 
10533 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10534    { "zap", "destroy", "channel", NULL },
10535    dahdi_destroy_channel, NULL,
10536    NULL };
10537 
10538 static struct ast_cli_entry cli_zap_restart_deprecated = {
10539    { "zap", "restart", NULL },
10540    dahdi_restart_cmd, NULL,
10541    NULL };
10542 
10543 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10544    { "zap", "show", "status", NULL },
10545    dahdi_show_status, NULL,
10546    NULL };
10547 
10548 static struct ast_cli_entry dahdi_cli[] = {
10549    { { "dahdi", "show", "cadences", NULL },
10550    handle_dahdi_show_cadences, "List cadences",
10551    dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10552 
10553    { { "dahdi", "show", "channels", NULL},
10554    dahdi_show_channels, "Show active DAHDI channels",
10555    show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10556 
10557    { { "dahdi", "show", "channel", NULL},
10558    dahdi_show_channel, "Show information on a channel",
10559    show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10560 
10561    { { "dahdi", "destroy", "channel", NULL},
10562    dahdi_destroy_channel, "Destroy a channel",
10563    destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10564 
10565    { { "dahdi", "restart", NULL},
10566    dahdi_restart_cmd, "Fully restart DAHDI channels",
10567    dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10568 
10569    { { "dahdi", "show", "status", NULL},
10570    dahdi_show_status, "Show all DAHDI cards status",
10571    dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10572 };
10573 
10574 #define TRANSFER  0
10575 #define HANGUP    1
10576 
10577 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10578 {
10579    if (p) {
10580       switch (mode) {
10581          case TRANSFER:
10582             p->fake_event = DAHDI_EVENT_WINKFLASH;
10583             break;
10584          case HANGUP:
10585             p->fake_event = DAHDI_EVENT_ONHOOK;
10586             break;
10587          default:
10588             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10589       }
10590    }
10591    return 0;
10592 }
10593 static struct dahdi_pvt *find_channel(int channel)
10594 {
10595    struct dahdi_pvt *p = iflist;
10596    while (p) {
10597       if (p->channel == channel) {
10598          break;
10599       }
10600       p = p->next;
10601    }
10602    return p;
10603 }
10604 
10605 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10606 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10607 
10608 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10609 {
10610    struct dahdi_pvt *p = NULL;
10611    const char *channel = local_astman_header(m, "Channel", zap_mode);
10612 
10613    if (ast_strlen_zero(channel)) {
10614       astman_send_error(s, m, "No channel specified");
10615       return 0;
10616    }
10617    if (!(p = find_channel(atoi(channel)))) {
10618       astman_send_error(s, m, "No such channel");
10619       return 0;
10620    }
10621    p->dnd = dnd;
10622    local_astman_ack(s, m, "DND", zap_mode);
10623 
10624    return 0;
10625 }
10626 
10627 static int zap_action_dndon(struct mansession *s, const struct message *m)
10628 {
10629    return __action_dnd(s, m, 1, 1);
10630 }
10631 
10632 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10633 {
10634    return __action_dnd(s, m, 0, 1);
10635 }
10636 
10637 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10638 {
10639    return __action_dnd(s, m, 1, 0);
10640 }
10641 
10642 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10643 {
10644    return __action_dnd(s, m, 0, 0);
10645 }
10646 
10647 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10648 {
10649    struct dahdi_pvt *p = NULL;
10650    const char *channel = local_astman_header(m, "Channel", zap_mode);
10651 
10652    if (ast_strlen_zero(channel)) {
10653       astman_send_error(s, m, "No channel specified");
10654       return 0;
10655    }
10656    if (!(p = find_channel(atoi(channel)))) {
10657       astman_send_error(s, m, "No such channel");
10658       return 0;
10659    }
10660    dahdi_fake_event(p,TRANSFER);
10661    local_astman_ack(s, m, "Transfer", zap_mode);
10662 
10663    return 0;
10664 }
10665 
10666 static int zap_action_transfer(struct mansession *s, const struct message *m)
10667 {
10668    return __action_transfer(s, m, 1);
10669 }
10670 
10671 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10672 {
10673    return __action_transfer(s, m, 0);
10674 }
10675 
10676 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10677 {
10678    struct dahdi_pvt *p = NULL;
10679    const char *channel = local_astman_header(m, "Channel", zap_mode);
10680 
10681    if (ast_strlen_zero(channel)) {
10682       astman_send_error(s, m, "No channel specified");
10683       return 0;
10684    }
10685    if (!(p = find_channel(atoi(channel)))) {
10686       astman_send_error(s, m, "No such channel");
10687       return 0;
10688    }
10689    dahdi_fake_event(p, HANGUP);
10690    local_astman_ack(s, m, "Hangup", zap_mode);
10691    return 0;
10692 }
10693 
10694 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10695 {
10696    return __action_transferhangup(s, m, 1);
10697 }
10698 
10699 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10700 {
10701    return __action_transferhangup(s, m, 0);
10702 }
10703 
10704 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10705 {
10706    struct dahdi_pvt *p = NULL;
10707    const char *channel = local_astman_header(m, "Channel", zap_mode);
10708    const char *number = astman_get_header(m, "Number");
10709    int i;
10710 
10711    if (ast_strlen_zero(channel)) {
10712       astman_send_error(s, m, "No channel specified");
10713       return 0;
10714    }
10715    if (ast_strlen_zero(number)) {
10716       astman_send_error(s, m, "No number specified");
10717       return 0;
10718    }
10719    if (!(p = find_channel(atoi(channel)))) {
10720       astman_send_error(s, m, "No such channel");
10721       return 0;
10722    }
10723    if (!p->owner) {
10724       astman_send_error(s, m, "Channel does not have an owner");
10725       return 0;
10726    }
10727    for (i = 0; i < strlen(number); i++) {
10728       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10729 
10730       dahdi_queue_frame(p, &f, NULL); 
10731    }
10732    local_astman_ack(s, m, "DialOffHook", zap_mode);
10733 
10734    return 0;
10735 }
10736 
10737 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10738 {
10739    return __action_dialoffhook(s, m, 1);
10740 }
10741 
10742 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10743 {
10744    return __action_dialoffhook(s, m, 0);
10745 }
10746 
10747 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10748 {
10749    struct dahdi_pvt *tmp = NULL;
10750    const char *id = astman_get_header(m, "ActionID");
10751    char idText[256] = "";
10752 
10753    local_astman_ack(s, m, " channel status will follow", zap_mode);
10754    if (!ast_strlen_zero(id))
10755       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10756 
10757    ast_mutex_lock(&iflock);
10758    
10759    tmp = iflist;
10760    while (tmp) {
10761       if (tmp->channel > 0) {
10762          int alarm = get_alarms(tmp);
10763          astman_append(s,
10764                   "Event: %sShowChannels\r\n"
10765                   "Channel: %d\r\n"
10766                   "Signalling: %s\r\n"
10767                   "Context: %s\r\n"
10768                   "DND: %s\r\n"
10769                   "Alarm: %s\r\n"
10770                   "%s"
10771                   "\r\n",
10772                   dahdi_chan_name,
10773                   tmp->channel, sig2str(tmp->sig), tmp->context, 
10774                   tmp->dnd ? "Enabled" : "Disabled",
10775                   alarm2str(alarm), idText);
10776       } 
10777 
10778       tmp = tmp->next;
10779    }
10780 
10781    ast_mutex_unlock(&iflock);
10782    
10783    astman_append(s, 
10784             "Event: %sShowChannelsComplete\r\n"
10785             "%s"
10786             "\r\n",
10787             dahdi_chan_name,
10788             idText);
10789    return 0;
10790 }
10791 
10792 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10793 {
10794    return __action_showchannels(s, m, 1);
10795 }
10796 
10797 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10798 {
10799    return __action_showchannels(s, m, 0);
10800 }
10801 
10802 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10803 {
10804    if (dahdi_restart() != 0) {
10805       if (zap_mode) {
10806          astman_send_error(s, m, "Failed to restart Zap");
10807       } else {
10808          astman_send_error(s, m, "Failed to restart DAHDI");
10809       }
10810       return 1;
10811    }
10812    local_astman_ack(s, m, "Restart: Success", zap_mode);
10813    return 0;
10814 }
10815 
10816 static int zap_action_restart(struct mansession *s, const struct message *m)
10817 {
10818    return __action_restart(s, m, 1);
10819 }
10820 
10821 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10822 {
10823    return __action_restart(s, m, 0);
10824 }
10825 
10826 #define local_astman_unregister(a) do { \
10827                if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10828                   ast_manager_unregister("DAHDI" a); \
10829                } \
10830                ast_manager_unregister("Zap" a); \
10831                } while (0)
10832 
10833 static int __unload_module(void)
10834 {
10835    struct dahdi_pvt *p;
10836 
10837 #ifdef HAVE_PRI
10838    int i, j;
10839    for (i = 0; i < NUM_SPANS; i++) {
10840       if (pris[i].master != AST_PTHREADT_NULL) 
10841          pthread_cancel(pris[i].master);
10842    }
10843    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10844 
10845    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10846       ast_unregister_application(dahdi_send_keypad_facility_app);
10847    }
10848    ast_unregister_application(zap_send_keypad_facility_app);
10849 #endif
10850    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10851    local_astman_unregister("DialOffHook");
10852    local_astman_unregister("Hangup");
10853    local_astman_unregister("Transfer");
10854    local_astman_unregister("DNDoff");
10855    local_astman_unregister("DNDon");
10856    local_astman_unregister("ShowChannels");
10857    local_astman_unregister("Restart");
10858    ast_channel_unregister(chan_tech);
10859    ast_mutex_lock(&iflock);
10860    /* Hangup all interfaces if they have an owner */
10861    p = iflist;
10862    while (p) {
10863       if (p->owner)
10864          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10865       p = p->next;
10866    }
10867    ast_mutex_unlock(&iflock);
10868    ast_mutex_lock(&monlock);
10869    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10870       pthread_cancel(monitor_thread);
10871       pthread_kill(monitor_thread, SIGURG);
10872       pthread_join(monitor_thread, NULL);
10873    }
10874    monitor_thread = AST_PTHREADT_STOP;
10875    ast_mutex_unlock(&monlock);
10876 
10877    destroy_all_channels();
10878 #ifdef HAVE_PRI      
10879    for (i = 0; i < NUM_SPANS; i++) {
10880       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10881          pthread_join(pris[i].master, NULL);
10882       for (j = 0; j < NUM_DCHANS; j++) {
10883          dahdi_close_pri_fd(&(pris[i]), j);
10884       }
10885    }
10886 #endif
10887    ast_cond_destroy(&ss_thread_complete);
10888    return 0;
10889 }
10890 
10891 static int unload_module(void)
10892 {
10893 #ifdef HAVE_PRI      
10894    int y;
10895    for (y = 0; y < NUM_SPANS; y++)
10896       ast_mutex_destroy(&pris[y].lock);
10897 #endif
10898    return __unload_module();
10899 }
10900 
10901 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10902 {
10903    char *c, *chan;
10904    int x, start, finish;
10905    struct dahdi_pvt *tmp;
10906 #ifdef HAVE_PRI
10907    struct dahdi_pri *pri;
10908    int trunkgroup, y;
10909 #endif
10910    
10911    if ((reload == 0) && (conf->chan.sig < 0)) {
10912       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10913       return -1;
10914    }
10915 
10916    c = ast_strdupa(value);
10917 
10918 #ifdef HAVE_PRI
10919    pri = NULL;
10920    if (iscrv) {
10921       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10922          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10923          return -1;
10924       }
10925       if (trunkgroup < 1) {
10926          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10927          return -1;
10928       }
10929       c += y;
10930       for (y = 0; y < NUM_SPANS; y++) {
10931          if (pris[y].trunkgroup == trunkgroup) {
10932             pri = pris + y;
10933             break;
10934          }
10935       }
10936       if (!pri) {
10937          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10938          return -1;
10939       }
10940    }
10941 #endif         
10942 
10943    while ((chan = strsep(&c, ","))) {
10944       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10945          /* Range */
10946       } else if (sscanf(chan, "%d", &start)) {
10947          /* Just one */
10948          finish = start;
10949       } else if (!strcasecmp(chan, "pseudo")) {
10950          finish = start = CHAN_PSEUDO;
10951          if (found_pseudo)
10952             *found_pseudo = 1;
10953       } else {
10954          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10955          return -1;
10956       }
10957       if (finish < start) {
10958          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10959          x = finish;
10960          finish = start;
10961          start = x;
10962       }
10963 
10964       for (x = start; x <= finish; x++) {
10965 #ifdef HAVE_PRI
10966          tmp = mkintf(x, conf, pri, reload);
10967 #else       
10968          tmp = mkintf(x, conf, NULL, reload);
10969 #endif         
10970 
10971          if (tmp) {
10972             if (option_verbose > 2) {
10973 #ifdef HAVE_PRI
10974                if (pri)
10975                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10976                else
10977 #endif
10978                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10979             }
10980          } else {
10981             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10982                (reload == 1) ? "reconfigure" : "register", value);
10983             return -1;
10984          }
10985       }
10986    }
10987 
10988    return 0;
10989 }
10990 
10991 /** The length of the parameters list of 'dahdichan'. 
10992  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10993 #define MAX_CHANLIST_LEN 80
10994 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10995 {
10996    struct dahdi_pvt *tmp;
10997    int y;
10998    int found_pseudo = 0;
10999         char dahdichan[MAX_CHANLIST_LEN] = {};
11000 
11001    for (; v; v = v->next) {
11002       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11003          continue;
11004 
11005       /* Create the interface list */
11006       if (!strcasecmp(v->name, "channel")
11007 #ifdef HAVE_PRI
11008           || !strcasecmp(v->name, "crv")
11009 #endif         
11010          ) {
11011          int iscrv;
11012          if (skipchannels)
11013             continue;
11014          iscrv = !strcasecmp(v->name, "crv");
11015          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11016                return -1;
11017       } else if (!strcasecmp(v->name, "buffers")) {
11018          int res;
11019          char policy[21] = "";
11020 
11021          res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
11022          if (res != 2) {
11023             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11024             confp->chan.buf_no = numbufs;
11025             continue;
11026          }
11027          if (confp->chan.buf_no < 0)
11028             confp->chan.buf_no = numbufs;
11029          if (!strcasecmp(policy, "full")) {
11030             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11031          } else if (!strcasecmp(policy, "immediate")) {
11032             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11033          } else {
11034             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11035          }
11036       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11037          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11038          if (v->name[0] == 'z' || v->name[0] == 'Z') {
11039             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11040          }
11041       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11042          if (ast_true(v->value))
11043             confp->chan.usedistinctiveringdetection = 1;
11044       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11045          if (ast_true(v->value))
11046             distinctiveringaftercid = 1;
11047       } else if (!strcasecmp(v->name, "dring1context")) {
11048          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11049       } else if (!strcasecmp(v->name, "dring2context")) {
11050          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11051       } else if (!strcasecmp(v->name, "dring3context")) {
11052          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11053       } else if (!strcasecmp(v->name, "dring1")) {
11054          sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11055       } else if (!strcasecmp(v->name, "dring2")) {
11056          sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11057       } else if (!strcasecmp(v->name, "dring3")) {
11058          sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11059       } else if (!strcasecmp(v->name, "usecallerid")) {
11060          confp->chan.use_callerid = ast_true(v->value);
11061       } else if (!strcasecmp(v->name, "cidsignalling")) {
11062          if (!strcasecmp(v->value, "bell"))
11063             confp->chan.cid_signalling = CID_SIG_BELL;
11064          else if (!strcasecmp(v->value, "v23"))
11065             confp->chan.cid_signalling = CID_SIG_V23;
11066          else if (!strcasecmp(v->value, "dtmf"))
11067             confp->chan.cid_signalling = CID_SIG_DTMF;
11068          else if (!strcasecmp(v->value, "smdi"))
11069             confp->chan.cid_signalling = CID_SIG_SMDI;
11070          else if (!strcasecmp(v->value, "v23_jp"))
11071             confp->chan.cid_signalling = CID_SIG_V23_JP;
11072          else if (ast_true(v->value))
11073             confp->chan.cid_signalling = CID_SIG_BELL;
11074       } else if (!strcasecmp(v->name, "cidstart")) {
11075          if (!strcasecmp(v->value, "ring"))
11076             confp->chan.cid_start = CID_START_RING;
11077          else if (!strcasecmp(v->value, "polarity"))
11078             confp->chan.cid_start = CID_START_POLARITY;
11079          else if (ast_true(v->value))
11080             confp->chan.cid_start = CID_START_RING;
11081       } else if (!strcasecmp(v->name, "threewaycalling")) {
11082          confp->chan.threewaycalling = ast_true(v->value);
11083       } else if (!strcasecmp(v->name, "cancallforward")) {
11084          confp->chan.cancallforward = ast_true(v->value);
11085       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11086          if (ast_true(v->value)) 
11087             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11088          else
11089             confp->chan.dtmfrelax = 0;
11090       } else if (!strcasecmp(v->name, "mailbox")) {
11091          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11092       } else if (!strcasecmp(v->name, "hasvoicemail")) {
11093          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11094             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11095          }
11096       } else if (!strcasecmp(v->name, "adsi")) {
11097          confp->chan.adsi = ast_true(v->value);
11098       } else if (!strcasecmp(v->name, "usesmdi")) {
11099          confp->chan.use_smdi = ast_true(v->value);
11100       } else if (!strcasecmp(v->name, "smdiport")) {
11101          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11102       } else if (!strcasecmp(v->name, "transfer")) {
11103          confp->chan.transfer = ast_true(v->value);
11104       } else if (!strcasecmp(v->name, "canpark")) {
11105          confp->chan.canpark = ast_true(v->value);
11106       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11107          confp->chan.echocanbridged = ast_true(v->value);
11108       } else if (!strcasecmp(v->name, "busydetect")) {
11109          confp->chan.busydetect = ast_true(v->value);
11110       } else if (!strcasecmp(v->name, "busycount")) {
11111          confp->chan.busycount = atoi(v->value);
11112       } else if (!strcasecmp(v->name, "silencethreshold")) {
11113          confp->chan.silencethreshold = atoi(v->value);
11114       } else if (!strcasecmp(v->name, "busycompare")) {
11115          confp->chan.busycompare = ast_true(v->value);
11116       } else if (!strcasecmp(v->name, "busypattern")) {
11117          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11118          if (count == 1)
11119             confp->chan.busyquietlength = 0;
11120          else if (count < 1)
11121             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11122       } else if (!strcasecmp(v->name, "busyfuzziness")) {
11123          confp->chan.busyfuzziness = atoi(v->value);
11124       } else if (!strcasecmp(v->name, "callprogress")) {
11125          if (ast_true(v->value))
11126             confp->chan.callprogress |= 1;
11127          else
11128             confp->chan.callprogress &= ~1;
11129       } else if (!strcasecmp(v->name, "faxdetect")) {
11130          if (!strcasecmp(v->value, "incoming")) {
11131             confp->chan.callprogress |= 4;
11132             confp->chan.callprogress &= ~2;
11133          } else if (!strcasecmp(v->value, "outgoing")) {
11134             confp->chan.callprogress &= ~4;
11135             confp->chan.callprogress |= 2;
11136          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11137             confp->chan.callprogress |= 6;
11138          else
11139             confp->chan.callprogress &= ~6;
11140       } else if (!strcasecmp(v->name, "echocancel")) {
11141          if (!ast_strlen_zero(v->value)) {
11142             y = atoi(v->value);
11143          } else
11144             y = 0;
11145          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11146             confp->chan.echocancel = y;
11147          else {
11148             confp->chan.echocancel = ast_true(v->value);
11149             if (confp->chan.echocancel)
11150                confp->chan.echocancel=128;
11151          }
11152       } else if (!strcasecmp(v->name, "echotraining")) {
11153          if (sscanf(v->value, "%d", &y) == 1) {
11154             if ((y < 10) || (y > 4000)) {
11155                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
11156             } else {
11157                confp->chan.echotraining = y;
11158             }
11159          } else if (ast_true(v->value)) {
11160             confp->chan.echotraining = 400;
11161          } else
11162             confp->chan.echotraining = 0;
11163       } else if (!strcasecmp(v->name, "hidecallerid")) {
11164          confp->chan.hidecallerid = ast_true(v->value);
11165       } else if (!strcasecmp(v->name, "hidecalleridname")) {
11166          confp->chan.hidecalleridname = ast_true(v->value);
11167       } else if (!strcasecmp(v->name, "pulsedial")) {
11168          confp->chan.pulse = ast_true(v->value);
11169       } else if (!strcasecmp(v->name, "callreturn")) {
11170          confp->chan.callreturn = ast_true(v->value);
11171       } else if (!strcasecmp(v->name, "callwaiting")) {
11172          confp->chan.callwaiting = ast_true(v->value);
11173       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11174          confp->chan.callwaitingcallerid = ast_true(v->value);
11175       } else if (!strcasecmp(v->name, "context")) {
11176          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11177       } else if (!strcasecmp(v->name, "language")) {
11178          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11179       } else if (!strcasecmp(v->name, "progzone")) {
11180          ast_copy_string(progzone, v->value, sizeof(progzone));
11181       } else if (!strcasecmp(v->name, "mohinterpret") 
11182          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11183          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11184       } else if (!strcasecmp(v->name, "mohsuggest")) {
11185          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11186       } else if (!strcasecmp(v->name, "stripmsd")) {
11187          confp->chan.stripmsd = atoi(v->value);
11188       } else if (!strcasecmp(v->name, "jitterbuffers")) {
11189          numbufs = atoi(v->value);
11190       } else if (!strcasecmp(v->name, "group")) {
11191          confp->chan.group = ast_get_group(v->value);
11192       } else if (!strcasecmp(v->name, "callgroup")) {
11193          confp->chan.callgroup = ast_get_group(v->value);
11194       } else if (!strcasecmp(v->name, "pickupgroup")) {
11195          confp->chan.pickupgroup = ast_get_group(v->value);
11196       } else if (!strcasecmp(v->name, "immediate")) {
11197          confp->chan.immediate = ast_true(v->value);
11198       } else if (!strcasecmp(v->name, "transfertobusy")) {
11199          confp->chan.transfertobusy = ast_true(v->value);
11200       } else if (!strcasecmp(v->name, "rxgain")) {
11201          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11202             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11203          }
11204       } else if (!strcasecmp(v->name, "txgain")) {
11205          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11206             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11207          }
11208       } else if (!strcasecmp(v->name, "tonezone")) {
11209          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11210             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11211          }
11212       } else if (!strcasecmp(v->name, "callerid")) {
11213          if (!strcasecmp(v->value, "asreceived")) {
11214             confp->chan.cid_num[0] = '\0';
11215             confp->chan.cid_name[0] = '\0';
11216          } else {
11217             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11218          } 
11219       } else if (!strcasecmp(v->name, "fullname")) {
11220          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11221       } else if (!strcasecmp(v->name, "cid_number")) {
11222          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11223       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11224          confp->chan.dahditrcallerid = ast_true(v->value);
11225          if (strstr(v->name, "zap")) {
11226             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11227          }
11228       } else if (!strcasecmp(v->name, "restrictcid")) {
11229          confp->chan.restrictcid = ast_true(v->value);
11230       } else if (!strcasecmp(v->name, "usecallingpres")) {
11231          confp->chan.use_callingpres = ast_true(v->value);
11232       } else if (!strcasecmp(v->name, "accountcode")) {
11233          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11234       } else if (!strcasecmp(v->name, "amaflags")) {
11235          y = ast_cdr_amaflags2int(v->value);
11236          if (y < 0) 
11237             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11238          else
11239             confp->chan.amaflags = y;
11240       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11241          confp->chan.polarityonanswerdelay = atoi(v->value);
11242       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11243          confp->chan.answeronpolarityswitch = ast_true(v->value);
11244       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11245          confp->chan.hanguponpolarityswitch = ast_true(v->value);
11246       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11247          confp->chan.sendcalleridafter = atoi(v->value);
11248       } else if (reload != 1){ 
11249           if (!strcasecmp(v->name, "signalling")) {
11250             confp->chan.outsigmod = -1;
11251             if (!strcasecmp(v->value, "em")) {
11252                confp->chan.sig = SIG_EM;
11253             } else if (!strcasecmp(v->value, "em_e1")) {
11254                confp->chan.sig = SIG_EM_E1;
11255             } else if (!strcasecmp(v->value, "em_w")) {
11256                confp->chan.sig = SIG_EMWINK;
11257                confp->chan.radio = 0;
11258             } else if (!strcasecmp(v->value, "fxs_ls")) {
11259                confp->chan.sig = SIG_FXSLS;
11260                confp->chan.radio = 0;
11261             } else if (!strcasecmp(v->value, "fxs_gs")) {
11262                confp->chan.sig = SIG_FXSGS;
11263                confp->chan.radio = 0;
11264             } else if (!strcasecmp(v->value, "fxs_ks")) {
11265                confp->chan.sig = SIG_FXSKS;
11266                confp->chan.radio = 0;
11267             } else if (!strcasecmp(v->value, "fxo_ls")) {
11268                confp->chan.sig = SIG_FXOLS;
11269                confp->chan.radio = 0;
11270             } else if (!strcasecmp(v->value, "fxo_gs")) {
11271                confp->chan.sig = SIG_FXOGS;
11272                confp->chan.radio = 0;
11273             } else if (!strcasecmp(v->value, "fxo_ks")) {
11274                confp->chan.sig = SIG_FXOKS;
11275                confp->chan.radio = 0;
11276             } else if (!strcasecmp(v->value, "fxs_rx")) {
11277                confp->chan.sig = SIG_FXSKS;
11278                confp->chan.radio = 1;
11279             } else if (!strcasecmp(v->value, "fxo_rx")) {
11280                confp->chan.sig = SIG_FXOLS;
11281                confp->chan.radio = 1;
11282             } else if (!strcasecmp(v->value, "fxs_tx")) {
11283                confp->chan.sig = SIG_FXSLS;
11284                confp->chan.radio = 1;
11285             } else if (!strcasecmp(v->value, "fxo_tx")) {
11286                confp->chan.sig = SIG_FXOGS;
11287                confp->chan.radio = 1;
11288             } else if (!strcasecmp(v->value, "em_rx")) {
11289                confp->chan.sig = SIG_EM;
11290                confp->chan.radio = 1;
11291             } else if (!strcasecmp(v->value, "em_tx")) {
11292                confp->chan.sig = SIG_EM;
11293                confp->chan.radio = 1;
11294             } else if (!strcasecmp(v->value, "em_rxtx")) {
11295                confp->chan.sig = SIG_EM;
11296                confp->chan.radio = 2;
11297             } else if (!strcasecmp(v->value, "em_txrx")) {
11298                confp->chan.sig = SIG_EM;
11299                confp->chan.radio = 2;
11300             } else if (!strcasecmp(v->value, "sf")) {
11301                confp->chan.sig = SIG_SF;
11302                confp->chan.radio = 0;
11303             } else if (!strcasecmp(v->value, "sf_w")) {
11304                confp->chan.sig = SIG_SFWINK;
11305                confp->chan.radio = 0;
11306             } else if (!strcasecmp(v->value, "sf_featd")) {
11307                confp->chan.sig = SIG_FEATD;
11308                confp->chan.radio = 0;
11309             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11310                confp->chan.sig = SIG_FEATDMF;
11311                confp->chan.radio = 0;
11312             } else if (!strcasecmp(v->value, "sf_featb")) {
11313                confp->chan.sig = SIG_SF_FEATB;
11314                confp->chan.radio = 0;
11315             } else if (!strcasecmp(v->value, "sf")) {
11316                confp->chan.sig = SIG_SF;
11317                confp->chan.radio = 0;
11318             } else if (!strcasecmp(v->value, "sf_rx")) {
11319                confp->chan.sig = SIG_SF;
11320                confp->chan.radio = 1;
11321             } else if (!strcasecmp(v->value, "sf_tx")) {
11322                confp->chan.sig = SIG_SF;
11323                confp->chan.radio = 1;
11324             } else if (!strcasecmp(v->value, "sf_rxtx")) {
11325                confp->chan.sig = SIG_SF;
11326                confp->chan.radio = 2;
11327             } else if (!strcasecmp(v->value, "sf_txrx")) {
11328                confp->chan.sig = SIG_SF;
11329                confp->chan.radio = 2;
11330             } else if (!strcasecmp(v->value, "featd")) {
11331                confp->chan.sig = SIG_FEATD;
11332                confp->chan.radio = 0;
11333             } else if (!strcasecmp(v->value, "featdmf")) {
11334                confp->chan.sig = SIG_FEATDMF;
11335                confp->chan.radio = 0;
11336             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11337                confp->chan.sig = SIG_FEATDMF_TA;
11338                confp->chan.radio = 0;
11339             } else if (!strcasecmp(v->value, "e911")) {
11340                confp->chan.sig = SIG_E911;
11341                confp->chan.radio = 0;
11342             } else if (!strcasecmp(v->value, "fgccama")) {
11343                confp->chan.sig = SIG_FGC_CAMA;
11344                confp->chan.radio = 0;
11345             } else if (!strcasecmp(v->value, "fgccamamf")) {
11346                confp->chan.sig = SIG_FGC_CAMAMF;
11347                confp->chan.radio = 0;
11348             } else if (!strcasecmp(v->value, "featb")) {
11349                confp->chan.sig = SIG_FEATB;
11350                confp->chan.radio = 0;
11351 #ifdef HAVE_PRI
11352             } else if (!strcasecmp(v->value, "pri_net")) {
11353                confp->chan.radio = 0;
11354                confp->chan.sig = SIG_PRI;
11355                confp->pri.nodetype = PRI_NETWORK;
11356             } else if (!strcasecmp(v->value, "pri_cpe")) {
11357                confp->chan.sig = SIG_PRI;
11358                confp->chan.radio = 0;
11359                confp->pri.nodetype = PRI_CPE;
11360             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11361                confp->chan.sig = SIG_GR303FXOKS;
11362                confp->chan.radio = 0;
11363                confp->pri.nodetype = PRI_NETWORK;
11364             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11365                confp->chan.sig = SIG_GR303FXSKS;
11366                confp->chan.radio = 0;
11367                confp->pri.nodetype = PRI_CPE;
11368 #endif
11369             } else {
11370                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11371             }
11372           } else if (!strcasecmp(v->name, "outsignalling")) {
11373             if (!strcasecmp(v->value, "em")) {
11374                confp->chan.outsigmod = SIG_EM;
11375             } else if (!strcasecmp(v->value, "em_e1")) {
11376                confp->chan.outsigmod = SIG_EM_E1;
11377             } else if (!strcasecmp(v->value, "em_w")) {
11378                confp->chan.outsigmod = SIG_EMWINK;
11379             } else if (!strcasecmp(v->value, "sf")) {
11380                confp->chan.outsigmod = SIG_SF;
11381             } else if (!strcasecmp(v->value, "sf_w")) {
11382                confp->chan.outsigmod = SIG_SFWINK;
11383             } else if (!strcasecmp(v->value, "sf_featd")) {
11384                confp->chan.outsigmod = SIG_FEATD;
11385             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11386                confp->chan.outsigmod = SIG_FEATDMF;
11387             } else if (!strcasecmp(v->value, "sf_featb")) {
11388                confp->chan.outsigmod = SIG_SF_FEATB;
11389             } else if (!strcasecmp(v->value, "sf")) {
11390                confp->chan.outsigmod = SIG_SF;
11391             } else if (!strcasecmp(v->value, "featd")) {
11392                confp->chan.outsigmod = SIG_FEATD;
11393             } else if (!strcasecmp(v->value, "featdmf")) {
11394                confp->chan.outsigmod = SIG_FEATDMF;
11395             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11396                confp->chan.outsigmod = SIG_FEATDMF_TA;
11397             } else if (!strcasecmp(v->value, "e911")) {
11398                confp->chan.outsigmod = SIG_E911;
11399             } else if (!strcasecmp(v->value, "fgccama")) {
11400                confp->chan.outsigmod = SIG_FGC_CAMA;
11401             } else if (!strcasecmp(v->value, "fgccamamf")) {
11402                confp->chan.outsigmod = SIG_FGC_CAMAMF;
11403             } else if (!strcasecmp(v->value, "featb")) {
11404                confp->chan.outsigmod = SIG_FEATB;
11405             } else {
11406                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11407             }
11408 #ifdef HAVE_PRI
11409          } else if (!strcasecmp(v->name, "pridialplan")) {
11410             if (!strcasecmp(v->value, "national")) {
11411                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11412             } else if (!strcasecmp(v->value, "unknown")) {
11413                confp->pri.dialplan = PRI_UNKNOWN + 1;
11414             } else if (!strcasecmp(v->value, "private")) {
11415                confp->pri.dialplan = PRI_PRIVATE + 1;
11416             } else if (!strcasecmp(v->value, "international")) {
11417                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11418             } else if (!strcasecmp(v->value, "local")) {
11419                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11420             } else if (!strcasecmp(v->value, "dynamic")) {
11421                confp->pri.dialplan = -1;
11422             } else {
11423                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11424             }
11425          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11426             if (!strcasecmp(v->value, "national")) {
11427                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11428             } else if (!strcasecmp(v->value, "unknown")) {
11429                confp->pri.localdialplan = PRI_UNKNOWN + 1;
11430             } else if (!strcasecmp(v->value, "private")) {
11431                confp->pri.localdialplan = PRI_PRIVATE + 1;
11432             } else if (!strcasecmp(v->value, "international")) {
11433                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11434             } else if (!strcasecmp(v->value, "local")) {
11435                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11436             } else if (!strcasecmp(v->value, "dynamic")) {
11437                confp->pri.localdialplan = -1;
11438             } else {
11439                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11440             }
11441          } else if (!strcasecmp(v->name, "switchtype")) {
11442             if (!strcasecmp(v->value, "national")) 
11443                confp->pri.switchtype = PRI_SWITCH_NI2;
11444             else if (!strcasecmp(v->value, "ni1"))
11445                confp->pri.switchtype = PRI_SWITCH_NI1;
11446             else if (!strcasecmp(v->value, "dms100"))
11447                confp->pri.switchtype = PRI_SWITCH_DMS100;
11448             else if (!strcasecmp(v->value, "4ess"))
11449                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11450             else if (!strcasecmp(v->value, "5ess"))
11451                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11452             else if (!strcasecmp(v->value, "euroisdn"))
11453                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11454             else if (!strcasecmp(v->value, "qsig"))
11455                confp->pri.switchtype = PRI_SWITCH_QSIG;
11456             else {
11457                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11458                return -1;
11459             }
11460          } else if (!strcasecmp(v->name, "nsf")) {
11461             if (!strcasecmp(v->value, "sdn"))
11462                confp->pri.nsf = PRI_NSF_SDN;
11463             else if (!strcasecmp(v->value, "megacom"))
11464                confp->pri.nsf = PRI_NSF_MEGACOM;
11465             else if (!strcasecmp(v->value, "tollfreemegacom"))
11466                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
11467             else if (!strcasecmp(v->value, "accunet"))
11468                confp->pri.nsf = PRI_NSF_ACCUNET;
11469             else if (!strcasecmp(v->value, "none"))
11470                confp->pri.nsf = PRI_NSF_NONE;
11471             else {
11472                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11473                confp->pri.nsf = PRI_NSF_NONE;
11474             }
11475          } else if (!strcasecmp(v->name, "priindication")) {
11476             if (!strcasecmp(v->value, "outofband"))
11477                confp->chan.priindication_oob = 1;
11478             else if (!strcasecmp(v->value, "inband"))
11479                confp->chan.priindication_oob = 0;
11480             else
11481                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11482                   v->value, v->lineno);
11483          } else if (!strcasecmp(v->name, "priexclusive")) {
11484             confp->chan.priexclusive = ast_true(v->value);
11485          } else if (!strcasecmp(v->name, "internationalprefix")) {
11486             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11487          } else if (!strcasecmp(v->name, "nationalprefix")) {
11488             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11489          } else if (!strcasecmp(v->name, "localprefix")) {
11490             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11491          } else if (!strcasecmp(v->name, "privateprefix")) {
11492             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11493          } else if (!strcasecmp(v->name, "unknownprefix")) {
11494             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11495          } else if (!strcasecmp(v->name, "resetinterval")) {
11496             if (!strcasecmp(v->value, "never"))
11497                confp->pri.resetinterval = -1;
11498             else if (atoi(v->value) >= 60)
11499                confp->pri.resetinterval = atoi(v->value);
11500             else
11501                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11502                   v->value, v->lineno);
11503          } else if (!strcasecmp(v->name, "minunused")) {
11504             confp->pri.minunused = atoi(v->value);
11505          } else if (!strcasecmp(v->name, "minidle")) {
11506             confp->pri.minidle = atoi(v->value); 
11507          } else if (!strcasecmp(v->name, "idleext")) {
11508             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11509          } else if (!strcasecmp(v->name, "idledial")) {
11510             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11511          } else if (!strcasecmp(v->name, "overlapdial")) {
11512             confp->pri.overlapdial = ast_true(v->value);
11513 #ifdef HAVE_PRI_INBANDDISCONNECT
11514          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11515             confp->pri.inbanddisconnect = ast_true(v->value);
11516 #endif
11517          } else if (!strcasecmp(v->name, "pritimer")) {
11518 #ifdef PRI_GETSET_TIMERS
11519             char *timerc, *c;
11520             int timer, timeridx;
11521             c = v->value;
11522             timerc = strsep(&c, ",");
11523             if (timerc) {
11524                timer = atoi(c);
11525                if (!timer)
11526                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11527                else {
11528                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
11529                      pritimers[timeridx] = timer;
11530                   else
11531                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11532                }
11533             } else
11534                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11535 
11536          } else if (!strcasecmp(v->name, "facilityenable")) {
11537             confp->pri.facilityenable = ast_true(v->value);
11538 #endif /* PRI_GETSET_TIMERS */
11539 #endif /* HAVE_PRI */
11540          } else if (!strcasecmp(v->name, "cadence")) {
11541             /* setup to scan our argument */
11542             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11543             int i;
11544             struct dahdi_ring_cadence new_cadence;
11545             int cid_location = -1;
11546             int firstcadencepos = 0;
11547             char original_args[80];
11548             int cadence_is_ok = 1;
11549 
11550             ast_copy_string(original_args, v->value, sizeof(original_args));
11551             /* 16 cadences allowed (8 pairs) */
11552             element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
11553    
11554             /* Cadence must be even (on/off) */
11555             if (element_count % 2 == 1) {
11556                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11557                cadence_is_ok = 0;
11558             }
11559    
11560             /* Ring cadences cannot be negative */
11561             for (i = 0; i < element_count; i++) {
11562                if (c[i] == 0) {
11563                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11564                   cadence_is_ok = 0;
11565                   break;
11566                } else if (c[i] < 0) {
11567                   if (i % 2 == 1) {
11568                      /* Silence duration, negative possibly okay */
11569                      if (cid_location == -1) {
11570                         cid_location = i;
11571                         c[i] *= -1;
11572                      } else {
11573                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11574                         cadence_is_ok = 0;
11575                         break;
11576                      }
11577                   } else {
11578                      if (firstcadencepos == 0) {
11579                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11580                                  /* duration will be passed negative to the DAHDI driver */
11581                      } else {
11582                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11583                         cadence_is_ok = 0;
11584                         break;
11585                      }
11586                   }
11587                }
11588             }
11589    
11590             /* Substitute our scanned cadence */
11591             for (i = 0; i < 16; i++) {
11592                new_cadence.ringcadence[i] = c[i];
11593             }
11594    
11595             if (cadence_is_ok) {
11596                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11597                if (element_count < 2) {
11598                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11599                } else {
11600                   if (cid_location == -1) {
11601                      /* user didn't say; default to first pause */
11602                      cid_location = 1;
11603                   } else {
11604                      /* convert element_index to cidrings value */
11605                      cid_location = (cid_location + 1) / 2;
11606                   }
11607                   /* ---we like their cadence; try to install it--- */
11608                   if (!user_has_defined_cadences++)
11609                      /* this is the first user-defined cadence; clear the default user cadences */
11610                      num_cadence = 0;
11611                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11612                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11613                   else {
11614                      cadences[num_cadence] = new_cadence;
11615                      cidrings[num_cadence++] = cid_location;
11616                      if (option_verbose > 2)
11617                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11618                   }
11619                }
11620             }
11621          } else if (!strcasecmp(v->name, "ringtimeout")) {
11622             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11623          } else if (!strcasecmp(v->name, "prewink")) {
11624             confp->timing.prewinktime = atoi(v->value);
11625          } else if (!strcasecmp(v->name, "preflash")) {
11626             confp->timing.preflashtime = atoi(v->value);
11627          } else if (!strcasecmp(v->name, "wink")) {
11628             confp->timing.winktime = atoi(v->value);
11629          } else if (!strcasecmp(v->name, "flash")) {
11630             confp->timing.flashtime = atoi(v->value);
11631          } else if (!strcasecmp(v->name, "start")) {
11632             confp->timing.starttime = atoi(v->value);
11633          } else if (!strcasecmp(v->name, "rxwink")) {
11634             confp->timing.rxwinktime = atoi(v->value);
11635          } else if (!strcasecmp(v->name, "rxflash")) {
11636             confp->timing.rxflashtime = atoi(v->value);
11637          } else if (!strcasecmp(v->name, "debounce")) {
11638             confp->timing.debouncetime = atoi(v->value);
11639          } else if (!strcasecmp(v->name, "toneduration")) {
11640             int toneduration;
11641             int ctlfd;
11642             int res;
11643             struct dahdi_dialparams dps;
11644 
11645             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
11646 
11647             if (ctlfd == -1) {
11648                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
11649                return -1;
11650             }
11651 
11652             toneduration = atoi(v->value);
11653             if (toneduration > -1) {
11654                memset(&dps, 0, sizeof(dps));
11655 
11656                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11657                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11658                if (res < 0) {
11659                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11660                   return -1;
11661                }
11662             }
11663             close(ctlfd);
11664          } else if (!strcasecmp(v->name, "defaultcic")) {
11665             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11666          } else if (!strcasecmp(v->name, "defaultozz")) {
11667             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11668          } 
11669       } else if (!skipchannels)
11670          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11671    }
11672    if (dahdichan[0]) { 
11673       /* The user has set 'dahdichan' */
11674       /*< \todo pass proper line number instead of 0 */
11675       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11676          return -1;
11677       }
11678    }
11679    /*< \todo why check for the pseudo in the per-channel section.
11680     * Any actual use for manual setup of the pseudo channel? */
11681    if (!found_pseudo && reload == 0) {
11682       /* use the default configuration for a channel, so
11683          that any settings from real configured channels
11684          don't "leak" into the pseudo channel config
11685       */
11686       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11687 
11688       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
11689 
11690       if (tmp) {
11691          if (option_verbose > 2)
11692             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11693       } else {
11694          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11695       }
11696    }
11697    return 0;
11698 }
11699       
11700 static int setup_dahdi(int reload)
11701 {
11702    struct ast_config *cfg;
11703    struct ast_variable *v;
11704    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11705    int res;
11706 
11707 #ifdef HAVE_PRI
11708    char *c;
11709    int spanno;
11710    int i, x;
11711    int logicalspan;
11712    int trunkgroup;
11713    int dchannels[NUM_DCHANS];
11714 #endif
11715 
11716 #ifdef HAVE_ZAPTEL
11717    int load_from_zapata_conf = 1;
11718 #else
11719    int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11720 #endif
11721 
11722    if (load_from_zapata_conf) {
11723       if (!(cfg = ast_config_load("zapata.conf"))) {
11724          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11725          return 0;
11726       }
11727    } else {
11728       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11729          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11730          return 0;
11731       }
11732    }
11733 
11734    /* It's a little silly to lock it, but we mind as well just to be sure */
11735    ast_mutex_lock(&iflock);
11736 #ifdef HAVE_PRI
11737    if (reload != 1) {
11738       /* Process trunkgroups first */
11739       v = ast_variable_browse(cfg, "trunkgroups");
11740       while (v) {
11741          if (!strcasecmp(v->name, "trunkgroup")) {
11742             trunkgroup = atoi(v->value);
11743             if (trunkgroup > 0) {
11744                if ((c = strchr(v->value, ','))) {
11745                   i = 0;
11746                   memset(dchannels, 0, sizeof(dchannels));
11747                   while (c && (i < NUM_DCHANS)) {
11748                      dchannels[i] = atoi(c + 1);
11749                      if (dchannels[i] < 0) {
11750                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11751                      } else
11752                         i++;
11753                      c = strchr(c + 1, ',');
11754                   }
11755                   if (i) {
11756                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11757                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
11758                      } else if (option_verbose > 1)
11759                         ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11760                   } else
11761                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11762                } else
11763                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11764             } else
11765                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11766          } else if (!strcasecmp(v->name, "spanmap")) {
11767             spanno = atoi(v->value);
11768             if (spanno > 0) {
11769                if ((c = strchr(v->value, ','))) {
11770                   trunkgroup = atoi(c + 1);
11771                   if (trunkgroup > 0) {
11772                      if ((c = strchr(c + 1, ','))) 
11773                         logicalspan = atoi(c + 1);
11774                      else
11775                         logicalspan = 0;
11776                      if (logicalspan >= 0) {
11777                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11778                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11779                         } else if (option_verbose > 1) 
11780                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11781                      } else
11782                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
11783                   } else
11784                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11785                } else
11786                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11787             } else
11788                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11789          } else {
11790             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11791          }
11792          v = v->next;
11793       }
11794    }
11795 #endif
11796    
11797    /* Copy the default jb config over global_jbconf */
11798    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11799 
11800    v = ast_variable_browse(cfg, "channels");
11801    res = process_dahdi(&conf, "", v, reload, 0);
11802    ast_mutex_unlock(&iflock);
11803    ast_config_destroy(cfg);
11804    if (res)
11805       return res;
11806    cfg = ast_config_load("users.conf");
11807    if (cfg) {
11808       char *cat;
11809       const char *chans;
11810       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11811       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11812          if (!strcasecmp(cat, "general"))
11813             continue;
11814          chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11815          if (!ast_strlen_zero(chans)) {
11816             struct dahdi_chan_conf sect_conf;
11817             memcpy(&sect_conf, &conf, sizeof(sect_conf));
11818 
11819             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11820          }
11821       }
11822       ast_config_destroy(cfg);
11823    }
11824 #ifdef HAVE_PRI
11825    if (reload != 1) {
11826       for (x = 0; x < NUM_SPANS; x++) {
11827          if (pris[x].pvts[0]) {
11828             if (start_pri(pris + x)) {
11829                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11830                return -1;
11831             } else if (option_verbose > 1)
11832                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11833          }
11834       }
11835    }
11836 #endif
11837    /* And start the monitor for the first time */
11838    restart_monitor();
11839    return 0;
11840 }
11841 
11842 #define local_astman_register(a, b, c, d) do { \
11843                   if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11844                      ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11845                   } \
11846                   ast_manager_register("Zap" a, b, zap_ ## c, d); \
11847                  } while (0)
11848 
11849 static int load_module(void)
11850 {
11851    int res;
11852 
11853 #ifdef HAVE_PRI
11854    int y,i;
11855    memset(pris, 0, sizeof(pris));
11856    for (y = 0; y < NUM_SPANS; y++) {
11857       ast_mutex_init(&pris[y].lock);
11858       pris[y].offset = -1;
11859       pris[y].master = AST_PTHREADT_NULL;
11860       for (i = 0; i < NUM_DCHANS; i++)
11861          pris[y].fds[i] = -1;
11862    }
11863    pri_set_error(dahdi_pri_error);
11864    pri_set_message(dahdi_pri_message);
11865    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11866       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11867          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11868    }
11869    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11870       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11871 #endif
11872    if ((res = setup_dahdi(0))) {
11873       return AST_MODULE_LOAD_DECLINE;
11874    }
11875    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11876       chan_tech = &dahdi_tech;
11877    } else {
11878       chan_tech = &zap_tech;
11879    }
11880    if (ast_channel_register(chan_tech)) {
11881       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11882       __unload_module();
11883       return -1;
11884    }
11885 #ifdef HAVE_PRI
11886    ast_string_field_init(&inuse, 16);
11887    ast_string_field_set(&inuse, name, "GR-303InUse");
11888    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11889 #endif   
11890    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11891    
11892    memset(round_robin, 0, sizeof(round_robin));
11893    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11894    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11895    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11896    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11897    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11898    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11899    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11900 
11901    ast_cond_init(&ss_thread_complete, NULL);
11902 
11903    return res;
11904 }
11905 
11906 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11907 {
11908 #define  END_SILENCE_LEN 400
11909 #define  HEADER_MS 50
11910 #define  TRAILER_MS 5
11911 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11912 #define  ASCII_BYTES_PER_CHAR 80
11913 
11914    unsigned char *buf,*mybuf;
11915    struct dahdi_pvt *p = c->tech_pvt;
11916    struct pollfd fds[1];
11917    int size,res,fd,len,x;
11918    int bytes=0;
11919    /* Initial carrier (imaginary) */
11920    float cr = 1.0;
11921    float ci = 0.0;
11922    float scont = 0.0;
11923    int index;
11924 
11925    index = dahdi_get_index(c, p, 0);
11926    if (index < 0) {
11927       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11928       return -1;
11929    }
11930    if (!text[0]) return(0); /* if nothing to send, dont */
11931    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11932    if (p->mate) 
11933       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11934    else
11935       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11936    if (!buf)
11937       return -1;
11938    mybuf = buf;
11939    if (p->mate) {
11940       int codec = AST_LAW(p);
11941       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11942          PUT_CLID_MARKMS;
11943       }
11944       /* Put actual message */
11945       for (x = 0; text[x]; x++) {
11946          PUT_CLID(text[x]);
11947       }
11948       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11949          PUT_CLID_MARKMS;
11950       }
11951       len = bytes;
11952       buf = mybuf;
11953    } else {
11954       len = tdd_generate(p->tdd, buf, text);
11955       if (len < 1) {
11956          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11957          free(mybuf);
11958          return -1;
11959       }
11960    }
11961    memset(buf + len, 0x7f, END_SILENCE_LEN);
11962    len += END_SILENCE_LEN;
11963    fd = p->subs[index].dfd;
11964    while (len) {
11965       if (ast_check_hangup(c)) {
11966          free(mybuf);
11967          return -1;
11968       }
11969       size = len;
11970       if (size > READ_SIZE)
11971          size = READ_SIZE;
11972       fds[0].fd = fd;
11973       fds[0].events = POLLOUT | POLLPRI;
11974       fds[0].revents = 0;
11975       res = poll(fds, 1, -1);
11976       if (!res) {
11977          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11978          continue;
11979       }
11980         /* if got exception */
11981       if (fds[0].revents & POLLPRI) {
11982          ast_free(mybuf);
11983          return -1;
11984       }
11985       if (!(fds[0].revents & POLLOUT)) {
11986          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11987          continue;
11988       }
11989       res = write(fd, buf, size);
11990       if (res != size) {
11991          if (res == -1) {
11992             free(mybuf);
11993             return -1;
11994          }
11995          if (option_debug)
11996             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11997          break;
11998       }
11999       len -= size;
12000       buf += size;
12001    }
12002    free(mybuf);
12003    return(0);
12004 }
12005 
12006 
12007 static int reload(void)
12008 {
12009    int res = 0;
12010 
12011    res = setup_dahdi(1);
12012    if (res) {
12013       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12014       return -1;
12015    }
12016    return 0;
12017 }
12018 
12019 /* This is a workaround so that menuselect displays a proper description
12020  * AST_MODULE_INFO(, , "DAHDI Telephony"
12021  */
12022 
12023 #ifdef HAVE_PRI
12024 #define tdesc "DAHDI Telephony w/PRI"
12025 #else
12026 #define tdesc "DAHDI Telephony"
12027 #endif
12028 
12029 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12030       .load = load_module,
12031       .unload = unload_module,
12032       .reload = reload,
12033           );
12034 
12035 

Generated on Wed Mar 4 19:58:04 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7