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