Tue Aug 24 2010 19:41:27

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    <use>openr2</use>
00047  ***/
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 283124 $")
00052 
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <math.h>
00061 #include <ctype.h>
00062 
00063 #include <dahdi/user.h>
00064 #include <dahdi/tonezone.h>
00065 
00066 #ifdef HAVE_PRI
00067 #include <libpri.h>
00068 #endif
00069 
00070 #ifdef HAVE_SS7
00071 #include <libss7.h>
00072 #endif
00073 
00074 #ifdef HAVE_OPENR2
00075 #include <openr2.h>
00076 #endif
00077 
00078 #include "asterisk/lock.h"
00079 #include "asterisk/channel.h"
00080 #include "asterisk/config.h"
00081 #include "asterisk/module.h"
00082 #include "asterisk/pbx.h"
00083 #include "asterisk/file.h"
00084 #include "asterisk/ulaw.h"
00085 #include "asterisk/alaw.h"
00086 #include "asterisk/callerid.h"
00087 #include "asterisk/adsi.h"
00088 #include "asterisk/cli.h"
00089 #include "asterisk/cdr.h"
00090 #include "asterisk/features.h"
00091 #include "asterisk/musiconhold.h"
00092 #include "asterisk/say.h"
00093 #include "asterisk/tdd.h"
00094 #include "asterisk/app.h"
00095 #include "asterisk/dsp.h"
00096 #include "asterisk/astdb.h"
00097 #include "asterisk/manager.h"
00098 #include "asterisk/causes.h"
00099 #include "asterisk/term.h"
00100 #include "asterisk/utils.h"
00101 #include "asterisk/transcap.h"
00102 #include "asterisk/stringfields.h"
00103 #include "asterisk/abstract_jb.h"
00104 #include "asterisk/smdi.h"
00105 #include "asterisk/astobj.h"
00106 #include "asterisk/event.h"
00107 #include "asterisk/devicestate.h"
00108 #include "asterisk/paths.h"
00109 
00110 /*** DOCUMENTATION
00111    <application name="DAHDISendKeypadFacility" language="en_US">
00112       <synopsis>
00113          Send digits out of band over a PRI.
00114       </synopsis>
00115       <syntax>
00116          <parameter name="digits" required="true" />
00117       </syntax>
00118       <description>
00119          <para>This application will send the given string of digits in a Keypad
00120          Facility IE over the current channel.</para>
00121       </description>
00122    </application>
00123    <application name="DAHDISendCallreroutingFacility" language="en_US">
00124       <synopsis>
00125          Send QSIG call rerouting facility over a PRI.
00126       </synopsis>
00127       <syntax argsep=",">
00128          <parameter name="destination" required="true">
00129             <para>Destination number.</para>
00130          </parameter>
00131          <parameter name="original">
00132             <para>Original called number.</para>
00133          </parameter>
00134          <parameter name="reason">
00135             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00136          </parameter>
00137       </syntax>
00138       <description>
00139          <para>This application will send a Callrerouting Facility IE over the
00140          current channel.</para>
00141       </description>
00142    </application>
00143    <application name="DAHDIAcceptR2Call" language="en_US">
00144       <synopsis>
00145          Accept an R2 call if its not already accepted (you still need to answer it)
00146       </synopsis>
00147       <syntax>
00148          <parameter name="charge" required="true">
00149             <para>Yes or No.</para>
00150             <para>Whether you want to accept the call with charge or without charge.</para>
00151          </parameter>
00152       </syntax>
00153       <description>
00154          <para>This application will Accept the R2 call either with charge or no charge.</para>
00155       </description>
00156    </application>
00157  ***/
00158 
00159 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00160 
00161 static const char *lbostr[] = {
00162 "0 db (CSU)/0-133 feet (DSX-1)",
00163 "133-266 feet (DSX-1)",
00164 "266-399 feet (DSX-1)",
00165 "399-533 feet (DSX-1)",
00166 "533-655 feet (DSX-1)",
00167 "-7.5db (CSU)",
00168 "-15db (CSU)",
00169 "-22.5db (CSU)"
00170 };
00171 
00172 /*! Global jitterbuffer configuration - by default, jb is disabled */
00173 static struct ast_jb_conf default_jbconf =
00174 {
00175    .flags = 0,
00176    .max_size = -1,
00177    .resync_threshold = -1,
00178    .impl = "",
00179    .target_extra = -1,
00180 };
00181 static struct ast_jb_conf global_jbconf;
00182 
00183 /* define this to send PRI user-user information elements */
00184 #undef SUPPORT_USERUSER
00185 
00186 /*!
00187  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00188  * the user hangs up to reset the state machine so ring works properly.
00189  * This is used to be able to support kewlstart by putting the zhone in
00190  * groundstart mode since their forward disconnect supervision is entirely
00191  * broken even though their documentation says it isn't and their support
00192  * is entirely unwilling to provide any assistance with their channel banks
00193  * even though their web site says they support their products for life.
00194  */
00195 /* #define ZHONE_HACK */
00196 
00197 /*! \note
00198  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00199  * before dialing on it.  Certain FXO interfaces always think they're out of
00200  * service with this method however.
00201  */
00202 /* #define DAHDI_CHECK_HOOKSTATE */
00203 
00204 /*! \brief Typically, how many rings before we should send Caller*ID */
00205 #define DEFAULT_CIDRINGS 1
00206 
00207 #define CHANNEL_PSEUDO -12
00208 
00209 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00210 
00211 
00212 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00213 #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))
00214 
00215 static const char tdesc[] = "DAHDI Telephony Driver"
00216 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00217    " w/"
00218 #endif
00219 #ifdef HAVE_PRI
00220    "PRI"
00221 #endif
00222 #ifdef HAVE_SS7
00223    #ifdef HAVE_PRI
00224    " & SS7"
00225    #else
00226    "SS7"
00227    #endif
00228 #endif
00229 #ifdef HAVE_OPENR2
00230    #if defined(HAVE_PRI) || defined(HAVE_SS7)
00231    " & MFC/R2"
00232    #else
00233    "MFC/R2"
00234    #endif
00235 #endif
00236 ;
00237 
00238 static const char config[] = "chan_dahdi.conf";
00239 
00240 #define SIG_EM    DAHDI_SIG_EM
00241 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00242 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00243 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00244 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00245 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00246 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00247 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00248 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00249 #define SIG_FXSLS DAHDI_SIG_FXSLS
00250 #define SIG_FXSGS DAHDI_SIG_FXSGS
00251 #define SIG_FXSKS DAHDI_SIG_FXSKS
00252 #define SIG_FXOLS DAHDI_SIG_FXOLS
00253 #define SIG_FXOGS DAHDI_SIG_FXOGS
00254 #define SIG_FXOKS DAHDI_SIG_FXOKS
00255 #define SIG_PRI      DAHDI_SIG_CLEAR
00256 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00257 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00258 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00259 #define SIG_MFCR2    DAHDI_SIG_CAS
00260 #define  SIG_SF      DAHDI_SIG_SF
00261 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00262 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00263 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00264 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00265 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00266 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00267 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00268 
00269 #ifdef LOTS_OF_SPANS
00270 #define NUM_SPANS DAHDI_MAX_SPANS
00271 #else
00272 #define NUM_SPANS       32
00273 #endif
00274 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00275 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00276 
00277 #define CHAN_PSEUDO  -2
00278 
00279 #define DCHAN_PROVISIONED (1 << 0)
00280 #define DCHAN_NOTINALARM  (1 << 1)
00281 #define DCHAN_UP          (1 << 2)
00282 
00283 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00284 
00285 /* Overlap dialing option types */
00286 #define DAHDI_OVERLAPDIAL_NONE 0
00287 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00288 #define DAHDI_OVERLAPDIAL_INCOMING 2
00289 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00290 
00291 #define CALLPROGRESS_PROGRESS    1
00292 #define CALLPROGRESS_FAX_OUTGOING   2
00293 #define CALLPROGRESS_FAX_INCOMING   4
00294 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00295 
00296 static char defaultcic[64] = "";
00297 static char defaultozz[64] = "";
00298 
00299 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00300 
00301 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00302 static char mwimonitornotify[PATH_MAX] = "";
00303 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00304 static int  mwisend_rpas = 0;
00305 #endif
00306 
00307 static char progzone[10] = "";
00308 
00309 static int usedistinctiveringdetection = 0;
00310 static int distinctiveringaftercid = 0;
00311 
00312 static int numbufs = 4;
00313 
00314 static int mwilevel = 512;
00315 
00316 #ifdef HAVE_PRI
00317 static struct ast_channel inuse;
00318 #ifdef PRI_GETSET_TIMERS
00319 static int pritimers[PRI_MAX_TIMERS];
00320 #endif
00321 static int pridebugfd = -1;
00322 static char pridebugfilename[1024] = "";
00323 #endif
00324 
00325 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00326 static int firstdigittimeout = 16000;
00327 
00328 /*! \brief How long to wait for following digits (FXO logic) */
00329 static int gendigittimeout = 8000;
00330 
00331 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00332 static int matchdigittimeout = 3000;
00333 
00334 /*! \brief Protect the interface list (of dahdi_pvt's) */
00335 AST_MUTEX_DEFINE_STATIC(iflock);
00336 
00337 /* QSIG channel mapping option types */
00338 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00339 #define DAHDI_CHAN_MAPPING_LOGICAL  1
00340 
00341 
00342 static int ifcount = 0;
00343 
00344 #ifdef HAVE_PRI
00345 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00346 #endif
00347 
00348 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00349    when it's doing something critical. */
00350 AST_MUTEX_DEFINE_STATIC(monlock);
00351 
00352 /*! \brief This is the thread for the monitor which checks for input on the channels
00353    which are not currently in use. */
00354 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00355 static ast_cond_t ss_thread_complete;
00356 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00357 AST_MUTEX_DEFINE_STATIC(restart_lock);
00358 static int ss_thread_count = 0;
00359 static int num_restart_pending = 0;
00360 
00361 static int restart_monitor(void);
00362 
00363 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);
00364 
00365 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00366 
00367 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00368 {
00369    /* This module does not handle MWI in an event-based manner.  However, it
00370     * subscribes to MWI for each mailbox that is configured so that the core
00371     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00372     * event cache instead of checking the mailbox directly. */
00373 }
00374 
00375 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00376 static inline int dahdi_get_event(int fd)
00377 {
00378    int j;
00379    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00380       return -1;
00381    return j;
00382 }
00383 
00384 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00385 static inline int dahdi_wait_event(int fd)
00386 {
00387    int i, j = 0;
00388    i = DAHDI_IOMUX_SIGEVENT;
00389    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00390       return -1;
00391    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00392       return -1;
00393    return j;
00394 }
00395 
00396 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00397 #define READ_SIZE 160
00398 
00399 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00400 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00401 
00402 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00403 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00404 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00405 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00406 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00407 
00408 struct dahdi_pvt;
00409 
00410 /*!
00411  * \brief Configured ring timeout base.
00412  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00413  */
00414 static int ringt_base = DEFAULT_RINGT;
00415 
00416 #ifdef HAVE_SS7
00417 
00418 #define LINKSTATE_INALARM  (1 << 0)
00419 #define LINKSTATE_STARTING (1 << 1)
00420 #define LINKSTATE_UP    (1 << 2)
00421 #define LINKSTATE_DOWN     (1 << 3)
00422 
00423 #define SS7_NAI_DYNAMIC    -1
00424 
00425 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00426 
00427 struct dahdi_ss7 {
00428    pthread_t master;                /*!< Thread of master */
00429    ast_mutex_t lock;
00430    int fds[NUM_DCHANS];
00431    int numsigchans;
00432    int linkstate[NUM_DCHANS];
00433    int numchans;
00434    int type;
00435    enum {
00436       LINKSET_STATE_DOWN = 0,
00437       LINKSET_STATE_UP
00438    } state;
00439    char called_nai;                 /*!< Called Nature of Address Indicator */
00440    char calling_nai;                /*!< Calling Nature of Address Indicator */
00441    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00442    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00443    char subscriberprefix[20];             /*!< area access code + area code ('0'+area code for european dialplans) */
00444    char unknownprefix[20];                /*!< for unknown dialplans */
00445    struct ss7 *ss7;
00446    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00447    int flags;                    /*!< Linkset flags */
00448 };
00449 
00450 static struct dahdi_ss7 linksets[NUM_SPANS];
00451 
00452 static int cur_ss7type = -1;
00453 static int cur_linkset = -1;
00454 static int cur_pointcode = -1;
00455 static int cur_cicbeginswith = -1;
00456 static int cur_adjpointcode = -1;
00457 static int cur_networkindicator = -1;
00458 static int cur_defaultdpc = -1;
00459 #endif /* HAVE_SS7 */
00460 
00461 #ifdef HAVE_OPENR2
00462 struct dahdi_mfcr2 {
00463    pthread_t r2master;            /*!< Thread of master */
00464    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00465    struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
00466    int numchans;                          /*!< Number of channels in this R2 block */
00467    int monitored_count;                   /*!< Number of channels being monitored */
00468 };
00469 
00470 struct dahdi_mfcr2_conf {
00471    openr2_variant_t variant;
00472    int mfback_timeout;
00473    int metering_pulse_timeout;
00474    int max_ani;
00475    int max_dnis;
00476    signed int get_ani_first:2;
00477 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00478    signed int skip_category_request:2;
00479 #endif
00480    unsigned int call_files:1;
00481    unsigned int allow_collect_calls:1;
00482    unsigned int charge_calls:1;
00483    unsigned int accept_on_offer:1;
00484    unsigned int forced_release:1;
00485    unsigned int double_answer:1;
00486    signed int immediate_accept:2;
00487    char logdir[OR2_MAX_PATH];
00488    char r2proto_file[OR2_MAX_PATH];
00489    openr2_log_level_t loglevel;
00490    openr2_calling_party_category_t category;
00491 };
00492 
00493 /* malloc'd array of malloc'd r2links */
00494 static struct dahdi_mfcr2 **r2links;
00495 /* how many r2links have been malloc'd */
00496 static int r2links_count = 0;
00497 
00498 #endif /* HAVE_OPENR2 */
00499 
00500 #ifdef HAVE_PRI
00501 
00502 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00503 #define PRI_CHANNEL(p) ((p) & 0xff)
00504 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00505 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00506 
00507 struct dahdi_pri {
00508    pthread_t master;                /*!< Thread of master */
00509    ast_mutex_t lock;                /*!< Mutex */
00510    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00511    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00512    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00513    int minunused;                   /*!< Min # of channels to keep empty */
00514    int minidle;                     /*!< Min # of "idling" calls to keep active */
00515    int nodetype;                    /*!< Node type */
00516    int switchtype;                     /*!< Type of switch to emulate */
00517    int nsf;                   /*!< Network-Specific Facilities */
00518    int dialplan;                    /*!< Dialing plan */
00519    int localdialplan;                  /*!< Local dialing plan */
00520    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00521    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00522    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00523    char privateprefix[20];                /*!< for private dialplans */
00524    char unknownprefix[20];                /*!< for unknown dialplans */
00525    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00526    int trunkgroup;                     /*!< What our trunkgroup is */
00527    int mastertrunkgroup;                  /*!< What trunk group is our master */
00528    int prilogicalspan;                 /*!< Logical span number within trunk group */
00529    int numchans;                    /*!< Num of channels we represent */
00530    int overlapdial;                 /*!< In overlap dialing mode */
00531    int qsigchannelmapping;                /*!< QSIG channel mapping type */
00532    int discardremoteholdretrieval;              /*!< shall remote hold or remote retrieval notifications be discarded? */
00533    int facilityenable;                 /*!< Enable facility IEs */
00534    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00535    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00536    struct pri *pri;                 /*!< Currently active D-channel */
00537    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00538    int debug;
00539    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00540    /*! \brief Value set but not used */
00541    int offset;
00542    /*! \brief Span number put into user output messages */
00543    int span;
00544    /*! \brief TRUE if span is being reset/restarted */
00545    int resetting;
00546    /*! \brief Current position during a reset (-1 if not started) */
00547    int resetpos;
00548 #ifdef HAVE_PRI_INBANDDISCONNECT
00549    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00550 #endif
00551    time_t lastreset;                /*!< time when unused channels were last reset */
00552    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00553    /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
00554    int sig;
00555    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00556    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00557    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00558 };
00559 
00560 
00561 static struct dahdi_pri pris[NUM_SPANS];
00562 
00563 #if 0
00564 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00565 #else
00566 #define DEFAULT_PRI_DEBUG 0
00567 #endif
00568 
00569 static inline void pri_rel(struct dahdi_pri *pri)
00570 {
00571    ast_mutex_unlock(&pri->lock);
00572 }
00573 
00574 #else
00575 /*! Shut up the compiler */
00576 struct dahdi_pri;
00577 #endif
00578 
00579 #define SUB_REAL  0        /*!< Active call */
00580 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00581 #define SUB_THREEWAY 2        /*!< Three-way call */
00582 
00583 /* Polarity states */
00584 #define POLARITY_IDLE   0
00585 #define POLARITY_REV    1
00586 
00587 
00588 struct distRingData {
00589    int ring[3];
00590    int range;
00591 };
00592 struct ringContextData {
00593    char contextData[AST_MAX_CONTEXT];
00594 };
00595 struct dahdi_distRings {
00596    struct distRingData ringnum[3];
00597    struct ringContextData ringContext[3];
00598 };
00599 
00600 static char *subnames[] = {
00601    "Real",
00602    "Callwait",
00603    "Threeway"
00604 };
00605 
00606 struct dahdi_subchannel {
00607    int dfd;
00608    struct ast_channel *owner;
00609    int chan;
00610    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00611    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00612    unsigned int needringing:1;
00613    unsigned int needbusy:1;
00614    unsigned int needcongestion:1;
00615    unsigned int needcallerid:1;
00616    unsigned int needanswer:1;
00617    unsigned int needflash:1;
00618    unsigned int needhold:1;
00619    unsigned int needunhold:1;
00620    unsigned int linear:1;
00621    unsigned int inthreeway:1;
00622    struct dahdi_confinfo curconf;
00623 };
00624 
00625 #define CONF_USER_REAL     (1 << 0)
00626 #define CONF_USER_THIRDCALL   (1 << 1)
00627 
00628 #define MAX_SLAVES   4
00629 
00630 /* States for sending MWI message
00631  * First three states are required for send Ring Pulse Alert Signal
00632  */
00633 typedef enum {
00634    MWI_SEND_NULL = 0,
00635    MWI_SEND_SA,
00636    MWI_SEND_SA_WAIT,
00637    MWI_SEND_PAUSE,
00638    MWI_SEND_SPILL,
00639    MWI_SEND_CLEANUP,
00640    MWI_SEND_DONE,
00641 } mwisend_states;
00642 
00643 struct mwisend_info {
00644    struct   timeval  pause;
00645    mwisend_states    mwisend_current;
00646 };
00647 
00648 static struct dahdi_pvt {
00649    ast_mutex_t lock;             /*!< Channel private lock. */
00650    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00651                      /*!< Up to three channels can be associated with this call */
00652 
00653    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00654    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00655    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00656 
00657    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00658    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00659    int inconference;          /*!< If our real should be in the conference */
00660 
00661    int bufsize;                /*!< Size of the buffers */
00662    int buf_no;             /*!< Number of buffers */
00663    int buf_policy;            /*!< Buffer policy */
00664    int faxbuf_no;              /*!< Number of Fax buffers */
00665    int faxbuf_policy;          /*!< Fax buffer policy */
00666    int sig;             /*!< Signalling style */
00667    /*!
00668     * \brief Nonzero if the signaling type is sent over a radio.
00669     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00670     */
00671    int radio;
00672    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00673    int oprmode;               /*!< "Operator Services" mode */
00674    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00675    /*! \brief Amount of gain to increase during caller id */
00676    float cid_rxgain;
00677    /*! \brief Rx gain set by chan_dahdi.conf */
00678    float rxgain;
00679    /*! \brief Tx gain set by chan_dahdi.conf */
00680    float txgain;
00681    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00682    struct dahdi_pvt *next;          /*!< Next channel in list */
00683    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00684 
00685    /* flags */
00686 
00687    /*!
00688     * \brief TRUE if ADSI (Analog Display Services Interface) available
00689     * \note Set from the "adsi" value read in from chan_dahdi.conf
00690     */
00691    unsigned int adsi:1;
00692    /*!
00693     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00694     * call is answered by the remote party.
00695     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00696     */
00697    unsigned int answeronpolarityswitch:1;
00698    /*!
00699     * \brief TRUE if busy detection is enabled.
00700     * (Listens for the beep-beep busy pattern.)
00701     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00702     */
00703    unsigned int busydetect:1;
00704    /*!
00705     * \brief TRUE if call return is enabled.
00706     * (*69, if your dialplan doesn't catch this first)
00707     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00708     */
00709    unsigned int callreturn:1;
00710    /*!
00711     * \brief TRUE if busy extensions will hear the call-waiting tone
00712     * and can use hook-flash to switch between callers.
00713     * \note Can be disabled by dialing *70.
00714     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00715     */
00716    unsigned int callwaiting:1;
00717    /*!
00718     * \brief TRUE if send caller ID for Call Waiting
00719     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00720     */
00721    unsigned int callwaitingcallerid:1;
00722    /*!
00723     * \brief TRUE if support for call forwarding enabled.
00724     * Dial *72 to enable call forwarding.
00725     * Dial *73 to disable call forwarding.
00726     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00727     */
00728    unsigned int cancallforward:1;
00729    /*!
00730     * \brief TRUE if support for call parking is enabled.
00731     * \note Set from the "canpark" value read in from chan_dahdi.conf
00732     */
00733    unsigned int canpark:1;
00734    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00735    unsigned int confirmanswer:1;
00736    /*!
00737     * \brief TRUE if the channel is to be destroyed on hangup.
00738     * (Used by pseudo channels.)
00739     */
00740    unsigned int destroy:1;
00741    unsigned int didtdd:1;           /*!< flag to say its done it once */
00742    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00743    unsigned int dialednone:1;
00744    /*! \brief TRUE if in the process of dialing digits or sending something. */
00745    unsigned int dialing:1;
00746    /*! \brief TRUE if the transfer capability of the call is digital. */
00747    unsigned int digital:1;
00748    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00749    unsigned int dnd:1;
00750    /*! \brief XXX BOOLEAN Purpose??? */
00751    unsigned int echobreak:1;
00752    /*!
00753     * \brief TRUE if echo cancellation enabled when bridged.
00754     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00755     * \note Disabled if the echo canceller is not setup.
00756     */
00757    unsigned int echocanbridged:1;
00758    /*! \brief TRUE if echo cancellation is turned on. */
00759    unsigned int echocanon:1;
00760    /*! \brief TRUE if a fax tone has already been handled. */
00761    unsigned int faxhandled:1;
00762    /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
00763    unsigned int usefaxbuffers:1;
00764    /*! \brief TRUE while dynamic faxbuffers are in use */
00765    unsigned int bufferoverrideinuse:1;
00766    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00767    unsigned int firstradio:1;
00768    /*!
00769     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00770     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00771     */
00772    unsigned int hanguponpolarityswitch:1;
00773    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00774    unsigned int hardwaredtmf:1;
00775    /*!
00776     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00777     * \note Caller ID can be disabled by dialing *67.
00778     * \note Caller ID can be enabled by dialing *82.
00779     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00780     */
00781    unsigned int hidecallerid:1;
00782    /*!
00783     * \brief TRUE if hide just the name not the number for legacy PBX use.
00784     * \note Only applies to PRI channels.
00785     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00786     */
00787    unsigned int hidecalleridname:1;
00788    /*! \brief TRUE if DTMF detection is disabled. */
00789    unsigned int ignoredtmf:1;
00790    /*!
00791     * \brief TRUE if the channel should be answered immediately
00792     * without attempting to gather any digits.
00793     * \note Set from the "immediate" value read in from chan_dahdi.conf
00794     */
00795    unsigned int immediate:1;
00796    /*! \brief TRUE if in an alarm condition. */
00797    unsigned int inalarm:1;
00798    /*! \brief TRUE if TDD in MATE mode */
00799    unsigned int mate:1;
00800    /*! \brief TRUE if we originated the call leg. */
00801    unsigned int outgoing:1;
00802    /* unsigned int overlapdial:1;         unused and potentially confusing */
00803    /*!
00804     * \brief TRUE if busy extensions will hear the call-waiting tone
00805     * and can use hook-flash to switch between callers.
00806     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00807     */
00808    unsigned int permcallwaiting:1;
00809    /*!
00810     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00811     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00812     */
00813    unsigned int permhidecallerid:1;
00814    /*!
00815     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00816     * \note Set from the "priindication" value read in from chan_dahdi.conf
00817     */
00818    unsigned int priindication_oob:1;
00819    /*!
00820     * \brief TRUE if PRI B channels are always exclusively selected.
00821     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00822     */
00823    unsigned int priexclusive:1;
00824    /*!
00825     * \brief TRUE if we will pulse dial.
00826     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00827     */
00828    unsigned int pulse:1;
00829    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00830    unsigned int pulsedial:1;
00831    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00832    /*!
00833     * \brief TRUE if caller ID is restricted.
00834     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00835     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00836     */
00837    unsigned int restrictcid:1;
00838    /*!
00839     * \brief TRUE if three way calling is enabled
00840     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00841     */
00842    unsigned int threewaycalling:1;
00843    /*!
00844     * \brief TRUE if call transfer is enabled
00845     * \note For FXS ports (either direct analog or over T1/E1):
00846     *   Support flash-hook call transfer
00847     * \note For digital ports using ISDN PRI protocols:
00848     *   Support switch-side transfer (called 2BCT, RLT or other names)
00849     * \note Set from the "transfer" value read in from chan_dahdi.conf
00850     */
00851    unsigned int transfer:1;
00852    /*!
00853     * \brief TRUE if caller ID is used on this channel.
00854     * \note PRI and SS7 spans will save caller ID from the networking peer.
00855     * \note FXS ports will generate the caller ID spill.
00856     * \note FXO ports will listen for the caller ID spill.
00857     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00858     */
00859    unsigned int use_callerid:1;
00860    /*!
00861     * \brief TRUE if we will use the calling presentation setting
00862     * from the Asterisk channel for outgoing calls.
00863     * \note Only applies to PRI and SS7 channels.
00864     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00865     */
00866    unsigned int use_callingpres:1;
00867    /*!
00868     * \brief TRUE if distinctive rings are to be detected.
00869     * \note For FXO lines
00870     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00871     */
00872    unsigned int usedistinctiveringdetection:1;
00873    /*!
00874     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00875     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00876     */
00877    unsigned int dahditrcallerid:1;
00878    /*!
00879     * \brief TRUE if allowed to flash-transfer to busy channels.
00880     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00881     */
00882    unsigned int transfertobusy:1;
00883    /*!
00884     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00885     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00886     */
00887    unsigned int mwimonitor_neon:1;
00888    /*!
00889     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00890     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00891     */
00892    unsigned int mwimonitor_fsk:1;
00893    /*!
00894     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00895     * \note RPAS - Ring Pulse Alert Signal
00896     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00897     */
00898    unsigned int mwimonitor_rpas:1;
00899    /*! \brief TRUE if an MWI monitor thread is currently active */
00900    unsigned int mwimonitoractive:1;
00901    /*! \brief TRUE if a MWI message sending thread is active */
00902    unsigned int mwisendactive:1;
00903    /*!
00904     * \brief TRUE if channel is out of reset and ready
00905     * \note Set but not used.
00906     */
00907    unsigned int inservice:1;
00908    /*!
00909     * \brief TRUE if the channel is locally blocked.
00910     * \note Applies to SS7 channels.
00911     */
00912    unsigned int locallyblocked:1;
00913    /*!
00914     * \brief TRUE if the channel is remotely blocked.
00915     * \note Applies to SS7 channels.
00916     */
00917    unsigned int remotelyblocked:1;
00918 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00919    /*!
00920     * \brief XXX BOOLEAN Purpose???
00921     * \note Applies to SS7 channels.
00922     */
00923    unsigned int rlt:1;
00924    /*! \brief TRUE if channel is alerting/ringing */
00925    unsigned int alerting:1;
00926    /*! \brief TRUE if the call has already gone/hungup */
00927    unsigned int alreadyhungup:1;
00928    /*!
00929     * \brief TRUE if this is an idle call
00930     * \note Applies to PRI channels.
00931     */
00932    unsigned int isidlecall:1;
00933    /*!
00934     * \brief TRUE if call is in a proceeding state.
00935     * The call has started working its way through the network.
00936     */
00937    unsigned int proceeding:1;
00938    /*! \brief TRUE if the call has seen progress through the network. */
00939    unsigned int progress:1;
00940    /*!
00941     * \brief TRUE if this channel is being reset/restarted
00942     * \note Applies to PRI channels.
00943     */
00944    unsigned int resetting:1;
00945    /*!
00946     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00947     * \note Applies to PRI channels.
00948     */
00949    unsigned int setup_ack:1;
00950 #endif
00951    /*!
00952     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00953     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00954     */
00955    unsigned int use_smdi:1;
00956    struct mwisend_info mwisend_data;
00957    /*! \brief The serial port to listen for SMDI data on */
00958    struct ast_smdi_interface *smdi_iface;
00959 
00960    /*! \brief Distinctive Ring data */
00961    struct dahdi_distRings drings;
00962 
00963    /*!
00964     * \brief The configured context for incoming calls.
00965     * \note The "context" string read in from chan_dahdi.conf
00966     */
00967    char context[AST_MAX_CONTEXT];
00968    /*!
00969     * \brief Saved context string.
00970     */
00971    char defcontext[AST_MAX_CONTEXT];
00972    /*! \brief Extension to use in the dialplan. */
00973    char exten[AST_MAX_EXTENSION];
00974    /*!
00975     * \brief Language configured for calls.
00976     * \note The "language" string read in from chan_dahdi.conf
00977     */
00978    char language[MAX_LANGUAGE];
00979    /*!
00980     * \brief The configured music-on-hold class to use for calls.
00981     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00982     */
00983    char mohinterpret[MAX_MUSICCLASS];
00984    /*!
00985     * \brief Suggested music-on-hold class for peer channel to use for calls.
00986     * \note The "mohsuggest" string read in from chan_dahdi.conf
00987     */
00988    char mohsuggest[MAX_MUSICCLASS];
00989    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
00990 #if defined(PRI_ANI) || defined(HAVE_SS7)
00991    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00992    char cid_ani[AST_MAX_EXTENSION];
00993 #endif
00994    /*! \brief Automatic Number Identification code from PRI */
00995    int cid_ani2;
00996    /*! \brief Caller ID number from an incoming call. */
00997    char cid_num[AST_MAX_EXTENSION];
00998    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00999    int cid_ton;
01000    /*! \brief Caller ID name from an incoming call. */
01001    char cid_name[AST_MAX_EXTENSION];
01002    /*! \brief Last Caller ID number from an incoming call. */
01003    char lastcid_num[AST_MAX_EXTENSION];
01004    /*! \brief Last Caller ID name from an incoming call. */
01005    char lastcid_name[AST_MAX_EXTENSION];
01006    char *origcid_num;            /*!< malloced original callerid */
01007    char *origcid_name;           /*!< malloced original callerid */
01008    /*! \brief Call waiting number. */
01009    char callwait_num[AST_MAX_EXTENSION];
01010    /*! \brief Call waiting name. */
01011    char callwait_name[AST_MAX_EXTENSION];
01012    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01013    char rdnis[AST_MAX_EXTENSION];
01014    /*! \brief Dialed Number Identifier */
01015    char dnid[AST_MAX_EXTENSION];
01016    /*!
01017     * \brief Bitmapped groups this belongs to.
01018     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01019     */
01020    ast_group_t group;
01021    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01022    int law;
01023    int confno;             /*!< Our conference */
01024    int confusers;             /*!< Who is using our conference */
01025    int propconfno;               /*!< Propagated conference number */
01026    /*!
01027     * \brief Bitmapped call groups this belongs to.
01028     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01029     */
01030    ast_group_t callgroup;
01031    /*!
01032     * \brief Bitmapped pickup groups this belongs to.
01033     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01034     */
01035    ast_group_t pickupgroup;
01036    /*!
01037     * \brief Channel variable list with associated values to set when a channel is created.
01038     * \note The "setvar" strings read in from chan_dahdi.conf
01039     */
01040    struct ast_variable *vars;
01041    int channel;               /*!< Channel Number or CRV */
01042    int span;               /*!< Span number */
01043    time_t guardtime;          /*!< Must wait this much time before using for new call */
01044    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01045    int cid_start;             /*!< CID start indicator, polarity or ring */
01046    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01047    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01048    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
01049    /*! \brief Analog caller ID waveform sample buffer */
01050    unsigned char *cidspill;
01051    /*! \brief Position in the cidspill buffer to send out next. */
01052    int cidpos;
01053    /*! \brief Length of the cidspill buffer containing samples. */
01054    int cidlen;
01055    /*! \brief Ring timeout timer?? */
01056    int ringt;
01057    /*!
01058     * \brief Ring timeout base.
01059     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01060     */
01061    int ringt_base;
01062    /*!
01063     * \brief Number of most significant digits/characters to strip from the dialed number.
01064     * \note Feature is deprecated.  Use dialplan logic.
01065     * \note The characters are stripped before the PRI TON/NPI prefix
01066     * characters are processed.
01067     */
01068    int stripmsd;
01069    /*! \brief BOOLEAN. XXX Meaning what?? */
01070    int callwaitcas;
01071    /*! \brief Number of call waiting rings. */
01072    int callwaitrings;
01073    /*! \brief Echo cancel parameters. */
01074    struct {
01075       struct dahdi_echocanparams head;
01076       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01077    } echocancel;
01078    /*!
01079     * \brief Echo training time. 0 = disabled
01080     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01081     */
01082    int echotraining;
01083    /*! \brief Filled with 'w'.  XXX Purpose?? */
01084    char echorest[20];
01085    /*!
01086     * \brief Number of times to see "busy" tone before hanging up.
01087     * \note Set from the "busycount" value read in from chan_dahdi.conf
01088     */
01089    int busycount;
01090    /*!
01091     * \brief Length of "busy" tone on time.
01092     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01093     */
01094    int busy_tonelength;
01095    /*!
01096     * \brief Length of "busy" tone off time.
01097     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01098     */
01099    int busy_quietlength;
01100    /*!
01101     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01102     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01103     */
01104    int callprogress;
01105    /*!
01106     * \brief Number of milliseconds to wait for dialtone.
01107     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01108     */
01109    int waitfordialtone;
01110    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01111    struct timeval flashtime;        /*!< Last flash-hook time */
01112    /*! \brief Opaque DSP configuration structure. */
01113    struct ast_dsp *dsp;
01114    //int cref;             /*!< Call reference number (Not used) */
01115    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01116    struct dahdi_dialoperation dop;
01117    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01118    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01119    char finaldial[64];
01120    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01121    int amaflags;              /*!< AMA Flags */
01122    struct tdd_state *tdd;           /*!< TDD flag */
01123    /*! \brief Accumulated call forwarding number. */
01124    char call_forward[AST_MAX_EXTENSION];
01125    /*!
01126     * \brief Voice mailbox location.
01127     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01128     */
01129    char mailbox[AST_MAX_EXTENSION];
01130    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01131    struct ast_event_sub *mwi_event_sub;
01132    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01133    char dialdest[256];
01134    /*! \brief Time the interface went on-hook. */
01135    int onhooktime;
01136    /*! \brief TRUE if the FXS port is off-hook */
01137    int fxsoffhookstate;
01138    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
01139    int msgstate;
01140 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01141    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01142    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01143    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01144 #endif
01145    int distinctivering;          /*!< Which distinctivering to use */
01146    int cidrings;              /*!< Which ring to deliver CID on */
01147    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01148    /*! \brief Holding place for event injected from outside normal operation. */
01149    int fake_event;
01150    /*!
01151     * \brief Minimal time period (ms) between the answer polarity
01152     * switch and hangup polarity switch.
01153     */
01154    int polarityonanswerdelay;
01155    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01156    struct timeval polaritydelaytv;
01157    /*!
01158     * \brief Send caller ID after this many rings.
01159     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01160     */
01161    int sendcalleridafter;
01162 #ifdef HAVE_PRI
01163    /*! \brief DAHDI PRI control parameters */
01164    struct dahdi_pri *pri;
01165    /*! \brief XXX Purpose??? */
01166    struct dahdi_pvt *bearer;
01167    /*! \brief XXX Purpose??? */
01168    struct dahdi_pvt *realcall;
01169    /*! \brief Opaque libpri call control structure */
01170    q931_call *call;
01171    /*! \brief Channel number in span. */
01172    int prioffset;
01173    /*! \brief Logical span number within trunk group */
01174    int logicalspan;
01175 #endif
01176    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01177    int polarity;
01178    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01179    int dsp_features;
01180 #ifdef HAVE_SS7
01181    /*! \brief SS7 control parameters */
01182    struct dahdi_ss7 *ss7;
01183    /*! \brief Opaque libss7 call control structure */
01184    struct isup_call *ss7call;
01185    char charge_number[50];
01186    char gen_add_number[50];
01187    char gen_dig_number[50];
01188    char orig_called_num[50];
01189    char redirecting_num[50];
01190    char generic_name[50];
01191    unsigned char gen_add_num_plan;
01192    unsigned char gen_add_nai;
01193    unsigned char gen_add_pres_ind;
01194    unsigned char gen_add_type;
01195    unsigned char gen_dig_type;
01196    unsigned char gen_dig_scheme;
01197    char jip_number[50];
01198    unsigned char lspi_type;
01199    unsigned char lspi_scheme;
01200    unsigned char lspi_context;
01201    char lspi_ident[50];
01202    unsigned int call_ref_ident;
01203    unsigned int call_ref_pc;
01204    unsigned char calling_party_cat;
01205    int transcap;
01206    int cic;                   /*!< CIC associated with channel */
01207    unsigned int dpc;                /*!< CIC's DPC */
01208    unsigned int loopedback:1;
01209 #endif
01210 #ifdef HAVE_OPENR2
01211    struct dahdi_mfcr2 *mfcr2;
01212    openr2_chan_t *r2chan;
01213    openr2_calling_party_category_t mfcr2_recvd_category;
01214    openr2_calling_party_category_t mfcr2_category;
01215    int mfcr2_dnis_index;
01216    int mfcr2_ani_index;
01217    int mfcr2call:1;
01218    int mfcr2_answer_pending:1;
01219    int mfcr2_charge_calls:1;
01220    int mfcr2_allow_collect_calls:1;
01221    int mfcr2_forced_release:1;
01222    int mfcr2_dnis_matched:1;
01223    int mfcr2_call_accepted:1;
01224    int mfcr2_accept_on_offer:1;
01225 #endif
01226    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01227    char begindigit;
01228    /*! \brief TRUE if confrence is muted. */
01229    int muting;
01230 } *iflist = NULL, *ifend = NULL;
01231 
01232 /*! \brief Channel configuration from chan_dahdi.conf .
01233  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01234  * Generally there is a field here for every possible configuration item.
01235  *
01236  * The state of fields is saved along the parsing and whenever a 'channel'
01237  * statement is reached, the current dahdi_chan_conf is used to configure the
01238  * channel (struct dahdi_pvt)
01239  *
01240  * \see dahdi_chan_init for the default values.
01241  */
01242 struct dahdi_chan_conf {
01243    struct dahdi_pvt chan;
01244 #ifdef HAVE_PRI
01245    struct dahdi_pri pri;
01246 #endif
01247 
01248 #ifdef HAVE_SS7
01249    struct dahdi_ss7 ss7;
01250 #endif
01251 
01252 #ifdef HAVE_OPENR2
01253    struct dahdi_mfcr2_conf mfcr2;
01254 #endif
01255    struct dahdi_params timing;
01256    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01257 
01258    /*!
01259     * \brief The serial port to listen for SMDI data on
01260     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01261     */
01262    char smdi_port[SMDI_MAX_FILENAME_LEN];
01263 };
01264 
01265 /*! returns a new dahdi_chan_conf with default values (by-value) */
01266 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01267 {
01268    /* recall that if a field is not included here it is initialized
01269     * to 0 or equivalent
01270     */
01271    struct dahdi_chan_conf conf = {
01272 #ifdef HAVE_PRI
01273       .pri = {
01274          .nsf = PRI_NSF_NONE,
01275          .switchtype = PRI_SWITCH_NI2,
01276          .dialplan = PRI_UNKNOWN + 1,
01277          .localdialplan = PRI_NATIONAL_ISDN + 1,
01278          .nodetype = PRI_CPE,
01279          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01280 
01281          .minunused = 2,
01282          .idleext = "",
01283          .idledial = "",
01284          .internationalprefix = "",
01285          .nationalprefix = "",
01286          .localprefix = "",
01287          .privateprefix = "",
01288          .unknownprefix = "",
01289          .resetinterval = -1,
01290       },
01291 #endif
01292 #ifdef HAVE_SS7
01293       .ss7 = {
01294          .called_nai = SS7_NAI_NATIONAL,
01295          .calling_nai = SS7_NAI_NATIONAL,
01296          .internationalprefix = "",
01297          .nationalprefix = "",
01298          .subscriberprefix = "",
01299          .unknownprefix = ""
01300       },
01301 #endif
01302 #ifdef HAVE_OPENR2
01303       .mfcr2 = {
01304          .variant = OR2_VAR_ITU,
01305          .mfback_timeout = -1,
01306          .metering_pulse_timeout = -1,
01307          .max_ani = 10,
01308          .max_dnis = 4,
01309          .get_ani_first = -1,
01310 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01311          .skip_category_request = -1,
01312 #endif
01313          .call_files = 0,
01314          .allow_collect_calls = 0,
01315          .charge_calls = 1,
01316          .accept_on_offer = 1,
01317          .forced_release = 0,
01318          .double_answer = 0,
01319          .immediate_accept = -1,
01320          .logdir = "",
01321          .r2proto_file = "",
01322          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01323          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01324       },
01325 #endif
01326       .chan = {
01327          .context = "default",
01328          .cid_num = "",
01329          .cid_name = "",
01330          .mohinterpret = "default",
01331          .mohsuggest = "",
01332          .parkinglot = "",
01333          .transfertobusy = 1,
01334 
01335          .cid_signalling = CID_SIG_BELL,
01336          .cid_start = CID_START_RING,
01337          .dahditrcallerid = 0,
01338          .use_callerid = 1,
01339          .sig = -1,
01340          .outsigmod = -1,
01341 
01342          .cid_rxgain = +5.0,
01343 
01344          .tonezone = -1,
01345 
01346          .echocancel.head.tap_length = 1,
01347 
01348          .busycount = 3,
01349 
01350          .accountcode = "",
01351 
01352          .mailbox = "",
01353 
01354 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01355          .mwisend_fsk = 1,
01356 #endif
01357          .polarityonanswerdelay = 600,
01358 
01359          .sendcalleridafter = DEFAULT_CIDRINGS,
01360 
01361          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01362          .buf_no = numbufs,
01363          .usefaxbuffers = 0,
01364          .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01365          .faxbuf_no = numbufs,
01366       },
01367       .timing = {
01368          .prewinktime = -1,
01369          .preflashtime = -1,
01370          .winktime = -1,
01371          .flashtime = -1,
01372          .starttime = -1,
01373          .rxwinktime = -1,
01374          .rxflashtime = -1,
01375          .debouncetime = -1
01376       },
01377       .is_sig_auto = 1,
01378       .smdi_port = "/dev/ttyS0",
01379    };
01380 
01381    return conf;
01382 }
01383 
01384 
01385 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01386 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01387 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01388 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01389 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01390 static int dahdi_hangup(struct ast_channel *ast);
01391 static int dahdi_answer(struct ast_channel *ast);
01392 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01393 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01394 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01395 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01396 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01397 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01398 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01399 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01400 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01401 
01402 static const struct ast_channel_tech dahdi_tech = {
01403    .type = "DAHDI",
01404    .description = tdesc,
01405    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01406    .requester = dahdi_request,
01407    .send_digit_begin = dahdi_digit_begin,
01408    .send_digit_end = dahdi_digit_end,
01409    .send_text = dahdi_sendtext,
01410    .call = dahdi_call,
01411    .hangup = dahdi_hangup,
01412    .answer = dahdi_answer,
01413    .read = dahdi_read,
01414    .write = dahdi_write,
01415    .bridge = dahdi_bridge,
01416    .exception = dahdi_exception,
01417    .indicate = dahdi_indicate,
01418    .fixup = dahdi_fixup,
01419    .setoption = dahdi_setoption,
01420    .func_channel_read = dahdi_func_read,
01421    .func_channel_write = dahdi_func_write,
01422 };
01423 
01424 #ifdef HAVE_PRI
01425 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01426 #else
01427 #define GET_CHANNEL(p) ((p)->channel)
01428 #endif
01429 
01430 struct dahdi_pvt *round_robin[32];
01431 
01432 #if defined(HAVE_PRI)
01433 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01434 {
01435    int res;
01436    /* Grab the lock first */
01437    do {
01438       res = ast_mutex_trylock(&pri->lock);
01439       if (res) {
01440          DEADLOCK_AVOIDANCE(&pvt->lock);
01441       }
01442    } while (res);
01443    /* Then break the poll */
01444    if (pri->master != AST_PTHREADT_NULL)
01445       pthread_kill(pri->master, SIGURG);
01446    return 0;
01447 }
01448 #endif   /* defined(HAVE_PRI) */
01449 
01450 #if defined(HAVE_SS7)
01451 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01452 {
01453    ast_mutex_unlock(&ss7->lock);
01454 }
01455 #endif   /* defined(HAVE_SS7) */
01456 
01457 #if defined(HAVE_SS7)
01458 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01459 {
01460    int res;
01461    /* Grab the lock first */
01462    do {
01463       res = ast_mutex_trylock(&pri->lock);
01464       if (res) {
01465          DEADLOCK_AVOIDANCE(&pvt->lock);
01466       }
01467    } while (res);
01468    /* Then break the poll */
01469    if (pri->master != AST_PTHREADT_NULL)
01470       pthread_kill(pri->master, SIGURG);
01471    return 0;
01472 }
01473 #endif   /* defined(HAVE_SS7) */
01474 #define NUM_CADENCE_MAX 25
01475 static int num_cadence = 4;
01476 static int user_has_defined_cadences = 0;
01477 
01478 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01479    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01480    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01481    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01482    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01483 };
01484 
01485 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01486  * is 1, the second pause is 2 and so on.
01487  */
01488 
01489 static int cidrings[NUM_CADENCE_MAX] = {
01490    2,                            /*!< Right after first long ring */
01491    4,                            /*!< Right after long part */
01492    3,                            /*!< After third chirp */
01493    2,                            /*!< Second spell */
01494 };
01495 
01496 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01497 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01498 
01499 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01500          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01501 
01502 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01503 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01504 
01505 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01506 {
01507    int res;
01508    if (p->subs[SUB_REAL].owner == ast)
01509       res = 0;
01510    else if (p->subs[SUB_CALLWAIT].owner == ast)
01511       res = 1;
01512    else if (p->subs[SUB_THREEWAY].owner == ast)
01513       res = 2;
01514    else {
01515       res = -1;
01516       if (!nullok)
01517          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01518    }
01519    return res;
01520 }
01521 
01522 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01523 {
01524 #ifdef HAVE_PRI
01525    if (pri)
01526       ast_mutex_unlock(&pri->lock);
01527 #endif
01528    for (;;) {
01529       if (p->subs[a].owner) {
01530          if (ast_channel_trylock(p->subs[a].owner)) {
01531             DEADLOCK_AVOIDANCE(&p->lock);
01532          } else {
01533             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01534             ast_channel_unlock(p->subs[a].owner);
01535             break;
01536          }
01537       } else
01538          break;
01539    }
01540 #ifdef HAVE_PRI
01541    if (pri)
01542       ast_mutex_lock(&pri->lock);
01543 #endif
01544 }
01545 
01546 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01547 {
01548 #ifdef HAVE_PRI
01549    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01550 #endif
01551 #ifdef HAVE_SS7
01552    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01553 #endif
01554    /* We must unlock the PRI to avoid the possibility of a deadlock */
01555 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01556    if (data) {
01557       switch (p->sig) {
01558 #ifdef HAVE_PRI
01559       case SIG_BRI:
01560       case SIG_BRI_PTMP:
01561       case SIG_PRI:
01562          ast_mutex_unlock(&pri->lock);
01563          break;
01564 #endif
01565 #ifdef HAVE_SS7
01566       case SIG_SS7:
01567          ast_mutex_unlock(&ss7->lock);
01568          break;
01569 #endif
01570       default:
01571          break;
01572       }
01573    }
01574 #endif
01575    for (;;) {
01576       if (p->owner) {
01577          if (ast_channel_trylock(p->owner)) {
01578             DEADLOCK_AVOIDANCE(&p->lock);
01579          } else {
01580             ast_queue_frame(p->owner, f);
01581             ast_channel_unlock(p->owner);
01582             break;
01583          }
01584       } else
01585          break;
01586    }
01587 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01588    if (data) {
01589       switch (p->sig) {
01590 #ifdef HAVE_PRI
01591       case SIG_BRI:
01592       case SIG_BRI_PTMP:
01593       case SIG_PRI:
01594          ast_mutex_lock(&pri->lock);
01595          break;
01596 #endif
01597 #ifdef HAVE_SS7
01598       case SIG_SS7:
01599          ast_mutex_lock(&ss7->lock);
01600          break;
01601 #endif
01602       default:
01603          break;
01604       }
01605    }
01606 #endif
01607 }
01608 
01609 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01610 #ifdef HAVE_OPENR2
01611 
01612 static int dahdi_r2_answer(struct dahdi_pvt *p)
01613 {
01614    int res = 0;
01615    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01616    * and does not has support for openr2_chan_answer_call_with_mode
01617    *  */
01618 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01619    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01620    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01621    if (!double_answer) {
01622       /* this still can result in double answer if the channel context
01623       * was configured that way */
01624       res = openr2_chan_answer_call(p->r2chan);
01625    } else if (wants_double_answer) {
01626       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01627    } else {
01628       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01629    }
01630 #else
01631    res = openr2_chan_answer_call(p->r2chan);
01632 #endif
01633    return res;
01634 }
01635 
01636 
01637 
01638 /* should be called with the ast_channel locked */
01639 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01640 {
01641    openr2_calling_party_category_t cat;
01642    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01643    struct dahdi_pvt *p = c->tech_pvt;
01644    if (ast_strlen_zero(catstr)) {
01645       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01646             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01647       return p->mfcr2_category;
01648    }
01649    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01650       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01651             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01652       return p->mfcr2_category;
01653    }
01654    ast_debug(1, "Using category %s\n", catstr);
01655    return cat;
01656 }
01657 
01658 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01659 {
01660    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01661    ast_mutex_lock(&p->lock);
01662    if (p->mfcr2call) {
01663       ast_mutex_unlock(&p->lock);
01664       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
01665          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
01666          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
01667          the other end will see our seize as a forced release and drop the call, we will see an invalid
01668          pattern that will be seen and treated as protocol error. */
01669       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01670       return;
01671    }
01672    p->mfcr2call = 1;
01673    /* better safe than sorry ... */
01674    p->cid_name[0] = '\0';
01675    p->cid_num[0] = '\0';
01676    p->rdnis[0] = '\0';
01677    p->exten[0] = '\0';
01678    p->mfcr2_ani_index = '\0';
01679    p->mfcr2_dnis_index = '\0';
01680    p->mfcr2_dnis_matched = 0;
01681    p->mfcr2_answer_pending = 0;
01682    p->mfcr2_call_accepted = 0;
01683    ast_mutex_unlock(&p->lock);
01684    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01685 }
01686 
01687 static int get_alarms(struct dahdi_pvt *p);
01688 static void handle_alarms(struct dahdi_pvt *p, int alms);
01689 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01690 {
01691    int res;
01692    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01693    ast_mutex_lock(&p->lock);
01694    p->inalarm = alarm ? 1 : 0;
01695    if (p->inalarm) {
01696       res = get_alarms(p);
01697       handle_alarms(p, res);
01698    } else {
01699       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01700       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01701    }
01702    ast_mutex_unlock(&p->lock);
01703 }
01704 
01705 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01706 {
01707    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01708 }
01709 
01710 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01711 {
01712    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01713    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01714    if (p->owner) {
01715       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01716       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01717    }
01718    ast_mutex_lock(&p->lock);
01719    p->mfcr2call = 0;
01720    ast_mutex_unlock(&p->lock);
01721 }
01722 
01723 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01724 {
01725    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01726       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01727          p->channel, openr2_proto_get_disconnect_string(cause));
01728       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01729       openr2_chan_set_idle(p->r2chan);
01730       ast_mutex_lock(&p->lock);
01731       p->mfcr2call = 0;
01732       ast_mutex_unlock(&p->lock);
01733    }
01734 }
01735 
01736 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01737 {
01738    struct dahdi_pvt *p;
01739    struct ast_channel *c;
01740    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01741          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01742          openr2_proto_get_category_string(category));
01743    p = openr2_chan_get_client_data(r2chan);
01744    /* if collect calls are not allowed and this is a collect call, reject it! */
01745    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01746       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01747       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01748       return;
01749    }
01750    ast_mutex_lock(&p->lock);
01751    p->mfcr2_recvd_category = category;
01752    /* if we're not supposed to use CID, clear whatever we have */
01753    if (!p->use_callerid) {
01754       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01755       p->cid_num[0] = 0;
01756       p->cid_name[0] = 0;
01757    }
01758    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01759    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01760       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01761       p->exten[0] = 's';
01762       p->exten[1] = 0;
01763    }
01764    ast_mutex_unlock(&p->lock);
01765    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01766       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01767             p->channel, p->exten, p->context);
01768       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01769       return;
01770    }
01771    if (!p->mfcr2_accept_on_offer) {
01772       /* The user wants us to start the PBX thread right away without accepting the call first */
01773       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01774       if (c) {
01775          /* Done here, don't disable reading now since we still need to generate MF tones to accept
01776             the call or reject it and detect the tone off condition of the other end, all of this
01777             will be done in the PBX thread now */
01778          return;
01779       }
01780       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01781       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01782    } else if (p->mfcr2_charge_calls) {
01783       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01784       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01785    } else {
01786       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01787       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01788    }
01789 }
01790 
01791 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01792 {
01793    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01794    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01795    ast_mutex_lock(&p->lock);
01796    p->mfcr2call = 0;
01797    ast_mutex_unlock(&p->lock);
01798 }
01799 
01800 static void dahdi_enable_ec(struct dahdi_pvt *p);
01801 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01802 {
01803    struct dahdi_pvt *p = NULL;
01804    struct ast_channel *c = NULL;
01805    p = openr2_chan_get_client_data(r2chan);
01806    dahdi_enable_ec(p);
01807    p->mfcr2_call_accepted = 1;
01808    /* if it's an incoming call ... */
01809    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01810       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01811       /* If accept on offer is not set, it means at this point the PBX thread is already
01812          launched (was launched in the 'on call offered' handler) and therefore this callback
01813          is being executed already in the PBX thread rather than the monitor thread, don't launch
01814          any other thread, just disable the openr2 reading and answer the call if needed */
01815       if (!p->mfcr2_accept_on_offer) {
01816          openr2_chan_disable_read(r2chan);
01817          if (p->mfcr2_answer_pending) {
01818             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01819             dahdi_r2_answer(p);
01820          }
01821          return;
01822       }
01823       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01824       if (c) {
01825          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
01826             library to forget about it */
01827          openr2_chan_disable_read(r2chan);
01828          return;
01829       }
01830       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01831       /* failed to create the channel, bail out and report it as an out of order line */
01832       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01833       return;
01834    }
01835    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
01836    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01837    p->subs[SUB_REAL].needringing = 1;
01838    p->dialing = 0;
01839    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
01840    openr2_chan_disable_read(r2chan);
01841 }
01842 
01843 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01844 {
01845    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01846    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01847    p->subs[SUB_REAL].needanswer = 1;
01848 }
01849 
01850 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01851 {
01852    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01853 }
01854 
01855 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01856 {
01857    switch (cause) {
01858    case OR2_CAUSE_BUSY_NUMBER:
01859       return AST_CAUSE_BUSY;
01860    case OR2_CAUSE_NETWORK_CONGESTION:
01861       return AST_CAUSE_CONGESTION;
01862    case OR2_CAUSE_OUT_OF_ORDER:
01863       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01864    case OR2_CAUSE_UNALLOCATED_NUMBER:
01865       return AST_CAUSE_UNREGISTERED;
01866    case OR2_CAUSE_NO_ANSWER:
01867       return AST_CAUSE_NO_ANSWER;
01868    case OR2_CAUSE_NORMAL_CLEARING:
01869       return AST_CAUSE_NORMAL_CLEARING;
01870    case OR2_CAUSE_UNSPECIFIED:
01871    default:
01872       return AST_CAUSE_NOTDEFINED;
01873    }
01874 }
01875 
01876 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01877 {
01878    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01879    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01880    ast_mutex_lock(&p->lock);
01881    if (!p->owner) {
01882       ast_mutex_unlock(&p->lock);
01883       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
01884       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01885       return;
01886    }
01887    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
01888       be done in dahdi_hangup */
01889    if (p->owner->_state == AST_STATE_UP) {
01890       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01891       ast_mutex_unlock(&p->lock);
01892    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01893       /* being the forward side we must report what happened to the call to whoever requested it */
01894       switch (cause) {
01895       case OR2_CAUSE_BUSY_NUMBER:
01896          p->subs[SUB_REAL].needbusy = 1;
01897          break;
01898       case OR2_CAUSE_NETWORK_CONGESTION:
01899       case OR2_CAUSE_OUT_OF_ORDER:
01900       case OR2_CAUSE_UNALLOCATED_NUMBER:
01901       case OR2_CAUSE_NO_ANSWER:
01902       case OR2_CAUSE_UNSPECIFIED:
01903       case OR2_CAUSE_NORMAL_CLEARING:
01904          p->subs[SUB_REAL].needcongestion = 1;
01905          break;
01906       default:
01907          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01908       }
01909       ast_mutex_unlock(&p->lock);
01910    } else {
01911       ast_mutex_unlock(&p->lock);
01912       /* being the backward side and not UP yet, we only need to request hangup */
01913       /* TODO: what about doing this same thing when were AST_STATE_UP? */
01914       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01915    }
01916 }
01917 
01918 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01919 {
01920    switch (level) {
01921    case OR2_LOG_NOTICE:
01922       ast_verbose("%s", logmessage);
01923       break;
01924    case OR2_LOG_WARNING:
01925       ast_log(LOG_WARNING, "%s", logmessage);
01926       break;
01927    case OR2_LOG_ERROR:
01928       ast_log(LOG_ERROR, "%s", logmessage);
01929       break;
01930    case OR2_LOG_STACK_TRACE:
01931    case OR2_LOG_MF_TRACE:
01932    case OR2_LOG_CAS_TRACE:
01933    case OR2_LOG_DEBUG:
01934    case OR2_LOG_EX_DEBUG:
01935       ast_log(LOG_DEBUG, "%s", logmessage);
01936       break;
01937    default:
01938       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01939       ast_log(LOG_DEBUG, "%s", logmessage);
01940       break;
01941    }
01942 }
01943 
01944 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01945 {
01946    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01947    ast_mutex_lock(&p->lock);
01948    p->remotelyblocked = 1;
01949    ast_mutex_unlock(&p->lock);
01950    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01951 }
01952 
01953 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01954 {
01955    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01956    ast_mutex_lock(&p->lock);
01957    p->remotelyblocked = 0;
01958    ast_mutex_unlock(&p->lock);
01959    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01960 }
01961 
01962 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01963    __attribute__((format (printf, 3, 0)));
01964 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01965 {
01966 #define CONTEXT_TAG "Context - "
01967    char logmsg[256];
01968    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
01969    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01970    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
01971    dahdi_r2_write_log(level, completemsg);
01972 #undef CONTEXT_TAG
01973 }
01974 
01975 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01976    __attribute__((format (printf, 3, 0)));
01977 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01978 {
01979 #define CHAN_TAG "Chan "
01980    char logmsg[256];
01981    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
01982    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01983    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
01984    dahdi_r2_write_log(level, completemsg);
01985 }
01986 
01987 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01988 {
01989    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01990    /* if 'immediate' is set, let's stop requesting DNIS */
01991    if (p->immediate) {
01992       return 0;
01993    }
01994    p->exten[p->mfcr2_dnis_index] = digit;
01995    p->rdnis[p->mfcr2_dnis_index] = digit;
01996    p->mfcr2_dnis_index++;
01997    p->exten[p->mfcr2_dnis_index] = 0;
01998    p->rdnis[p->mfcr2_dnis_index] = 0;
01999    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
02000    if ((p->mfcr2_dnis_matched ||
02001        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02002        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02003       return 0;
02004    }
02005    /* otherwise keep going */
02006    return 1;
02007 }
02008 
02009 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02010 {
02011    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02012    p->cid_num[p->mfcr2_ani_index] = digit;
02013    p->cid_name[p->mfcr2_ani_index] = digit;
02014    p->mfcr2_ani_index++;
02015    p->cid_num[p->mfcr2_ani_index] = 0;
02016    p->cid_name[p->mfcr2_ani_index] = 0;
02017 }
02018 
02019 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02020 {
02021    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02022 }
02023 
02024 static openr2_event_interface_t dahdi_r2_event_iface = {
02025    .on_call_init = dahdi_r2_on_call_init,
02026    .on_call_offered = dahdi_r2_on_call_offered,
02027    .on_call_accepted = dahdi_r2_on_call_accepted,
02028    .on_call_answered = dahdi_r2_on_call_answered,
02029    .on_call_disconnect = dahdi_r2_on_call_disconnect,
02030    .on_call_end = dahdi_r2_on_call_end,
02031    .on_call_read = dahdi_r2_on_call_read,
02032    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02033    .on_os_error = dahdi_r2_on_os_error,
02034    .on_protocol_error = dahdi_r2_on_protocol_error,
02035    .on_line_blocked = dahdi_r2_on_line_blocked,
02036    .on_line_idle = dahdi_r2_on_line_idle,
02037    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
02038    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02039    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02040    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02041    /* so far we do nothing with billing pulses */
02042    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02043 };
02044 
02045 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02046 {
02047    return AST_ALAW(sample);
02048 }
02049 
02050 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02051 {
02052    return AST_LIN2A(sample);
02053 }
02054 
02055 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02056    dahdi_r2_alaw_to_linear,
02057    dahdi_r2_linear_to_alaw
02058 };
02059 
02060 #endif /* HAVE_OPENR2 */
02061 
02062 static int restore_gains(struct dahdi_pvt *p);
02063 
02064 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02065 {
02066    int tchan;
02067    int tinthreeway;
02068    struct ast_channel *towner;
02069 
02070    ast_debug(1, "Swapping %d and %d\n", a, b);
02071 
02072    tchan = p->subs[a].chan;
02073    towner = p->subs[a].owner;
02074    tinthreeway = p->subs[a].inthreeway;
02075 
02076    p->subs[a].chan = p->subs[b].chan;
02077    p->subs[a].owner = p->subs[b].owner;
02078    p->subs[a].inthreeway = p->subs[b].inthreeway;
02079 
02080    p->subs[b].chan = tchan;
02081    p->subs[b].owner = towner;
02082    p->subs[b].inthreeway = tinthreeway;
02083 
02084    if (p->subs[a].owner)
02085       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02086    if (p->subs[b].owner)
02087       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02088    wakeup_sub(p, a, NULL);
02089    wakeup_sub(p, b, NULL);
02090 }
02091 
02092 static int dahdi_open(char *fn)
02093 {
02094    int fd;
02095    int isnum;
02096    int chan = 0;
02097    int bs;
02098    int x;
02099    isnum = 1;
02100    for (x = 0; x < strlen(fn); x++) {
02101       if (!isdigit(fn[x])) {
02102          isnum = 0;
02103          break;
02104       }
02105    }
02106    if (isnum) {
02107       chan = atoi(fn);
02108       if (chan < 1) {
02109          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02110          return -1;
02111       }
02112       fn = "/dev/dahdi/channel";
02113    }
02114    fd = open(fn, O_RDWR | O_NONBLOCK);
02115    if (fd < 0) {
02116       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02117       return -1;
02118    }
02119    if (chan) {
02120       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02121          x = errno;
02122          close(fd);
02123          errno = x;
02124          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02125          return -1;
02126       }
02127    }
02128    bs = READ_SIZE;
02129    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02130       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
02131       x = errno;
02132       close(fd);
02133       errno = x;
02134       return -1;
02135    }
02136    return fd;
02137 }
02138 
02139 static void dahdi_close(int fd)
02140 {
02141    if (fd > 0)
02142       close(fd);
02143 }
02144 
02145 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02146 {
02147    dahdi_close(chan_pvt->subs[sub_num].dfd);
02148    chan_pvt->subs[sub_num].dfd = -1;
02149 }
02150 
02151 #if defined(HAVE_PRI)
02152 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02153 {
02154    dahdi_close(pri->fds[fd_num]);
02155    pri->fds[fd_num] = -1;
02156 }
02157 #endif   /* defined(HAVE_PRI) */
02158 
02159 #if defined(HAVE_SS7)
02160 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02161 {
02162    dahdi_close(ss7->fds[fd_num]);
02163    ss7->fds[fd_num] = -1;
02164 }
02165 #endif   /* defined(HAVE_SS7) */
02166 
02167 static int dahdi_setlinear(int dfd, int linear)
02168 {
02169    int res;
02170    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02171    if (res)
02172       return res;
02173    return 0;
02174 }
02175 
02176 
02177 static int alloc_sub(struct dahdi_pvt *p, int x)
02178 {
02179    struct dahdi_bufferinfo bi;
02180    int res;
02181    if (p->subs[x].dfd >= 0) {
02182       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02183       return -1;
02184    }
02185 
02186    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02187    if (p->subs[x].dfd <= -1) {
02188       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02189       return -1;
02190    }
02191 
02192    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02193    if (!res) {
02194       bi.txbufpolicy = p->buf_policy;
02195       bi.rxbufpolicy = p->buf_policy;
02196       bi.numbufs = p->buf_no;
02197       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02198       if (res < 0) {
02199          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02200       }
02201    } else
02202       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02203 
02204    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02205       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02206       dahdi_close_sub(p, x);
02207       p->subs[x].dfd = -1;
02208       return -1;
02209    }
02210    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02211    return 0;
02212 }
02213 
02214 static int unalloc_sub(struct dahdi_pvt *p, int x)
02215 {
02216    if (!x) {
02217       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02218       return -1;
02219    }
02220    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02221    dahdi_close_sub(p, x);
02222    p->subs[x].linear = 0;
02223    p->subs[x].chan = 0;
02224    p->subs[x].owner = NULL;
02225    p->subs[x].inthreeway = 0;
02226    p->polarity = POLARITY_IDLE;
02227    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02228    return 0;
02229 }
02230 
02231 static int digit_to_dtmfindex(char digit)
02232 {
02233    if (isdigit(digit))
02234       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02235    else if (digit >= 'A' && digit <= 'D')
02236       return DAHDI_TONE_DTMF_A + (digit - 'A');
02237    else if (digit >= 'a' && digit <= 'd')
02238       return DAHDI_TONE_DTMF_A + (digit - 'a');
02239    else if (digit == '*')
02240       return DAHDI_TONE_DTMF_s;
02241    else if (digit == '#')
02242       return DAHDI_TONE_DTMF_p;
02243    else
02244       return -1;
02245 }
02246 
02247 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02248 {
02249    struct dahdi_pvt *pvt;
02250    int idx;
02251    int dtmf = -1;
02252 
02253    pvt = chan->tech_pvt;
02254 
02255    ast_mutex_lock(&pvt->lock);
02256 
02257    idx = dahdi_get_index(chan, pvt, 0);
02258 
02259    if ((idx != SUB_REAL) || !pvt->owner)
02260       goto out;
02261 
02262 #ifdef HAVE_PRI
02263    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02264          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
02265       if (pvt->setup_ack) {
02266          if (!pri_grab(pvt, pvt->pri)) {
02267             pri_information(pvt->pri->pri, pvt->call, digit);
02268             pri_rel(pvt->pri);
02269          } else
02270             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02271       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
02272          int res;
02273          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
02274          res = strlen(pvt->dialdest);
02275          pvt->dialdest[res++] = digit;
02276          pvt->dialdest[res] = '\0';
02277       }
02278       goto out;
02279    }
02280 #endif
02281    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02282       goto out;
02283 
02284    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02285       int res;
02286       struct dahdi_dialoperation zo = {
02287          .op = DAHDI_DIAL_OP_APPEND,
02288       };
02289 
02290       zo.dialstr[0] = 'T';
02291       zo.dialstr[1] = digit;
02292       zo.dialstr[2] = '\0';
02293       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02294          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02295       else
02296          pvt->dialing = 1;
02297    } else {
02298       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02299       pvt->dialing = 1;
02300       pvt->begindigit = digit;
02301    }
02302 
02303 out:
02304    ast_mutex_unlock(&pvt->lock);
02305 
02306    return 0;
02307 }
02308 
02309 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02310 {
02311    struct dahdi_pvt *pvt;
02312    int res = 0;
02313    int idx;
02314    int x;
02315 
02316    pvt = chan->tech_pvt;
02317 
02318    ast_mutex_lock(&pvt->lock);
02319 
02320    idx = dahdi_get_index(chan, pvt, 0);
02321 
02322    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02323       goto out;
02324 
02325 #ifdef HAVE_PRI
02326    /* This means that the digit was already sent via PRI signalling */
02327    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02328          && !pvt->begindigit)
02329       goto out;
02330 #endif
02331 
02332    if (pvt->begindigit) {
02333       x = -1;
02334       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02335       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02336       pvt->dialing = 0;
02337       pvt->begindigit = 0;
02338    }
02339 
02340 out:
02341    ast_mutex_unlock(&pvt->lock);
02342 
02343    return res;
02344 }
02345 
02346 static char *events[] = {
02347    "No event",
02348    "On hook",
02349    "Ring/Answered",
02350    "Wink/Flash",
02351    "Alarm",
02352    "No more alarm",
02353    "HDLC Abort",
02354    "HDLC Overrun",
02355    "HDLC Bad FCS",
02356    "Dial Complete",
02357    "Ringer On",
02358    "Ringer Off",
02359    "Hook Transition Complete",
02360    "Bits Changed",
02361    "Pulse Start",
02362    "Timer Expired",
02363    "Timer Ping",
02364    "Polarity Reversal",
02365    "Ring Begin",
02366 };
02367 
02368 static struct {
02369    int alarm;
02370    char *name;
02371 } alarms[] = {
02372    { DAHDI_ALARM_RED, "Red Alarm" },
02373    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02374    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02375    { DAHDI_ALARM_RECOVER, "Recovering" },
02376    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02377    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02378    { DAHDI_ALARM_NONE, "None" },
02379 };
02380 
02381 static char *alarm2str(int alm)
02382 {
02383    int x;
02384    for (x = 0; x < ARRAY_LEN(alarms); x++) {
02385       if (alarms[x].alarm & alm)
02386          return alarms[x].name;
02387    }
02388    return alm ? "Unknown Alarm" : "No Alarm";
02389 }
02390 
02391 static char *event2str(int event)
02392 {
02393    static char buf[256];
02394    if ((event < (ARRAY_LEN(events))) && (event > -1))
02395       return events[event];
02396    sprintf(buf, "Event %d", event); /* safe */
02397    return buf;
02398 }
02399 
02400 #ifdef HAVE_PRI
02401 static char *dialplan2str(int dialplan)
02402 {
02403    if (dialplan == -1 || dialplan == -2) {
02404       return("Dynamically set dialplan in ISDN");
02405    }
02406    return (pri_plan2str(dialplan));
02407 }
02408 #endif
02409 
02410 static char *dahdi_sig2str(int sig)
02411 {
02412    static char buf[256];
02413    switch (sig) {
02414    case SIG_EM:
02415       return "E & M Immediate";
02416    case SIG_EMWINK:
02417       return "E & M Wink";
02418    case SIG_EM_E1:
02419       return "E & M E1";
02420    case SIG_FEATD:
02421       return "Feature Group D (DTMF)";
02422    case SIG_FEATDMF:
02423       return "Feature Group D (MF)";
02424    case SIG_FEATDMF_TA:
02425       return "Feature Groud D (MF) Tandem Access";
02426    case SIG_FEATB:
02427       return "Feature Group B (MF)";
02428    case SIG_E911:
02429       return "E911 (MF)";
02430    case SIG_FGC_CAMA:
02431       return "FGC/CAMA (Dialpulse)";
02432    case SIG_FGC_CAMAMF:
02433       return "FGC/CAMA (MF)";
02434    case SIG_FXSLS:
02435       return "FXS Loopstart";
02436    case SIG_FXSGS:
02437       return "FXS Groundstart";
02438    case SIG_FXSKS:
02439       return "FXS Kewlstart";
02440    case SIG_FXOLS:
02441       return "FXO Loopstart";
02442    case SIG_FXOGS:
02443       return "FXO Groundstart";
02444    case SIG_FXOKS:
02445       return "FXO Kewlstart";
02446    case SIG_PRI:
02447       return "ISDN PRI";
02448    case SIG_BRI:
02449       return "ISDN BRI Point to Point";
02450    case SIG_BRI_PTMP:
02451       return "ISDN BRI Point to MultiPoint";
02452    case SIG_SS7:
02453       return "SS7";
02454    case SIG_MFCR2:
02455       return "MFC/R2";
02456    case SIG_SF:
02457       return "SF (Tone) Immediate";
02458    case SIG_SFWINK:
02459       return "SF (Tone) Wink";
02460    case SIG_SF_FEATD:
02461       return "SF (Tone) with Feature Group D (DTMF)";
02462    case SIG_SF_FEATDMF:
02463       return "SF (Tone) with Feature Group D (MF)";
02464    case SIG_SF_FEATB:
02465       return "SF (Tone) with Feature Group B (MF)";
02466    case SIG_GR303FXOKS:
02467       return "GR-303 with FXOKS";
02468    case SIG_GR303FXSKS:
02469       return "GR-303 with FXSKS";
02470    case 0:
02471       return "Pseudo";
02472    default:
02473       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02474       return buf;
02475    }
02476 }
02477 
02478 #define sig2str dahdi_sig2str
02479 
02480 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02481 {
02482    /* If the conference already exists, and we're already in it
02483       don't bother doing anything */
02484    struct dahdi_confinfo zi;
02485 
02486    memset(&zi, 0, sizeof(zi));
02487    zi.chan = 0;
02488 
02489    if (slavechannel > 0) {
02490       /* If we have only one slave, do a digital mon */
02491       zi.confmode = DAHDI_CONF_DIGITALMON;
02492       zi.confno = slavechannel;
02493    } else {
02494       if (!idx) {
02495          /* Real-side and pseudo-side both participate in conference */
02496          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02497             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02498       } else
02499          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02500       zi.confno = p->confno;
02501    }
02502    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02503       return 0;
02504    if (c->dfd < 0)
02505       return 0;
02506    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02507       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02508       return -1;
02509    }
02510    if (slavechannel < 1) {
02511       p->confno = zi.confno;
02512    }
02513    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02514    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02515    return 0;
02516 }
02517 
02518 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02519 {
02520    /* If they're listening to our channel, they're ours */
02521    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02522       return 1;
02523    /* If they're a talker on our (allocated) conference, they're ours */
02524    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02525       return 1;
02526    return 0;
02527 }
02528 
02529 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02530 {
02531    struct dahdi_confinfo zi;
02532    if (/* Can't delete if there's no dfd */
02533       (c->dfd < 0) ||
02534       /* Don't delete from the conference if it's not our conference */
02535       !isourconf(p, c)
02536       /* Don't delete if we don't think it's conferenced at all (implied) */
02537       ) return 0;
02538    memset(&zi, 0, sizeof(zi));
02539    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02540       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02541       return -1;
02542    }
02543    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02544    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02545    return 0;
02546 }
02547 
02548 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02549 {
02550    int x;
02551    int useslavenative;
02552    struct dahdi_pvt *slave = NULL;
02553    /* Start out optimistic */
02554    useslavenative = 1;
02555    /* Update conference state in a stateless fashion */
02556    for (x = 0; x < 3; x++) {
02557       /* Any three-way calling makes slave native mode *definitely* out
02558          of the question */
02559       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02560          useslavenative = 0;
02561    }
02562    /* If we don't have any 3-way calls, check to see if we have
02563       precisely one slave */
02564    if (useslavenative) {
02565       for (x = 0; x < MAX_SLAVES; x++) {
02566          if (p->slaves[x]) {
02567             if (slave) {
02568                /* Whoops already have a slave!  No
02569                   slave native and stop right away */
02570                slave = NULL;
02571                useslavenative = 0;
02572                break;
02573             } else {
02574                /* We have one slave so far */
02575                slave = p->slaves[x];
02576             }
02577          }
02578       }
02579    }
02580    /* If no slave, slave native definitely out */
02581    if (!slave)
02582       useslavenative = 0;
02583    else if (slave->law != p->law) {
02584       useslavenative = 0;
02585       slave = NULL;
02586    }
02587    if (out)
02588       *out = slave;
02589    return useslavenative;
02590 }
02591 
02592 static int reset_conf(struct dahdi_pvt *p)
02593 {
02594    p->confno = -1;
02595    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02596    if (p->subs[SUB_REAL].dfd > -1) {
02597       struct dahdi_confinfo zi;
02598 
02599       memset(&zi, 0, sizeof(zi));
02600       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02601          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02602    }
02603    return 0;
02604 }
02605 
02606 static int update_conf(struct dahdi_pvt *p)
02607 {
02608    int needconf = 0;
02609    int x;
02610    int useslavenative;
02611    struct dahdi_pvt *slave = NULL;
02612 
02613    useslavenative = isslavenative(p, &slave);
02614    /* Start with the obvious, general stuff */
02615    for (x = 0; x < 3; x++) {
02616       /* Look for three way calls */
02617       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02618          conf_add(p, &p->subs[x], x, 0);
02619          needconf++;
02620       } else {
02621          conf_del(p, &p->subs[x], x);
02622       }
02623    }
02624    /* If we have a slave, add him to our conference now. or DAX
02625       if this is slave native */
02626    for (x = 0; x < MAX_SLAVES; x++) {
02627       if (p->slaves[x]) {
02628          if (useslavenative)
02629             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02630          else {
02631             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02632             needconf++;
02633          }
02634       }
02635    }
02636    /* If we're supposed to be in there, do so now */
02637    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02638       if (useslavenative)
02639          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02640       else {
02641          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02642          needconf++;
02643       }
02644    }
02645    /* If we have a master, add ourselves to his conference */
02646    if (p->master) {
02647       if (isslavenative(p->master, NULL)) {
02648          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02649       } else {
02650          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02651       }
02652    }
02653    if (!needconf) {
02654       /* Nobody is left (or should be left) in our conference.
02655          Kill it. */
02656       p->confno = -1;
02657    }
02658    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02659    return 0;
02660 }
02661 
02662 static void dahdi_enable_ec(struct dahdi_pvt *p)
02663 {
02664    int x;
02665    int res;
02666    if (!p)
02667       return;
02668    if (p->echocanon) {
02669       ast_debug(1, "Echo cancellation already on\n");
02670       return;
02671    }
02672    if (p->digital) {
02673       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02674       return;
02675    }
02676    if (p->echocancel.head.tap_length) {
02677       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02678          x = 1;
02679          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02680          if (res)
02681             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02682       }
02683       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02684       if (res) {
02685          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02686       } else {
02687          p->echocanon = 1;
02688          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02689       }
02690    } else
02691       ast_debug(1, "No echo cancellation requested\n");
02692 }
02693 
02694 static void dahdi_train_ec(struct dahdi_pvt *p)
02695 {
02696    int x;
02697    int res;
02698 
02699    if (p && p->echocanon && p->echotraining) {
02700       x = p->echotraining;
02701       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02702       if (res)
02703          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02704       else
02705          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02706    } else {
02707       ast_debug(1, "No echo training requested\n");
02708    }
02709 }
02710 
02711 static void dahdi_disable_ec(struct dahdi_pvt *p)
02712 {
02713    int res;
02714 
02715    if (p->echocanon) {
02716       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02717 
02718       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02719 
02720       if (res)
02721          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02722       else
02723          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02724    }
02725 
02726    p->echocanon = 0;
02727 }
02728 
02729 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02730 {
02731    int j;
02732    int k;
02733    float linear_gain = pow(10.0, gain / 20.0);
02734 
02735    switch (law) {
02736    case DAHDI_LAW_ALAW:
02737       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02738          if (gain) {
02739             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02740             if (k > 32767) k = 32767;
02741             if (k < -32767) k = -32767;
02742             g->txgain[j] = AST_LIN2A(k);
02743          } else {
02744             g->txgain[j] = j;
02745          }
02746       }
02747       break;
02748    case DAHDI_LAW_MULAW:
02749       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02750          if (gain) {
02751             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02752             if (k > 32767) k = 32767;
02753             if (k < -32767) k = -32767;
02754             g->txgain[j] = AST_LIN2MU(k);
02755          } else {
02756             g->txgain[j] = j;
02757          }
02758       }
02759       break;
02760    }
02761 }
02762 
02763 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02764 {
02765    int j;
02766    int k;
02767    float linear_gain = pow(10.0, gain / 20.0);
02768 
02769    switch (law) {
02770    case DAHDI_LAW_ALAW:
02771       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02772          if (gain) {
02773             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02774             if (k > 32767) k = 32767;
02775             if (k < -32767) k = -32767;
02776             g->rxgain[j] = AST_LIN2A(k);
02777          } else {
02778             g->rxgain[j] = j;
02779          }
02780       }
02781       break;
02782    case DAHDI_LAW_MULAW:
02783       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02784          if (gain) {
02785             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02786             if (k > 32767) k = 32767;
02787             if (k < -32767) k = -32767;
02788             g->rxgain[j] = AST_LIN2MU(k);
02789          } else {
02790             g->rxgain[j] = j;
02791          }
02792       }
02793       break;
02794    }
02795 }
02796 
02797 static int set_actual_txgain(int fd, int chan, float gain, int law)
02798 {
02799    struct dahdi_gains g;
02800    int res;
02801 
02802    memset(&g, 0, sizeof(g));
02803    g.chan = chan;
02804    res = ioctl(fd, DAHDI_GETGAINS, &g);
02805    if (res) {
02806       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02807       return res;
02808    }
02809 
02810    fill_txgain(&g, gain, law);
02811 
02812    return ioctl(fd, DAHDI_SETGAINS, &g);
02813 }
02814 
02815 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02816 {
02817    struct dahdi_gains g;
02818    int res;
02819 
02820    memset(&g, 0, sizeof(g));
02821    g.chan = chan;
02822    res = ioctl(fd, DAHDI_GETGAINS, &g);
02823    if (res) {
02824       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02825       return res;
02826    }
02827 
02828    fill_rxgain(&g, gain, law);
02829 
02830    return ioctl(fd, DAHDI_SETGAINS, &g);
02831 }
02832 
02833 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02834 {
02835    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02836 }
02837 
02838 static int bump_gains(struct dahdi_pvt *p)
02839 {
02840    int res;
02841 
02842    /* Bump receive gain by value stored in cid_rxgain */
02843    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02844    if (res) {
02845       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02846       return -1;
02847    }
02848 
02849    return 0;
02850 }
02851 
02852 static int restore_gains(struct dahdi_pvt *p)
02853 {
02854    int res;
02855 
02856    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02857    if (res) {
02858       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02859       return -1;
02860    }
02861 
02862    return 0;
02863 }
02864 
02865 static inline int dahdi_set_hook(int fd, int hs)
02866 {
02867    int x, res;
02868 
02869    x = hs;
02870    res = ioctl(fd, DAHDI_HOOK, &x);
02871 
02872    if (res < 0) {
02873       if (errno == EINPROGRESS)
02874          return 0;
02875       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02876       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02877    }
02878 
02879    return res;
02880 }
02881 
02882 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02883 {
02884    int x, y, res;
02885    x = muted;
02886    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02887       y = 1;
02888       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02889       if (res)
02890          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02891    }
02892    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02893    if (res < 0)
02894       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02895    return res;
02896 }
02897 
02898 static int save_conference(struct dahdi_pvt *p)
02899 {
02900    struct dahdi_confinfo c;
02901    int res;
02902    if (p->saveconf.confmode) {
02903       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02904       return -1;
02905    }
02906    p->saveconf.chan = 0;
02907    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02908    if (res) {
02909       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02910       p->saveconf.confmode = 0;
02911       return -1;
02912    }
02913    memset(&c, 0, sizeof(c));
02914    c.confmode = DAHDI_CONF_NORMAL;
02915    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02916    if (res) {
02917       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02918       return -1;
02919    }
02920    ast_debug(1, "Disabled conferencing\n");
02921    return 0;
02922 }
02923 
02924 /*!
02925  * \brief Send MWI state change
02926  *
02927  * \arg mailbox_full This is the mailbox associated with the FXO line that the
02928  *      MWI state has changed on.
02929  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
02930  *      whether there are messages waiting or not.
02931  *
02932  *  \return nothing
02933  *
02934  * This function does two things:
02935  *
02936  * 1) It generates an internal Asterisk event notifying any other module that
02937  *    cares about MWI that the state of a mailbox has changed.
02938  *
02939  * 2) It runs the script specified by the mwimonitornotify option to allow
02940  *    some custom handling of the state change.
02941  */
02942 static void notify_message(char *mailbox_full, int thereornot)
02943 {
02944    char s[sizeof(mwimonitornotify) + 80];
02945    struct ast_event *event;
02946    char *mailbox, *context;
02947 
02948    /* Strip off @default */
02949    context = mailbox = ast_strdupa(mailbox_full);
02950    strsep(&context, "@");
02951    if (ast_strlen_zero(context))
02952       context = "default";
02953 
02954    if (!(event = ast_event_new(AST_EVENT_MWI,
02955          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02956          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02957          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02958          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02959          AST_EVENT_IE_END))) {
02960       return;
02961    }
02962 
02963    ast_event_queue_and_cache(event);
02964 
02965    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02966       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02967       ast_safe_system(s);
02968    }
02969 }
02970 
02971 static int restore_conference(struct dahdi_pvt *p)
02972 {
02973    int res;
02974    if (p->saveconf.confmode) {
02975       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02976       p->saveconf.confmode = 0;
02977       if (res) {
02978          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02979          return -1;
02980       }
02981    }
02982    ast_debug(1, "Restored conferencing\n");
02983    return 0;
02984 }
02985 
02986 static int send_callerid(struct dahdi_pvt *p);
02987 
02988 static int send_cwcidspill(struct dahdi_pvt *p)
02989 {
02990    p->callwaitcas = 0;
02991    p->cidcwexpire = 0;
02992    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02993       return -1;
02994    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02995    /* Make sure we account for the end */
02996    p->cidlen += READ_SIZE * 4;
02997    p->cidpos = 0;
02998    send_callerid(p);
02999    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03000    return 0;
03001 }
03002 
03003 static int has_voicemail(struct dahdi_pvt *p)
03004 {
03005    int new_msgs;
03006    struct ast_event *event;
03007    char *mailbox, *context;
03008 
03009    mailbox = context = ast_strdupa(p->mailbox);
03010    strsep(&context, "@");
03011    if (ast_strlen_zero(context))
03012       context = "default";
03013 
03014    event = ast_event_get_cached(AST_EVENT_MWI,
03015       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03016       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03017       AST_EVENT_IE_END);
03018 
03019    if (event) {
03020       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03021       ast_event_destroy(event);
03022    } else
03023       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03024 
03025    return new_msgs;
03026 }
03027 
03028 static int send_callerid(struct dahdi_pvt *p)
03029 {
03030    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
03031    int res;
03032    /* Take out of linear mode if necessary */
03033    if (p->subs[SUB_REAL].linear) {
03034       p->subs[SUB_REAL].linear = 0;
03035       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03036    }
03037    while (p->cidpos < p->cidlen) {
03038       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03039       if (res < 0) {
03040          if (errno == EAGAIN)
03041             return 0;
03042          else {
03043             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03044             return -1;
03045          }
03046       }
03047       if (!res)
03048          return 0;
03049       p->cidpos += res;
03050    }
03051    ast_free(p->cidspill);
03052    p->cidspill = NULL;
03053    if (p->callwaitcas) {
03054       /* Wait for CID/CW to expire */
03055       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03056    } else
03057       restore_conference(p);
03058    return 0;
03059 }
03060 
03061 static int dahdi_callwait(struct ast_channel *ast)
03062 {
03063    struct dahdi_pvt *p = ast->tech_pvt;
03064    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03065    if (p->cidspill) {
03066       ast_log(LOG_WARNING, "Spill already exists?!?\n");
03067       ast_free(p->cidspill);
03068    }
03069    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
03070       return -1;
03071    save_conference(p);
03072    /* Silence */
03073    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03074    if (!p->callwaitrings && p->callwaitingcallerid) {
03075       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03076       p->callwaitcas = 1;
03077       p->cidlen = 2400 + 680 + READ_SIZE * 4;
03078    } else {
03079       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03080       p->callwaitcas = 0;
03081       p->cidlen = 2400 + READ_SIZE * 4;
03082    }
03083    p->cidpos = 0;
03084    send_callerid(p);
03085 
03086    return 0;
03087 }
03088 
03089 #if defined(HAVE_SS7)
03090 static unsigned char cid_pres2ss7pres(int cid_pres)
03091 {
03092     return (cid_pres >> 5) & 0x03;
03093 }
03094 #endif   /* defined(HAVE_SS7) */
03095 
03096 #if defined(HAVE_SS7)
03097 static unsigned char cid_pres2ss7screen(int cid_pres)
03098 {
03099    return cid_pres & 0x03;
03100 }
03101 #endif   /* defined(HAVE_SS7) */
03102 
03103 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03104 {
03105    struct dahdi_pvt *p = ast->tech_pvt;
03106    int x, res, idx,mysig;
03107    char *c, *n, *l;
03108 #ifdef HAVE_PRI
03109    char *s = NULL;
03110 #endif
03111    char dest[256]; /* must be same length as p->dialdest */
03112    ast_mutex_lock(&p->lock);
03113    ast_copy_string(dest, rdest, sizeof(dest));
03114    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03115    if ((ast->_state == AST_STATE_BUSY)) {
03116       p->subs[SUB_REAL].needbusy = 1;
03117       ast_mutex_unlock(&p->lock);
03118       return 0;
03119    }
03120    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03121       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03122       ast_mutex_unlock(&p->lock);
03123       return -1;
03124    }
03125    p->waitingfordt.tv_sec = 0;
03126    p->dialednone = 0;
03127    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
03128    {
03129       /* Special pseudo -- automatically up */
03130       ast_setstate(ast, AST_STATE_UP);
03131       ast_mutex_unlock(&p->lock);
03132       return 0;
03133    }
03134    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03135    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03136    if (res)
03137       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03138    p->outgoing = 1;
03139 
03140    if (IS_DIGITAL(ast->transfercapability)){
03141       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03142    } else {
03143       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03144    }  
03145 
03146    mysig = p->sig;
03147    if (p->outsigmod > -1)
03148       mysig = p->outsigmod;
03149 
03150    switch (mysig) {
03151    case SIG_FXOLS:
03152    case SIG_FXOGS:
03153    case SIG_FXOKS:
03154       if (p->owner == ast) {
03155          /* Normal ring, on hook */
03156 
03157          /* Don't send audio while on hook, until the call is answered */
03158          p->dialing = 1;
03159          if (p->use_callerid) {
03160             /* Generate the Caller-ID spill if desired */
03161             if (p->cidspill) {
03162                ast_log(LOG_WARNING, "cidspill already exists??\n");
03163                ast_free(p->cidspill);
03164             }
03165             p->callwaitcas = 0;
03166             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03167                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03168                p->cidpos = 0;
03169                send_callerid(p);
03170             }
03171          }
03172          /* Choose proper cadence */
03173          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03174             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03175                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03176             p->cidrings = cidrings[p->distinctivering - 1];
03177          } else {
03178             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03179                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03180             p->cidrings = p->sendcalleridafter;
03181          }
03182 
03183          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
03184          c = strchr(dest, '/');
03185          if (c)
03186             c++;
03187          if (c && (strlen(c) < p->stripmsd)) {
03188             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03189             c = NULL;
03190          }
03191          if (c) {
03192             p->dop.op = DAHDI_DIAL_OP_REPLACE;
03193             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03194             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03195          } else {
03196             p->dop.dialstr[0] = '\0';
03197          }
03198          x = DAHDI_RING;
03199          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03200             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03201             ast_mutex_unlock(&p->lock);
03202             return -1;
03203          }
03204          p->dialing = 1;
03205       } else {
03206          /* Call waiting call */
03207          p->callwaitrings = 0;
03208          if (ast->cid.cid_num)
03209             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03210          else
03211             p->callwait_num[0] = '\0';
03212          if (ast->cid.cid_name)
03213             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03214          else
03215             p->callwait_name[0] = '\0';
03216          /* Call waiting tone instead */
03217          if (dahdi_callwait(ast)) {
03218             ast_mutex_unlock(&p->lock);
03219             return -1;
03220          }
03221          /* Make ring-back */
03222          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03223             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03224       }
03225       n = ast->cid.cid_name;
03226       l = ast->cid.cid_num;
03227       if (l)
03228          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03229       else
03230          p->lastcid_num[0] = '\0';
03231       if (n)
03232          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03233       else
03234          p->lastcid_name[0] = '\0';
03235       ast_setstate(ast, AST_STATE_RINGING);
03236       idx = dahdi_get_index(ast, p, 0);
03237       if (idx > -1) {
03238          p->subs[idx].needringing = 1;
03239       }
03240       break;
03241    case SIG_FXSLS:
03242    case SIG_FXSGS:
03243    case SIG_FXSKS:
03244       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03245          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03246          p->polaritydelaytv = ast_tvnow();
03247       }
03248       /* fall through */
03249    case SIG_EMWINK:
03250    case SIG_EM:
03251    case SIG_EM_E1:
03252    case SIG_FEATD:
03253    case SIG_FEATDMF:
03254    case SIG_E911:
03255    case SIG_FGC_CAMA:
03256    case SIG_FGC_CAMAMF:
03257    case SIG_FEATB:
03258    case SIG_SFWINK:
03259    case SIG_SF:
03260    case SIG_SF_FEATD:
03261    case SIG_SF_FEATDMF:
03262    case SIG_FEATDMF_TA:
03263    case SIG_SF_FEATB:
03264       c = strchr(dest, '/');
03265       if (c)
03266          c++;
03267       else
03268          c = "";
03269       if (strlen(c) < p->stripmsd) {
03270          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03271          ast_mutex_unlock(&p->lock);
03272          return -1;
03273       }
03274 #ifdef HAVE_PRI
03275       /* Start the trunk, if not GR-303 */
03276       if (!p->pri) {
03277 #endif
03278          x = DAHDI_START;
03279          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03280          if (res < 0) {
03281             if (errno != EINPROGRESS) {
03282                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03283                ast_mutex_unlock(&p->lock);
03284                return -1;
03285             }
03286          }
03287 #ifdef HAVE_PRI
03288       }
03289 #endif
03290       ast_debug(1, "Dialing '%s'\n", c);
03291       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03292 
03293       c += p->stripmsd;
03294 
03295       switch (mysig) {
03296       case SIG_FEATD:
03297          l = ast->cid.cid_num;
03298          if (l)
03299             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03300          else
03301             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03302          break;
03303       case SIG_FEATDMF:
03304          l = ast->cid.cid_num;
03305          if (l)
03306             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03307          else
03308             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03309          break;
03310       case SIG_FEATDMF_TA:
03311       {
03312          const char *cic, *ozz;
03313 
03314          /* If you have to go through a Tandem Access point you need to use this */
03315          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03316          if (!ozz)
03317             ozz = defaultozz;
03318          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03319          if (!cic)
03320             cic = defaultcic;
03321          if (!ozz || !cic) {
03322             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03323             ast_mutex_unlock(&p->lock);
03324             return -1;
03325          }
03326          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03327          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03328          p->whichwink = 0;
03329       }
03330          break;
03331       case SIG_E911:
03332          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03333          break;
03334       case SIG_FGC_CAMA:
03335          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03336          break;
03337       case SIG_FGC_CAMAMF:
03338       case SIG_FEATB:
03339          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03340          break;
03341       default:
03342          if (p->pulse)
03343             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03344          else
03345             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03346          break;
03347       }
03348 
03349       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03350          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03351          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03352          p->echorest[sizeof(p->echorest) - 1] = '\0';
03353          p->echobreak = 1;
03354          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03355       } else
03356          p->echobreak = 0;
03357 
03358       /* waitfordialtone ? */
03359 #ifdef HAVE_PRI
03360       if (!p->pri) {
03361 #endif
03362          if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03363             ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03364             gettimeofday(&p->waitingfordt,NULL);
03365             ast_setstate(ast, AST_STATE_OFFHOOK);
03366             break;
03367          }
03368 #ifdef HAVE_PRI
03369       }
03370 #endif
03371       if (!res) {
03372          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03373             int saveerr = errno;
03374 
03375             x = DAHDI_ONHOOK;
03376             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03377             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03378             ast_mutex_unlock(&p->lock);
03379             return -1;
03380          }
03381       } else
03382          ast_debug(1, "Deferring dialing...\n");
03383 
03384       p->dialing = 1;
03385       if (ast_strlen_zero(c))
03386          p->dialednone = 1;
03387       ast_setstate(ast, AST_STATE_DIALING);
03388       break;
03389    case 0:
03390       /* Special pseudo -- automatically up*/
03391       ast_setstate(ast, AST_STATE_UP);
03392       break;
03393    case SIG_PRI:
03394    case SIG_BRI:
03395    case SIG_BRI_PTMP:
03396    case SIG_SS7:
03397    case SIG_MFCR2:
03398       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03399       p->dialdest[0] = '\0';
03400       p->dialing = 1;
03401       break;
03402    default:
03403       ast_debug(1, "not yet implemented\n");
03404       ast_mutex_unlock(&p->lock);
03405       return -1;
03406    }
03407 #ifdef HAVE_SS7
03408    if (p->ss7) {
03409       char ss7_called_nai;
03410       int called_nai_strip;
03411       char ss7_calling_nai;
03412       int calling_nai_strip;
03413       const char *charge_str = NULL;
03414       const char *gen_address = NULL;
03415       const char *gen_digits = NULL;
03416       const char *gen_dig_type = NULL;
03417       const char *gen_dig_scheme = NULL;
03418       const char *gen_name = NULL;
03419       const char *jip_digits = NULL;
03420       const char *lspi_ident = NULL;
03421       const char *rlt_flag = NULL;
03422       const char *call_ref_id = NULL;
03423       const char *call_ref_pc = NULL;
03424       const char *send_far = NULL;
03425 
03426       c = strchr(dest, '/');
03427       if (c) {
03428          c++;
03429       } else {
03430          c = "";
03431       }
03432       if (strlen(c) < p->stripmsd) {
03433          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03434          ast_mutex_unlock(&p->lock);
03435          return -1;
03436       }
03437 
03438       if (!p->hidecallerid) {
03439          l = ast->cid.cid_num;
03440       } else {
03441          l = NULL;
03442       }
03443 
03444       if (ss7_grab(p, p->ss7)) {
03445          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03446          ast_mutex_unlock(&p->lock);
03447          return -1;
03448       }
03449       p->digital = IS_DIGITAL(ast->transfercapability);
03450       p->ss7call = isup_new_call(p->ss7->ss7);
03451 
03452       if (!p->ss7call) {
03453          ss7_rel(p->ss7);
03454          ast_mutex_unlock(&p->lock);
03455          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03456          return -1;
03457       }
03458 
03459       called_nai_strip = 0;
03460       ss7_called_nai = p->ss7->called_nai;
03461       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
03462          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03463             called_nai_strip = strlen(p->ss7->internationalprefix);
03464             ss7_called_nai = SS7_NAI_INTERNATIONAL;
03465          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03466             called_nai_strip = strlen(p->ss7->nationalprefix);
03467             ss7_called_nai = SS7_NAI_NATIONAL;
03468          } else {
03469             ss7_called_nai = SS7_NAI_SUBSCRIBER;
03470          }
03471       }
03472       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03473 
03474       calling_nai_strip = 0;
03475       ss7_calling_nai = p->ss7->calling_nai;
03476       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
03477          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03478             calling_nai_strip = strlen(p->ss7->internationalprefix);
03479             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03480          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03481             calling_nai_strip = strlen(p->ss7->nationalprefix);
03482             ss7_calling_nai = SS7_NAI_NATIONAL;
03483          } else {
03484             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03485          }
03486       }
03487       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03488          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03489          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03490 
03491       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03492       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03493 
03494       ast_channel_lock(ast);
03495       /* Set the charge number if it is set */
03496       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03497       if (charge_str)
03498          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03499 
03500       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03501       if (gen_address)
03502          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 */
03503 
03504       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03505       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03506       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03507       if (gen_digits)
03508          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03509 
03510       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03511       if (gen_name)
03512          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03513 
03514       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03515       if (jip_digits)
03516          isup_set_jip_digits(p->ss7call, jip_digits);
03517 
03518       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03519       if (lspi_ident)
03520          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03521 
03522       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03523       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03524          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
03525       }
03526 
03527       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03528       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03529       if (call_ref_id && call_ref_pc) {
03530          isup_set_callref(p->ss7call, atoi(call_ref_id),
03531                 call_ref_pc ? atoi(call_ref_pc) : 0);
03532       }
03533 
03534       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03535       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03536          (isup_far(p->ss7->ss7, p->ss7call));
03537 
03538       ast_channel_unlock(ast);
03539 
03540       isup_iam(p->ss7->ss7, p->ss7call);
03541       ast_setstate(ast, AST_STATE_DIALING);
03542       ss7_rel(p->ss7);
03543    }
03544 #endif /* HAVE_SS7 */
03545 #ifdef HAVE_OPENR2
03546    if (p->mfcr2) {
03547       openr2_calling_party_category_t chancat;
03548       int callres = 0;
03549       char *c, *l;
03550 
03551       c = strchr(dest, '/');
03552       if (c) {
03553          c++;
03554       } else {
03555          c = "";
03556       }
03557       if (!p->hidecallerid) {
03558          l = ast->cid.cid_num;
03559       } else {
03560          l = NULL;
03561       }
03562       if (strlen(c) < p->stripmsd) {
03563          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03564          ast_mutex_unlock(&p->lock);
03565          return -1;
03566       }
03567       p->dialing = 1;
03568       ast_channel_lock(ast);
03569       chancat = dahdi_r2_get_channel_category(ast);
03570       ast_channel_unlock(ast);
03571       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03572       if (-1 == callres) {
03573          ast_mutex_unlock(&p->lock);
03574          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03575          return -1;
03576       }
03577       ast_setstate(ast, AST_STATE_DIALING);
03578    }
03579 #endif /* HAVE_OPENR2 */
03580 #ifdef HAVE_PRI
03581    if (p->pri) {
03582       struct pri_sr *sr;
03583 #ifdef SUPPORT_USERUSER
03584       const char *useruser;
03585 #endif
03586       int pridialplan;
03587       int dp_strip;
03588       int prilocaldialplan;
03589       int ldp_strip;
03590       int exclusive;
03591       const char *rr_str;
03592       int redirect_reason;
03593 
03594       c = strchr(dest, '/');
03595       if (c) {
03596          c++;
03597       } else {
03598          c = "";
03599       }
03600 
03601       l = NULL;
03602       n = NULL;
03603       if (!p->hidecallerid) {
03604          /* If we get to the end of this loop without breaking, there's no
03605           * numeric calleridnum. This is done instead of testing for
03606           * "unknown" or the thousands of other ways that the calleridnum
03607           * could be invalid. */
03608          for (l = ast->cid.cid_num; l && *l; l++) {
03609             if (strchr("0123456789", *l)) {
03610                l = ast->cid.cid_num;
03611                break;
03612             }
03613          }
03614          if (!p->hidecalleridname) {
03615             n = ast->cid.cid_name;
03616          }
03617       }
03618 
03619       if (strlen(c) < p->stripmsd) {
03620          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03621          ast_mutex_unlock(&p->lock);
03622          return -1;
03623       }
03624       if (mysig != SIG_FXSKS) {
03625          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03626          s = strchr(c + p->stripmsd, 'w');
03627          if (s) {
03628             if (strlen(s) > 1)
03629                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03630             else
03631                p->dop.dialstr[0] = '\0';
03632             *s = '\0';
03633          } else {
03634             p->dop.dialstr[0] = '\0';
03635          }
03636       }
03637       if (pri_grab(p, p->pri)) {
03638          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03639          ast_mutex_unlock(&p->lock);
03640          return -1;
03641       }
03642       if (!(p->call = pri_new_call(p->pri->pri))) {
03643          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03644          pri_rel(p->pri);
03645          ast_mutex_unlock(&p->lock);
03646          return -1;
03647       }
03648       if (!(sr = pri_sr_new())) {
03649          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03650          pri_rel(p->pri);
03651          ast_mutex_unlock(&p->lock);
03652       }
03653       if (p->bearer || (mysig == SIG_FXSKS)) {
03654          if (p->bearer) {
03655             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03656             p->bearer->call = p->call;
03657          } else
03658             ast_debug(1, "I'm being setup with no bearer right now...\n");
03659 
03660          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03661       }
03662       p->digital = IS_DIGITAL(ast->transfercapability);
03663 
03664       /* Should the picked channel be used exclusively? */
03665       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03666          exclusive = 1;
03667       } else {
03668          exclusive = 0;
03669       }
03670 
03671       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03672       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03673          (p->digital ? -1 :
03674             ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03675       if (p->pri->facilityenable)
03676          pri_facility_enable(p->pri->pri);
03677 
03678       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03679 
03680       dp_strip = 0;
03681       pridialplan = p->pri->dialplan - 1;
03682       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
03683          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03684             if (pridialplan == -2) {
03685                dp_strip = strlen(p->pri->internationalprefix);
03686             }
03687             pridialplan = PRI_INTERNATIONAL_ISDN;
03688          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03689             if (pridialplan == -2) {
03690                dp_strip = strlen(p->pri->nationalprefix);
03691             }
03692             pridialplan = PRI_NATIONAL_ISDN;
03693          } else {
03694             pridialplan = PRI_LOCAL_ISDN;
03695          }
03696       }
03697       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03698          switch (c[p->stripmsd]) {
03699          case 'U':
03700             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03701             break;
03702          case 'I':
03703             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03704             break;
03705          case 'N':
03706             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03707             break;
03708          case 'L':
03709             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03710             break;
03711          case 'S':
03712             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03713             break;
03714          case 'V':
03715             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03716             break;
03717          case 'R':
03718             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03719             break;
03720          case 'u':
03721             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03722             break;
03723          case 'e':
03724             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03725             break;
03726          case 'x':
03727             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03728             break;
03729          case 'f':
03730             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03731             break;
03732          case 'n':
03733             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03734             break;
03735          case 'p':
03736             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03737             break;
03738          case 'r':
03739             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03740             break;
03741          default:
03742             if (isalpha(c[p->stripmsd])) {
03743                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03744                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03745             }
03746             break;
03747          }
03748          c++;
03749       }
03750       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03751 
03752       ldp_strip = 0;
03753       prilocaldialplan = p->pri->localdialplan - 1;
03754       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03755          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03756             if (prilocaldialplan == -2) {
03757                ldp_strip = strlen(p->pri->internationalprefix);
03758             }
03759             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03760          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03761             if (prilocaldialplan == -2) {
03762                ldp_strip = strlen(p->pri->nationalprefix);
03763             }
03764             prilocaldialplan = PRI_NATIONAL_ISDN;
03765          } else {
03766             prilocaldialplan = PRI_LOCAL_ISDN;
03767          }
03768       }
03769       if (l != NULL) {
03770          while (*l > '9' && *l != '*' && *l != '#') {
03771             switch (*l) {
03772             case 'U':
03773                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03774                break;
03775             case 'I':
03776                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03777                break;
03778             case 'N':
03779                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03780                break;
03781             case 'L':
03782                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03783                break;
03784             case 'S':
03785                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03786                break;
03787             case 'V':
03788                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03789                break;
03790             case 'R':
03791                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03792                break;
03793             case 'u':
03794                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03795                break;
03796             case 'e':
03797                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03798                break;
03799             case 'x':
03800                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03801                break;
03802             case 'f':
03803                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03804                break;
03805             case 'n':
03806                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03807                break;
03808             case 'p':
03809                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03810                break;
03811             case 'r':
03812                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03813                break;
03814             default:
03815                if (isalpha(*l)) {
03816                   ast_log(LOG_WARNING,
03817                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03818                      *l > 'Z' ? "NPI" : "TON", *l);
03819                }
03820                break;
03821             }
03822             l++;
03823          }
03824       }
03825       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03826          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03827       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03828          if (!strcasecmp(rr_str, "UNKNOWN"))
03829             redirect_reason = 0;
03830          else if (!strcasecmp(rr_str, "BUSY"))
03831             redirect_reason = 1;
03832          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03833          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03834             redirect_reason = 2;
03835          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03836             redirect_reason = 15;
03837          else
03838             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03839       } else
03840          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03841       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03842 
03843 #ifdef SUPPORT_USERUSER
03844       /* User-user info */
03845       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03846       if (useruser)
03847          pri_sr_set_useruser(sr, useruser);
03848 #endif
03849 
03850       if (pri_setup(p->pri->pri, p->call, sr)) {
03851          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03852             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03853          pri_rel(p->pri);
03854          ast_mutex_unlock(&p->lock);
03855          pri_sr_free(sr);
03856          return -1;
03857       }
03858       pri_sr_free(sr);
03859       ast_setstate(ast, AST_STATE_DIALING);
03860       pri_rel(p->pri);
03861    }
03862 #endif
03863    ast_mutex_unlock(&p->lock);
03864    return 0;
03865 }
03866 
03867 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03868 {
03869    struct dahdi_pvt *p = *pvt;
03870    /* Remove channel from the list */
03871    if (p->prev)
03872       p->prev->next = p->next;
03873    if (p->next)
03874       p->next->prev = p->prev;
03875    if (p->use_smdi)
03876       ast_smdi_interface_unref(p->smdi_iface);
03877    if (p->mwi_event_sub)
03878       ast_event_unsubscribe(p->mwi_event_sub);
03879    if (p->vars) {
03880       ast_variables_destroy(p->vars);
03881    }
03882    ast_mutex_destroy(&p->lock);
03883    dahdi_close_sub(p, SUB_REAL);
03884    if (p->owner)
03885       p->owner->tech_pvt = NULL;
03886    free(p);
03887    *pvt = NULL;
03888 }
03889 
03890 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03891 {
03892    int owned = 0;
03893    int i = 0;
03894 
03895    if (!now) {
03896       if (cur->owner) {
03897          owned = 1;
03898       }
03899 
03900       for (i = 0; i < 3; i++) {
03901          if (cur->subs[i].owner) {
03902             owned = 1;
03903          }
03904       }
03905       if (!owned) {
03906          if (prev) {
03907             prev->next = cur->next;
03908             if (prev->next)
03909                prev->next->prev = prev;
03910             else
03911                ifend = prev;
03912          } else {
03913             iflist = cur->next;
03914             if (iflist)
03915                iflist->prev = NULL;
03916             else
03917                ifend = NULL;
03918          }
03919          destroy_dahdi_pvt(&cur);
03920       }
03921    } else {
03922       if (prev) {
03923          prev->next = cur->next;
03924          if (prev->next)
03925             prev->next->prev = prev;
03926          else
03927             ifend = prev;
03928       } else {
03929          iflist = cur->next;
03930          if (iflist)
03931             iflist->prev = NULL;
03932          else
03933             ifend = NULL;
03934       }
03935       destroy_dahdi_pvt(&cur);
03936    }
03937    return 0;
03938 }
03939 
03940 static void destroy_all_channels(void)
03941 {
03942    int x;
03943    struct dahdi_pvt *p, *pl;
03944 
03945    while (num_restart_pending) {
03946       usleep(1);
03947    }
03948 
03949    ast_mutex_lock(&iflock);
03950    /* Destroy all the interfaces and free their memory */
03951    p = iflist;
03952    while (p) {
03953       /* Free any callerid */
03954       if (p->cidspill)
03955          ast_free(p->cidspill);
03956       pl = p;
03957       p = p->next;
03958       x = pl->channel;
03959       /* Free associated memory */
03960       if (pl)
03961          destroy_dahdi_pvt(&pl);
03962       if (option_verbose > 2)
03963          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03964    }
03965    iflist = NULL;
03966    ifcount = 0;
03967    ast_mutex_unlock(&iflock);
03968 }
03969 
03970 #if defined(HAVE_PRI)
03971 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03972 
03973 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03974 {
03975    /* Data will be our digit string */
03976    struct dahdi_pvt *p;
03977    char *digits = (char *) data;
03978 
03979    if (ast_strlen_zero(digits)) {
03980       ast_debug(1, "No digit string sent to application!\n");
03981       return -1;
03982    }
03983 
03984    p = (struct dahdi_pvt *)chan->tech_pvt;
03985 
03986    if (!p) {
03987       ast_debug(1, "Unable to find technology private\n");
03988       return -1;
03989    }
03990 
03991    ast_mutex_lock(&p->lock);
03992 
03993    if (!p->pri || !p->call) {
03994       ast_debug(1, "Unable to find pri or call on channel!\n");
03995       ast_mutex_unlock(&p->lock);
03996       return -1;
03997    }
03998 
03999    if (!pri_grab(p, p->pri)) {
04000       pri_keypad_facility(p->pri->pri, p->call, digits);
04001       pri_rel(p->pri);
04002    } else {
04003       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04004       ast_mutex_unlock(&p->lock);
04005       return -1;
04006    }
04007 
04008    ast_mutex_unlock(&p->lock);
04009 
04010    return 0;
04011 }
04012 #endif   /* defined(HAVE_PRI) */
04013 
04014 #if defined(HAVE_PRI)
04015 #if defined(HAVE_PRI_PROG_W_CAUSE)
04016 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04017 
04018 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04019 {
04020    /* Data will be our digit string */
04021    struct dahdi_pvt *p;
04022    char *parse;
04023    int res = -1;
04024    AST_DECLARE_APP_ARGS(args,
04025       AST_APP_ARG(destination);
04026       AST_APP_ARG(original);
04027       AST_APP_ARG(reason);
04028    );
04029 
04030    if (ast_strlen_zero(data)) {
04031       ast_log(LOG_DEBUG, "No data sent to application!\n");
04032       return -1;
04033    }
04034 
04035    p = (struct dahdi_pvt *)chan->tech_pvt;
04036 
04037    if (!p) {
04038       ast_log(LOG_DEBUG, "Unable to find technology private\n");
04039       return -1;
04040    }
04041 
04042    parse = ast_strdupa(data);
04043    AST_STANDARD_APP_ARGS(args, parse);
04044 
04045    if (ast_strlen_zero(args.destination)) {
04046       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04047       return -1;
04048    }
04049 
04050    if (ast_strlen_zero(args.original)) {
04051       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04052       args.original = NULL;
04053    }
04054 
04055    if (ast_strlen_zero(args.reason)) {
04056       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04057       args.reason = NULL;
04058    }
04059 
04060    ast_mutex_lock(&p->lock);
04061 
04062    if (!p->pri || !p->call) {
04063       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04064       ast_mutex_unlock(&p->lock);
04065       return -1;
04066    }
04067 
04068    switch (p->sig) {
04069    case SIG_PRI:
04070       if (!pri_grab(p, p->pri)) {
04071          if (chan->_state == AST_STATE_RING) {
04072             res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04073          }
04074          pri_rel(p->pri);
04075       } else {
04076          ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04077          ast_mutex_unlock(&p->lock);
04078          return -1;
04079       }
04080       break;
04081    }
04082 
04083    ast_mutex_unlock(&p->lock);
04084 
04085    return res;
04086 }
04087 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
04088 #endif   /* defined(HAVE_PRI) */
04089 
04090 #if defined(HAVE_PRI)
04091 static int pri_is_up(struct dahdi_pri *pri)
04092 {
04093    int x;
04094    for (x = 0; x < NUM_DCHANS; x++) {
04095       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04096          return 1;
04097    }
04098    return 0;
04099 }
04100 #endif   /* defined(HAVE_PRI) */
04101 
04102 #if defined(HAVE_PRI)
04103 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04104 {
04105    bearer->owner = &inuse;
04106    bearer->realcall = crv;
04107    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04108    if (crv->subs[SUB_REAL].owner)
04109       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04110    crv->bearer = bearer;
04111    crv->call = bearer->call;
04112    crv->pri = pri;
04113    return 0;
04114 }
04115 #endif   /* defined(HAVE_PRI) */
04116 
04117 #if defined(HAVE_PRI)
04118 static char *pri_order(int level)
04119 {
04120    switch (level) {
04121    case 0:
04122       return "Primary";
04123    case 1:
04124       return "Secondary";
04125    case 2:
04126       return "Tertiary";
04127    case 3:
04128       return "Quaternary";
04129    default:
04130       return "<Unknown>";
04131    }
04132 }
04133 #endif   /* defined(HAVE_PRI) */
04134 
04135 #if defined(HAVE_PRI)
04136 /* Returns fd of the active dchan */
04137 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04138 {
04139    int x = -1;
04140 
04141    for (x = 0; x < NUM_DCHANS; x++) {
04142       if ((pri->dchans[x] == pri->pri))
04143          break;
04144    }
04145 
04146    return pri->fds[x];
04147 }
04148 #endif   /* defined(HAVE_PRI) */
04149 
04150 #if defined(HAVE_PRI)
04151 static int pri_find_dchan(struct dahdi_pri *pri)
04152 {
04153    int oldslot = -1;
04154    struct pri *old;
04155    int newslot = -1;
04156    int x;
04157    old = pri->pri;
04158    for (x = 0; x < NUM_DCHANS; x++) {
04159       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04160          newslot = x;
04161       if (pri->dchans[x] == old) {
04162          oldslot = x;
04163       }
04164    }
04165    if (newslot < 0) {
04166       newslot = 0;
04167       /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
04168       if (pri->sig != SIG_BRI_PTMP) {
04169          ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
04170             pri->dchannels[newslot]);
04171       }
04172    }
04173    if (old && (oldslot != newslot))
04174       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04175          pri->dchannels[oldslot], pri->dchannels[newslot]);
04176    pri->pri = pri->dchans[newslot];
04177    return 0;
04178 }
04179 #endif   /* defined(HAVE_PRI) */
04180 
04181 #if defined(HAVE_OPENR2)
04182 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04183 
04184 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04185 {
04186    /* data is whether to accept with charge or no charge */
04187    openr2_call_mode_t accept_mode;
04188    int res, timeout, maxloops;
04189    struct ast_frame *f;
04190    struct dahdi_pvt *p;
04191    char *parse;
04192    AST_DECLARE_APP_ARGS(args,
04193          AST_APP_ARG(charge);
04194    );
04195 
04196    if (ast_strlen_zero(data)) {
04197       ast_log(LOG_DEBUG, "No data sent to application!\n");
04198       return -1;
04199    }
04200 
04201    if (chan->tech != &dahdi_tech) {
04202       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04203       return -1;
04204    }
04205 
04206    p = (struct dahdi_pvt *)chan->tech_pvt;
04207    if (!p) {
04208       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04209       return -1;
04210    }
04211 
04212    parse = ast_strdupa(data);
04213    AST_STANDARD_APP_ARGS(args, parse);
04214 
04215    if (ast_strlen_zero(args.charge)) {
04216       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04217       return -1;
04218    }
04219 
04220    ast_mutex_lock(&p->lock);
04221    if (!p->mfcr2 || !p->mfcr2call) {
04222       ast_mutex_unlock(&p->lock);
04223       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04224       return -1;
04225    }
04226 
04227    if (p->mfcr2_call_accepted) {
04228       ast_mutex_unlock(&p->lock);
04229       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04230       return 0;
04231    }
04232    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04233    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04234       ast_mutex_unlock(&p->lock);
04235       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04236       return -1;
04237    }
04238    ast_mutex_unlock(&p->lock);
04239 
04240    res = 0;
04241    timeout = 100;
04242    maxloops = 50; /* wait up to 5 seconds */
04243    /* we need to read() until the call is accepted */
04244    while (maxloops > 0) {
04245       maxloops--;
04246       if (ast_check_hangup(chan)) {
04247          break;
04248       }
04249       res = ast_waitfor(chan, timeout);
04250       if (res < 0) {
04251          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04252          res = -1;
04253          break;
04254       }
04255       if (res == 0) {
04256          continue;
04257       }
04258       f = ast_read(chan);
04259       if (!f) {
04260          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04261          res = -1;
04262          break;
04263       }
04264       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04265          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04266          ast_frfree(f);
04267          res = -1;
04268          break;
04269       }
04270       ast_frfree(f);
04271       ast_mutex_lock(&p->lock);
04272       if (p->mfcr2_call_accepted) {
04273          ast_mutex_unlock(&p->lock);
04274          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04275          break;
04276       }
04277       ast_mutex_unlock(&p->lock);
04278    }
04279    if (res == -1) {
04280       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04281    }
04282    return res;
04283 }
04284 
04285 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04286 {
04287    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04288    switch (cause) {
04289    case AST_CAUSE_USER_BUSY:
04290    case AST_CAUSE_CALL_REJECTED:
04291    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
04292       r2cause = OR2_CAUSE_BUSY_NUMBER;
04293       break;
04294 
04295    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04296    case AST_CAUSE_SWITCH_CONGESTION:
04297       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04298       break;
04299 
04300    case AST_CAUSE_UNALLOCATED:
04301       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04302       break;
04303 
04304    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04305    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04306       r2cause = OR2_CAUSE_OUT_OF_ORDER;
04307       break;
04308 
04309    case AST_CAUSE_NO_ANSWER:
04310    case AST_CAUSE_NO_USER_RESPONSE:
04311       r2cause = OR2_CAUSE_NO_ANSWER;
04312       break;
04313 
04314    default:
04315       r2cause = OR2_CAUSE_NORMAL_CLEARING;
04316       break;
04317    }
04318    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04319          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04320    return r2cause;
04321 }
04322 #endif
04323 
04324 static int dahdi_hangup(struct ast_channel *ast)
04325 {
04326    int res;
04327    int idx,x, law;
04328    /*static int restore_gains(struct dahdi_pvt *p);*/
04329    struct dahdi_pvt *p = ast->tech_pvt;
04330    struct dahdi_pvt *tmp = NULL;
04331    struct dahdi_pvt *prev = NULL;
04332    struct dahdi_params par;
04333 
04334    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04335    if (!ast->tech_pvt) {
04336       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04337       return 0;
04338    }
04339 
04340    ast_mutex_lock(&p->lock);
04341 
04342    idx = dahdi_get_index(ast, p, 1);
04343 
04344    switch (p->sig) {
04345    case SIG_PRI:
04346    case SIG_BRI:
04347    case SIG_BRI_PTMP:
04348    case SIG_SS7:
04349       x = 1;
04350       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04351       /* Fall through */
04352    case SIG_MFCR2:
04353       p->cid_num[0] = '\0';
04354       p->cid_name[0] = '\0';
04355       break;
04356    default:
04357       break;
04358    }
04359 
04360    x = 0;
04361    dahdi_confmute(p, 0);
04362    p->muting = 0;
04363    restore_gains(p);
04364    if (p->origcid_num) {
04365       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04366       ast_free(p->origcid_num);
04367       p->origcid_num = NULL;
04368    }
04369    if (p->origcid_name) {
04370       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04371       ast_free(p->origcid_name);
04372       p->origcid_name = NULL;
04373    }
04374    if (p->dsp)
04375       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04376    p->exten[0] = '\0';
04377 
04378    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04379       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04380    p->ignoredtmf = 0;
04381 
04382    if (idx > -1) {
04383       /* Real channel, do some fixup */
04384       p->subs[idx].owner = NULL;
04385       p->subs[idx].needanswer = 0;
04386       p->subs[idx].needflash = 0;
04387       p->subs[idx].needringing = 0;
04388       p->subs[idx].needbusy = 0;
04389       p->subs[idx].needcongestion = 0;
04390       p->subs[idx].linear = 0;
04391       p->subs[idx].needcallerid = 0;
04392       p->polarity = POLARITY_IDLE;
04393       dahdi_setlinear(p->subs[idx].dfd, 0);
04394       if (idx == SUB_REAL) {
04395          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04396             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04397             if (p->subs[SUB_CALLWAIT].inthreeway) {
04398                /* We had flipped over to answer a callwait and now it's gone */
04399                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04400                /* Move to the call-wait, but un-own us until they flip back. */
04401                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04402                unalloc_sub(p, SUB_CALLWAIT);
04403                p->owner = NULL;
04404             } else {
04405                /* The three way hung up, but we still have a call wait */
04406                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
04407                swap_subs(p, SUB_THREEWAY, SUB_REAL);
04408                unalloc_sub(p, SUB_THREEWAY);
04409                if (p->subs[SUB_REAL].inthreeway) {
04410                   /* This was part of a three way call.  Immediately make way for
04411                      another call */
04412                   ast_debug(1, "Call was complete, setting owner to former third call\n");
04413                   p->owner = p->subs[SUB_REAL].owner;
04414                } else {
04415                   /* This call hasn't been completed yet...  Set owner to NULL */
04416                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04417                   p->owner = NULL;
04418                }
04419                p->subs[SUB_REAL].inthreeway = 0;
04420             }
04421          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04422             /* Move to the call-wait and switch back to them. */
04423             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04424             unalloc_sub(p, SUB_CALLWAIT);
04425             p->owner = p->subs[SUB_REAL].owner;
04426             if (p->owner->_state != AST_STATE_UP)
04427                p->subs[SUB_REAL].needanswer = 1;
04428             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04429                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04430          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04431             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04432             unalloc_sub(p, SUB_THREEWAY);
04433             if (p->subs[SUB_REAL].inthreeway) {
04434                /* This was part of a three way call.  Immediately make way for
04435                   another call */
04436                ast_debug(1, "Call was complete, setting owner to former third call\n");
04437                p->owner = p->subs[SUB_REAL].owner;
04438             } else {
04439                /* This call hasn't been completed yet...  Set owner to NULL */
04440                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04441                p->owner = NULL;
04442             }
04443             p->subs[SUB_REAL].inthreeway = 0;
04444          }
04445       } else if (idx == SUB_CALLWAIT) {
04446          /* Ditch the holding callwait call, and immediately make it availabe */
04447          if (p->subs[SUB_CALLWAIT].inthreeway) {
04448             /* This is actually part of a three way, placed on hold.  Place the third part
04449                on music on hold now */
04450             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04451                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04452                   S_OR(p->mohsuggest, NULL),
04453                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04454             }
04455             p->subs[SUB_THREEWAY].inthreeway = 0;
04456             /* Make it the call wait now */
04457             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04458             unalloc_sub(p, SUB_THREEWAY);
04459          } else
04460             unalloc_sub(p, SUB_CALLWAIT);
04461       } else if (idx == SUB_THREEWAY) {
04462          if (p->subs[SUB_CALLWAIT].inthreeway) {
04463             /* The other party of the three way call is currently in a call-wait state.
04464                Start music on hold for them, and take the main guy out of the third call */
04465             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04466                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04467                   S_OR(p->mohsuggest, NULL),
04468                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04469             }
04470             p->subs[SUB_CALLWAIT].inthreeway = 0;
04471          }
04472          p->subs[SUB_REAL].inthreeway = 0;
04473          /* If this was part of a three way call index, let us make
04474             another three way call */
04475          unalloc_sub(p, SUB_THREEWAY);
04476       } else {
04477          /* This wasn't any sort of call, but how are we an index? */
04478          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04479       }
04480    }
04481 
04482    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04483       p->owner = NULL;
04484       p->ringt = 0;
04485       p->distinctivering = 0;
04486       p->confirmanswer = 0;
04487       p->cidrings = 1;
04488       p->outgoing = 0;
04489       p->digital = 0;
04490       p->faxhandled = 0;
04491       p->pulsedial = 0;
04492       p->onhooktime = time(NULL);
04493 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04494       p->proceeding = 0;
04495       p->dialing = 0;
04496       p->progress = 0;
04497       p->alerting = 0;
04498       p->setup_ack = 0;
04499       p->rlt = 0;
04500 #endif
04501       if (p->dsp) {
04502          ast_dsp_free(p->dsp);
04503          p->dsp = NULL;
04504       }
04505 
04506       if (p->bufferoverrideinuse) {
04507          /* faxbuffers are in use, revert them */
04508          struct dahdi_bufferinfo bi = {
04509             .txbufpolicy = p->buf_policy,
04510             .rxbufpolicy = p->buf_policy,
04511             .bufsize = p->bufsize,
04512             .numbufs = p->buf_no
04513          };
04514          int bpres;
04515 
04516          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04517             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04518          }
04519          p->bufferoverrideinuse = 0;
04520       }
04521 
04522       law = DAHDI_LAW_DEFAULT;
04523       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04524       if (res < 0)
04525          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04526       /* Perform low level hangup if no owner left */
04527 #ifdef HAVE_SS7
04528       if (p->ss7) {
04529          if (p->ss7call) {
04530             if (!ss7_grab(p, p->ss7)) {
04531                if (!p->alreadyhungup) {
04532                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04533                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04534 
04535                   if (cause) {
04536                      if (atoi(cause))
04537                         icause = atoi(cause);
04538                   }
04539                   isup_rel(p->ss7->ss7, p->ss7call, icause);
04540                   ss7_rel(p->ss7);
04541                   p->alreadyhungup = 1;
04542                } else
04543                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04544             } else {
04545                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04546                res = -1;
04547             }
04548          }
04549       }
04550 #endif
04551 #ifdef HAVE_OPENR2
04552       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04553          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04554          /* If it's an incoming call, check the mfcr2_forced_release setting */
04555          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04556             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04557          } else {
04558             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04559             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04560             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04561                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04562             dahdi_r2_disconnect_call(p, r2cause);
04563          }
04564       } else if (p->mfcr2call) {
04565          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04566          /* since ast_request() was called but not ast_call() we have not yet dialed
04567          and the openr2 stack will not call on_call_end callback, we need to unset
04568          the mfcr2call flag and bump the monitor count so the monitor thread can take
04569          care of this channel events from now on */
04570          p->mfcr2call = 0;
04571       }
04572 #endif
04573 #ifdef HAVE_PRI
04574       if (p->pri) {
04575 #ifdef SUPPORT_USERUSER
04576          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04577 #endif
04578 
04579          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
04580          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04581             if (!pri_grab(p, p->pri)) {
04582                if (p->alreadyhungup) {
04583                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
04584 
04585 #ifdef SUPPORT_USERUSER
04586                   pri_call_set_useruser(p->call, useruser);
04587 #endif
04588 
04589                   pri_hangup(p->pri->pri, p->call, -1);
04590                   p->call = NULL;
04591                   if (p->bearer)
04592                      p->bearer->call = NULL;
04593                } else {
04594                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04595                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04596                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
04597 
04598 #ifdef SUPPORT_USERUSER
04599                   pri_call_set_useruser(p->call, useruser);
04600 #endif
04601 
04602                   p->alreadyhungup = 1;
04603                   if (p->bearer)
04604                      p->bearer->alreadyhungup = 1;
04605                   if (cause) {
04606                      if (atoi(cause))
04607                         icause = atoi(cause);
04608                   }
04609                   pri_hangup(p->pri->pri, p->call, icause);
04610                }
04611                if (res < 0)
04612                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
04613                pri_rel(p->pri);
04614             } else {
04615                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04616                res = -1;
04617             }
04618          } else {
04619             if (p->bearer)
04620                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04621             p->call = NULL;
04622             res = 0;
04623          }
04624       }
04625 #endif
04626       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04627          && (p->sig != SIG_BRI)
04628          && (p->sig != SIG_BRI_PTMP))
04629          && (p->sig != SIG_MFCR2))
04630          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04631       if (res < 0) {
04632          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04633       }
04634       switch (p->sig) {
04635       case SIG_FXOGS:
04636       case SIG_FXOLS:
04637       case SIG_FXOKS:
04638          memset(&par, 0, sizeof(par));
04639          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04640          if (!res) {
04641 #if 0
04642             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04643 #endif
04644             /* If they're off hook, try playing congestion */
04645             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04646                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04647             else
04648                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04649             p->fxsoffhookstate = par.rxisoffhook;
04650          }
04651          break;
04652       case SIG_FXSGS:
04653       case SIG_FXSLS:
04654       case SIG_FXSKS:
04655          /* Make sure we're not made available for at least two seconds assuming
04656             we were actually used for an inbound or outbound call. */
04657          if (ast->_state != AST_STATE_RESERVED) {
04658             time(&p->guardtime);
04659             p->guardtime += 2;
04660          }
04661          break;
04662       default:
04663          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04664       }
04665       if (p->cidspill)
04666          ast_free(p->cidspill);
04667       if (p->sig)
04668          dahdi_disable_ec(p);
04669       x = 0;
04670       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04671       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04672       p->didtdd = 0;
04673       p->cidspill = NULL;
04674       p->callwaitcas = 0;
04675       p->callwaiting = p->permcallwaiting;
04676       p->hidecallerid = p->permhidecallerid;
04677       p->waitingfordt.tv_sec = 0;
04678       p->dialing = 0;
04679       p->rdnis[0] = '\0';
04680       update_conf(p);
04681       reset_conf(p);
04682       /* Restore data mode */
04683       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04684          x = 0;
04685          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04686       }
04687 #ifdef HAVE_PRI
04688       if (p->bearer) {
04689          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04690          /* Free up the bearer channel as well, and
04691             don't use its file descriptor anymore */
04692          update_conf(p->bearer);
04693          reset_conf(p->bearer);
04694          p->bearer->owner = NULL;
04695          p->bearer->realcall = NULL;
04696          p->bearer = NULL;
04697          p->subs[SUB_REAL].dfd = -1;
04698          p->pri = NULL;
04699       }
04700 #endif
04701       if (num_restart_pending == 0)
04702          restart_monitor();
04703    }
04704 
04705    p->callwaitingrepeat = 0;
04706    p->cidcwexpire = 0;
04707    p->oprmode = 0;
04708    ast->tech_pvt = NULL;
04709    ast_mutex_unlock(&p->lock);
04710    ast_module_unref(ast_module_info->self);
04711    ast_verb(3, "Hungup '%s'\n", ast->name);
04712 
04713    ast_mutex_lock(&iflock);
04714 
04715    if (p->restartpending) {
04716       num_restart_pending--;
04717    }
04718 
04719    tmp = iflist;
04720    prev = NULL;
04721    if (p->destroy) {
04722       while (tmp) {
04723          if (tmp == p) {
04724             destroy_channel(prev, tmp, 0);
04725             break;
04726          } else {
04727             prev = tmp;
04728             tmp = tmp->next;
04729          }
04730       }
04731    }
04732    ast_mutex_unlock(&iflock);
04733    return 0;
04734 }
04735 
04736 static int dahdi_answer(struct ast_channel *ast)
04737 {
04738    struct dahdi_pvt *p = ast->tech_pvt;
04739    int res = 0;
04740    int idx;
04741    int oldstate = ast->_state;
04742    ast_setstate(ast, AST_STATE_UP);
04743    ast_mutex_lock(&p->lock);
04744    idx = dahdi_get_index(ast, p, 0);
04745    if (idx < 0)
04746       idx = SUB_REAL;
04747    /* nothing to do if a radio channel */
04748    if ((p->radio || (p->oprmode < 0))) {
04749       ast_mutex_unlock(&p->lock);
04750       return 0;
04751    }
04752    switch (p->sig) {
04753    case SIG_FXSLS:
04754    case SIG_FXSGS:
04755    case SIG_FXSKS:
04756       p->ringt = 0;
04757       /* Fall through */
04758    case SIG_EM:
04759    case SIG_EM_E1:
04760    case SIG_EMWINK:
04761    case SIG_FEATD:
04762    case SIG_FEATDMF:
04763    case SIG_FEATDMF_TA:
04764    case SIG_E911:
04765    case SIG_FGC_CAMA:
04766    case SIG_FGC_CAMAMF:
04767    case SIG_FEATB:
04768    case SIG_SF:
04769    case SIG_SFWINK:
04770    case SIG_SF_FEATD:
04771    case SIG_SF_FEATDMF:
04772    case SIG_SF_FEATB:
04773    case SIG_FXOLS:
04774    case SIG_FXOGS:
04775    case SIG_FXOKS:
04776       /* Pick up the line */
04777       ast_debug(1, "Took %s off hook\n", ast->name);
04778       if (p->hanguponpolarityswitch) {
04779          p->polaritydelaytv = ast_tvnow();
04780       }
04781       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04782       tone_zone_play_tone(p->subs[idx].dfd, -1);
04783       p->dialing = 0;
04784       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04785          if (oldstate == AST_STATE_RINGING) {
04786             ast_debug(1, "Finally swapping real and threeway\n");
04787             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04788             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04789             p->owner = p->subs[SUB_REAL].owner;
04790          }
04791       }
04792       if (p->sig & __DAHDI_SIG_FXS) {
04793          dahdi_enable_ec(p);
04794          dahdi_train_ec(p);
04795       }
04796       break;
04797 #ifdef HAVE_PRI
04798    case SIG_BRI:
04799    case SIG_BRI_PTMP:
04800    case SIG_PRI:
04801       /* Send a pri acknowledge */
04802       if (!pri_grab(p, p->pri)) {
04803          p->proceeding = 1;
04804          p->dialing = 0;
04805          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04806          pri_rel(p->pri);
04807       } else {
04808          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04809          res = -1;
04810       }
04811       break;
04812 #endif
04813 #ifdef HAVE_SS7
04814    case SIG_SS7:
04815       if (!ss7_grab(p, p->ss7)) {
04816          p->proceeding = 1;
04817          res = isup_anm(p->ss7->ss7, p->ss7call);
04818          ss7_rel(p->ss7);
04819       } else {
04820          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04821          res = -1;
04822       }
04823       break;
04824 #endif
04825 #ifdef HAVE_OPENR2
04826    case SIG_MFCR2:
04827       if (!p->mfcr2_call_accepted) {
04828          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
04829             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
04830          p->mfcr2_answer_pending = 1;
04831          if (p->mfcr2_charge_calls) {
04832             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04833             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04834          } else {
04835             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04836             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04837          }
04838       } else {
04839          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04840          dahdi_r2_answer(p);
04841       }
04842       break;
04843 #endif
04844    case 0:
04845       ast_mutex_unlock(&p->lock);
04846       return 0;
04847    default:
04848       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04849       res = -1;
04850    }
04851    ast_mutex_unlock(&p->lock);
04852    return res;
04853 }
04854 
04855 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04856 {
04857    char *cp;
04858    signed char *scp;
04859    int x;
04860    int idx;
04861    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04862    struct oprmode *oprmode;
04863 
04864 
04865    /* all supported options require data */
04866    if (!data || (datalen < 1)) {
04867       errno = EINVAL;
04868       return -1;
04869    }
04870 
04871    switch (option) {
04872    case AST_OPTION_TXGAIN:
04873       scp = (signed char *) data;
04874       idx = dahdi_get_index(chan, p, 0);
04875       if (idx < 0) {
04876          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04877          return -1;
04878       }
04879       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04880       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04881    case AST_OPTION_RXGAIN:
04882       scp = (signed char *) data;
04883       idx = dahdi_get_index(chan, p, 0);
04884       if (idx < 0) {
04885          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04886          return -1;
04887       }
04888       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04889       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04890    case AST_OPTION_TONE_VERIFY:
04891       if (!p->dsp)
04892          break;
04893       cp = (char *) data;
04894       switch (*cp) {
04895       case 1:
04896          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04897          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04898          break;
04899       case 2:
04900          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04901          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04902          break;
04903       default:
04904          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04905          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04906          break;
04907       }
04908       break;
04909    case AST_OPTION_TDD:
04910       /* turn on or off TDD */
04911       cp = (char *) data;
04912       p->mate = 0;
04913       if (!*cp) { /* turn it off */
04914          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04915          if (p->tdd)
04916             tdd_free(p->tdd);
04917          p->tdd = 0;
04918          break;
04919       }
04920       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04921          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04922       dahdi_disable_ec(p);
04923       /* otherwise, turn it on */
04924       if (!p->didtdd) { /* if havent done it yet */
04925          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04926          unsigned char *buf;
04927          int size, res, fd, len;
04928          struct pollfd fds[1];
04929 
04930          buf = mybuf;
04931          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04932          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04933          len = 40000;
04934          idx = dahdi_get_index(chan, p, 0);
04935          if (idx < 0) {
04936             ast_log(LOG_WARNING, "No index in TDD?\n");
04937             return -1;
04938          }
04939          fd = p->subs[idx].dfd;
04940          while (len) {
04941             if (ast_check_hangup(chan))
04942                return -1;
04943             size = len;
04944             if (size > READ_SIZE)
04945                size = READ_SIZE;
04946             fds[0].fd = fd;
04947             fds[0].events = POLLPRI | POLLOUT;
04948             fds[0].revents = 0;
04949             res = poll(fds, 1, -1);
04950             if (!res) {
04951                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04952                continue;
04953             }
04954             /* if got exception */
04955             if (fds[0].revents & POLLPRI)
04956                return -1;
04957             if (!(fds[0].revents & POLLOUT)) {
04958                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04959                continue;
04960             }
04961             res = write(fd, buf, size);
04962             if (res != size) {
04963                if (res == -1) return -1;
04964                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04965                break;
04966             }
04967             len -= size;
04968             buf += size;
04969          }
04970          p->didtdd = 1; /* set to have done it now */
04971       }
04972       if (*cp == 2) { /* Mate mode */
04973          if (p->tdd)
04974             tdd_free(p->tdd);
04975          p->tdd = 0;
04976          p->mate = 1;
04977          break;
04978       }
04979       if (!p->tdd) { /* if we dont have one yet */
04980          p->tdd = tdd_new(); /* allocate one */
04981       }
04982       break;
04983    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04984       if (!p->dsp)
04985          break;
04986       cp = (char *) data;
04987       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04988          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04989       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04990       break;
04991    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04992       cp = (char *) data;
04993       if (!*cp) {
04994          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04995          x = 0;
04996          dahdi_disable_ec(p);
04997       } else {
04998          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04999          x = 1;
05000       }
05001       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05002          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05003       break;
05004    case AST_OPTION_OPRMODE:  /* Operator services mode */
05005       oprmode = (struct oprmode *) data;
05006       /* We don't support operator mode across technologies */
05007       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05008          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05009                chan->tech->type, oprmode->peer->tech->type);
05010          errno = EINVAL;
05011          return -1;
05012       }
05013       pp = oprmode->peer->tech_pvt;
05014       p->oprmode = pp->oprmode = 0;
05015       /* setup peers */
05016       p->oprpeer = pp;
05017       pp->oprpeer = p;
05018       /* setup modes, if any */
05019       if (oprmode->mode)
05020       {
05021          pp->oprmode = oprmode->mode;
05022          p->oprmode = -oprmode->mode;
05023       }
05024       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05025          oprmode->mode, chan->name,oprmode->peer->name);
05026       break;
05027    case AST_OPTION_ECHOCAN:
05028       cp = (char *) data;
05029       if (*cp) {
05030          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05031          dahdi_enable_ec(p);
05032       } else {
05033          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05034          dahdi_disable_ec(p);
05035       }
05036       break;
05037    }
05038    errno = 0;
05039 
05040    return 0;
05041 }
05042 
05043 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05044 {
05045    struct dahdi_pvt *p = chan->tech_pvt;
05046    int res = 0;
05047 
05048    if (!strcasecmp(data, "rxgain")) {
05049       ast_mutex_lock(&p->lock);
05050       snprintf(buf, len, "%f", p->rxgain);
05051       ast_mutex_unlock(&p->lock);
05052    } else if (!strcasecmp(data, "txgain")) {
05053       ast_mutex_lock(&p->lock);
05054       snprintf(buf, len, "%f", p->txgain);
05055       ast_mutex_unlock(&p->lock);
05056    } else {
05057       ast_copy_string(buf, "", len);
05058       res = -1;
05059    }
05060 
05061    return res;
05062 }
05063 
05064 
05065 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05066 {
05067    int res;
05068    char policy_str[21] = "";
05069    
05070    if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05071       ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05072       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05073       return 1;
05074    }
05075    if (*num_buffers < 0) {
05076       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05077       return -1;
05078    }
05079    if (!strcasecmp(policy_str, "full")) {
05080       *policy = DAHDI_POLICY_WHEN_FULL;
05081    } else if (!strcasecmp(policy_str, "immediate")) {
05082       *policy = DAHDI_POLICY_IMMEDIATE;
05083 #ifdef DAHDI_POLICY_HALF_FULL
05084    } else if (!strcasecmp(policy_str, "half")) {
05085       *policy = DAHDI_POLICY_HALF_FULL;
05086 #endif
05087    } else {
05088       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05089       return -1;
05090    }
05091 
05092    return 0;
05093 }
05094 
05095 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05096 {
05097    struct dahdi_pvt *p = chan->tech_pvt;
05098    int res = 0;
05099 
05100    if (!strcasecmp(data, "buffers")) {
05101       int num_bufs, policy;
05102 
05103       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05104          struct dahdi_bufferinfo bi = {
05105             .txbufpolicy = policy,
05106             .rxbufpolicy = policy,
05107             .bufsize = p->bufsize,
05108             .numbufs = num_bufs,
05109          };
05110          int bpres;
05111 
05112          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05113             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05114          } else {
05115             p->bufferoverrideinuse = 1;
05116          }
05117       } else {
05118          res = -1;
05119       }
05120    } else {
05121       res = -1;
05122    }
05123 
05124    return res;
05125 }
05126 
05127 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05128 {
05129    /* Unlink a specific slave or all slaves/masters from a given master */
05130    int x;
05131    int hasslaves;
05132    if (!master)
05133       return;
05134    if (needlock) {
05135       ast_mutex_lock(&master->lock);
05136       if (slave) {
05137          while (ast_mutex_trylock(&slave->lock)) {
05138             DEADLOCK_AVOIDANCE(&master->lock);
05139          }
05140       }
05141    }
05142    hasslaves = 0;
05143    for (x = 0; x < MAX_SLAVES; x++) {
05144       if (master->slaves[x]) {
05145          if (!slave || (master->slaves[x] == slave)) {
05146             /* Take slave out of the conference */
05147             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05148             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05149             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05150             master->slaves[x]->master = NULL;
05151             master->slaves[x] = NULL;
05152          } else
05153             hasslaves = 1;
05154       }
05155       if (!hasslaves)
05156          master->inconference = 0;
05157    }
05158    if (!slave) {
05159       if (master->master) {
05160          /* Take master out of the conference */
05161          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05162          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05163          hasslaves = 0;
05164          for (x = 0; x < MAX_SLAVES; x++) {
05165             if (master->master->slaves[x] == master)
05166                master->master->slaves[x] = NULL;
05167             else if (master->master->slaves[x])
05168                hasslaves = 1;
05169          }
05170          if (!hasslaves)
05171             master->master->inconference = 0;
05172       }
05173       master->master = NULL;
05174    }
05175    update_conf(master);
05176    if (needlock) {
05177       if (slave)
05178          ast_mutex_unlock(&slave->lock);
05179       ast_mutex_unlock(&master->lock);
05180    }
05181 }
05182 
05183 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05184    int x;
05185    if (!slave || !master) {
05186       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05187       return;
05188    }
05189    for (x = 0; x < MAX_SLAVES; x++) {
05190       if (!master->slaves[x]) {
05191          master->slaves[x] = slave;
05192          break;
05193       }
05194    }
05195    if (x >= MAX_SLAVES) {
05196       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05197       master->slaves[MAX_SLAVES - 1] = slave;
05198    }
05199    if (slave->master)
05200       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05201    slave->master = master;
05202 
05203    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05204 }
05205 
05206 static void disable_dtmf_detect(struct dahdi_pvt *p)
05207 {
05208    int val;
05209 
05210    p->ignoredtmf = 1;
05211 
05212    val = 0;
05213    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05214 
05215    if (!p->hardwaredtmf && p->dsp) {
05216       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05217       ast_dsp_set_features(p->dsp, p->dsp_features);
05218    }
05219 }
05220 
05221 static void enable_dtmf_detect(struct dahdi_pvt *p)
05222 {
05223    int val;
05224 
05225    if (p->channel == CHAN_PSEUDO)
05226       return;
05227 
05228    p->ignoredtmf = 0;
05229 
05230    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05231    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05232 
05233    if (!p->hardwaredtmf && p->dsp) {
05234       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05235       ast_dsp_set_features(p->dsp, p->dsp_features);
05236    }
05237 }
05238 
05239 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)
05240 {
05241    struct ast_channel *who;
05242    struct dahdi_pvt *p0, *p1, *op0, *op1;
05243    struct dahdi_pvt *master = NULL, *slave = NULL;
05244    struct ast_frame *f;
05245    int inconf = 0;
05246    int nothingok = 1;
05247    int ofd0, ofd1;
05248    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05249    int os0 = -1, os1 = -1;
05250    int priority = 0;
05251    struct ast_channel *oc0, *oc1;
05252    enum ast_bridge_result res;
05253 
05254 #ifdef PRI_2BCT
05255    int triedtopribridge = 0;
05256 #endif
05257 
05258    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
05259       There is code below to handle it properly until DTMF is actually seen,
05260       but due to currently unresolved issues it's ignored...
05261    */
05262 
05263    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05264       return AST_BRIDGE_FAILED_NOWARN;
05265 
05266    ast_channel_lock(c0);
05267    while (ast_channel_trylock(c1)) {
05268       CHANNEL_DEADLOCK_AVOIDANCE(c0);
05269    }
05270 
05271    p0 = c0->tech_pvt;
05272    p1 = c1->tech_pvt;
05273    /* cant do pseudo-channels here */
05274    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05275       ast_channel_unlock(c0);
05276       ast_channel_unlock(c1);
05277       return AST_BRIDGE_FAILED_NOWARN;
05278    }
05279 
05280    oi0 = dahdi_get_index(c0, p0, 0);
05281    oi1 = dahdi_get_index(c1, p1, 0);
05282    if ((oi0 < 0) || (oi1 < 0)) {
05283       ast_channel_unlock(c0);
05284       ast_channel_unlock(c1);
05285       return AST_BRIDGE_FAILED;
05286    }
05287 
05288    op0 = p0 = c0->tech_pvt;
05289    op1 = p1 = c1->tech_pvt;
05290    ofd0 = c0->fds[0];
05291    ofd1 = c1->fds[0];
05292    oc0 = p0->owner;
05293    oc1 = p1->owner;
05294 
05295    if (ast_mutex_trylock(&p0->lock)) {
05296       /* Don't block, due to potential for deadlock */
05297       ast_channel_unlock(c0);
05298       ast_channel_unlock(c1);
05299       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05300       return AST_BRIDGE_RETRY;
05301    }
05302    if (ast_mutex_trylock(&p1->lock)) {
05303       /* Don't block, due to potential for deadlock */
05304       ast_mutex_unlock(&p0->lock);
05305       ast_channel_unlock(c0);
05306       ast_channel_unlock(c1);
05307       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05308       return AST_BRIDGE_RETRY;
05309    }
05310 
05311    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05312       if (p0->owner && p1->owner) {
05313          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
05314          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05315             master = p0;
05316             slave = p1;
05317             inconf = 1;
05318          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05319             master = p1;
05320             slave = p0;
05321             inconf = 1;
05322          } else {
05323             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
05324             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05325                p0->channel,
05326                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05327                p0->subs[SUB_REAL].inthreeway, p0->channel,
05328                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05329                p1->subs[SUB_REAL].inthreeway);
05330          }
05331          nothingok = 0;
05332       }
05333    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05334       if (p1->subs[SUB_THREEWAY].inthreeway) {
05335          master = p1;
05336          slave = p0;
05337          nothingok = 0;
05338       }
05339    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05340       if (p0->subs[SUB_THREEWAY].inthreeway) {
05341          master = p0;
05342          slave = p1;
05343          nothingok = 0;
05344       }
05345    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05346       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
05347          don't put us in anything */
05348       if (p1->subs[SUB_CALLWAIT].inthreeway) {
05349          master = p1;
05350          slave = p0;
05351          nothingok = 0;
05352       }
05353    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05354       /* Same as previous */
05355       if (p0->subs[SUB_CALLWAIT].inthreeway) {
05356          master = p0;
05357          slave = p1;
05358          nothingok = 0;
05359       }
05360    }
05361    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05362       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05363    if (master && slave) {
05364       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
05365          in an active threeway call with a channel that is ringing, we should
05366          indicate ringing. */
05367       if ((oi1 == SUB_THREEWAY) &&
05368          p1->subs[SUB_THREEWAY].inthreeway &&
05369          p1->subs[SUB_REAL].owner &&
05370          p1->subs[SUB_REAL].inthreeway &&
05371          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05372          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05373          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05374          os1 = p1->subs[SUB_REAL].owner->_state;
05375       } else {
05376          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05377          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05378       }
05379       if ((oi0 == SUB_THREEWAY) &&
05380          p0->subs[SUB_THREEWAY].inthreeway &&
05381          p0->subs[SUB_REAL].owner &&
05382          p0->subs[SUB_REAL].inthreeway &&
05383          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05384          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05385          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05386          os0 = p0->subs[SUB_REAL].owner->_state;
05387       } else {
05388          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05389          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05390       }
05391       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05392          if (!p0->echocanbridged || !p1->echocanbridged) {
05393             /* Disable echo cancellation if appropriate */
05394             dahdi_disable_ec(p0);
05395             dahdi_disable_ec(p1);
05396          }
05397       }
05398       dahdi_link(slave, master);
05399       master->inconference = inconf;
05400    } else if (!nothingok)
05401       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05402 
05403    update_conf(p0);
05404    update_conf(p1);
05405    t0 = p0->subs[SUB_REAL].inthreeway;
05406    t1 = p1->subs[SUB_REAL].inthreeway;
05407 
05408    ast_mutex_unlock(&p0->lock);
05409    ast_mutex_unlock(&p1->lock);
05410 
05411    ast_channel_unlock(c0);
05412    ast_channel_unlock(c1);
05413 
05414    /* Native bridge failed */
05415    if ((!master || !slave) && !nothingok) {
05416       dahdi_enable_ec(p0);
05417       dahdi_enable_ec(p1);
05418       return AST_BRIDGE_FAILED;
05419    }
05420 
05421    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05422 
05423    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05424       disable_dtmf_detect(op0);
05425 
05426    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05427       disable_dtmf_detect(op1);
05428 
05429    for (;;) {
05430       struct ast_channel *c0_priority[2] = {c0, c1};
05431       struct ast_channel *c1_priority[2] = {c1, c0};
05432 
05433       /* Here's our main loop...  Start by locking things, looking for private parts,
05434          and then balking if anything is wrong */
05435 
05436       ast_channel_lock(c0);
05437       while (ast_channel_trylock(c1)) {
05438          CHANNEL_DEADLOCK_AVOIDANCE(c0);
05439       }
05440 
05441       p0 = c0->tech_pvt;
05442       p1 = c1->tech_pvt;
05443 
05444       if (op0 == p0)
05445          i0 = dahdi_get_index(c0, p0, 1);
05446       if (op1 == p1)
05447          i1 = dahdi_get_index(c1, p1, 1);
05448 
05449       ast_channel_unlock(c0);
05450       ast_channel_unlock(c1);
05451 
05452       if (!timeoutms ||
05453          (op0 != p0) ||
05454          (op1 != p1) ||
05455          (ofd0 != c0->fds[0]) ||
05456          (ofd1 != c1->fds[0]) ||
05457          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05458          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05459          (oc0 != p0->owner) ||
05460          (oc1 != p1->owner) ||
05461          (t0 != p0->subs[SUB_REAL].inthreeway) ||
05462          (t1 != p1->subs[SUB_REAL].inthreeway) ||
05463          (oi0 != i0) ||
05464          (oi1 != i1)) {
05465          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05466             op0->channel, oi0, op1->channel, oi1);
05467          res = AST_BRIDGE_RETRY;
05468          goto return_from_bridge;
05469       }
05470 
05471 #ifdef PRI_2BCT
05472       if (!triedtopribridge) {
05473          triedtopribridge = 1;
05474          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05475             ast_mutex_lock(&p0->pri->lock);
05476             if (p0->call && p1->call) {
05477                pri_channel_bridge(p0->call, p1->call);
05478             }
05479             ast_mutex_unlock(&p0->pri->lock);
05480          }
05481       }
05482 #endif
05483 
05484       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05485       if (!who) {
05486          ast_debug(1, "Ooh, empty read...\n");
05487          continue;
05488       }
05489       f = ast_read(who);
05490       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05491          *fo = f;
05492          *rc = who;
05493          res = AST_BRIDGE_COMPLETE;
05494          goto return_from_bridge;
05495       }
05496       if (f->frametype == AST_FRAME_DTMF) {
05497          if ((who == c0) && p0->pulsedial) {
05498             ast_write(c1, f);
05499          } else if ((who == c1) && p1->pulsedial) {
05500             ast_write(c0, f);
05501          } else {
05502             *fo = f;
05503             *rc = who;
05504             res = AST_BRIDGE_COMPLETE;
05505             goto return_from_bridge;
05506          }
05507       }
05508       ast_frfree(f);
05509 
05510       /* Swap who gets priority */
05511       priority = !priority;
05512    }
05513 
05514 return_from_bridge:
05515    if (op0 == p0)
05516       dahdi_enable_ec(p0);
05517 
05518    if (op1 == p1)
05519       dahdi_enable_ec(p1);
05520 
05521    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05522       enable_dtmf_detect(op0);
05523 
05524    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05525       enable_dtmf_detect(op1);
05526 
05527    dahdi_unlink(slave, master, 1);
05528 
05529    return res;
05530 }
05531 
05532 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05533 {
05534    struct dahdi_pvt *p = newchan->tech_pvt;
05535    int x;
05536    ast_mutex_lock(&p->lock);
05537    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05538    if (p->owner == oldchan) {
05539       p->owner = newchan;
05540    }
05541    for (x = 0; x < 3; x++)
05542       if (p->subs[x].owner == oldchan) {
05543          if (!x)
05544             dahdi_unlink(NULL, p, 0);
05545          p->subs[x].owner = newchan;
05546       }
05547    update_conf(p);
05548    ast_mutex_unlock(&p->lock);
05549    if (newchan->_state == AST_STATE_RINGING) {
05550       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05551    }
05552    return 0;
05553 }
05554 
05555 static int dahdi_ring_phone(struct dahdi_pvt *p)
05556 {
05557    int x;
05558    int res;
05559    /* Make sure our transmit state is on hook */
05560    x = 0;
05561    x = DAHDI_ONHOOK;
05562    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05563    do {
05564       x = DAHDI_RING;
05565       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05566       if (res) {
05567          switch (errno) {
05568          case EBUSY:
05569          case EINTR:
05570             /* Wait just in case */
05571             usleep(10000);
05572             continue;
05573          case EINPROGRESS:
05574             res = 0;
05575             break;
05576          default:
05577             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05578             res = 0;
05579          }
05580       }
05581    } while (res);
05582    return res;
05583 }
05584 
05585 static void *ss_thread(void *data);
05586 
05587 static int attempt_transfer(struct dahdi_pvt *p)
05588 {
05589    /* In order to transfer, we need at least one of the channels to
05590       actually be in a call bridge.  We can't conference two applications
05591       together (but then, why would we want to?) */
05592    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05593       /* The three-way person we're about to transfer to could still be in MOH, so
05594          stop if now if appropriate */
05595       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05596          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05597       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05598          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05599       }
05600       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05601          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05602       }
05603        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05604          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05605                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05606          return -1;
05607       }
05608       /* Orphan the channel after releasing the lock */
05609       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05610       unalloc_sub(p, SUB_THREEWAY);
05611    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05612       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05613       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05614          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05615       }
05616       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05617          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05618       }
05619       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05620          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05621                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05622          return -1;
05623       }
05624       /* Three-way is now the REAL */
05625       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05626       ast_channel_unlock(p->subs[SUB_REAL].owner);
05627       unalloc_sub(p, SUB_THREEWAY);
05628       /* Tell the caller not to hangup */
05629       return 1;
05630    } else {
05631       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05632          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05633       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05634       return -1;
05635    }
05636    return 0;
05637 }
05638 
05639 static int check_for_conference(struct dahdi_pvt *p)
05640 {
05641    struct dahdi_confinfo ci;
05642    /* Fine if we already have a master, etc */
05643    if (p->master || (p->confno > -1))
05644       return 0;
05645    memset(&ci, 0, sizeof(ci));
05646    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05647       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05648       return 0;
05649    }
05650    /* If we have no master and don't have a confno, then
05651       if we're in a conference, it's probably a MeetMe room or
05652       some such, so don't let us 3-way out! */
05653    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05654       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05655       return 1;
05656    }
05657    return 0;
05658 }
05659 
05660 /*! Checks channel for alarms
05661  * \param p a channel to check for alarms.
05662  * \returns the alarms on the span to which the channel belongs, or alarms on
05663  *          the channel if no span alarms.
05664  */
05665 static int get_alarms(struct dahdi_pvt *p)
05666 {
05667    int res;
05668    struct dahdi_spaninfo zi;
05669    struct dahdi_params params;
05670 
05671    memset(&zi, 0, sizeof(zi));
05672    zi.spanno = p->span;
05673 
05674    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05675       if (zi.alarms != DAHDI_ALARM_NONE)
05676          return zi.alarms;
05677    } else {
05678       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05679       return 0;
05680    }
05681 
05682    /* No alarms on the span. Check for channel alarms. */
05683    memset(&params, 0, sizeof(params));
05684    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05685       return params.chan_alarms;
05686 
05687    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05688 
05689    return DAHDI_ALARM_NONE;
05690 }
05691 
05692 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
05693 {
05694    struct dahdi_pvt *p = ast->tech_pvt;
05695    struct ast_frame *f = *dest;
05696 
05697    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05698 
05699    if (p->confirmanswer) {
05700       ast_debug(1, "Confirm answer on %s!\n", ast->name);
05701       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05702          of a DTMF digit */
05703       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05704       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05705       *dest = &p->subs[idx].f;
05706       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05707       p->confirmanswer = 0;
05708    } else if (p->callwaitcas) {
05709       if ((f->subclass == 'A') || (f->subclass == 'D')) {
05710          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05711          if (p->cidspill)
05712             ast_free(p->cidspill);
05713          send_cwcidspill(p);
05714       }
05715       p->callwaitcas = 0;
05716       p->subs[idx].f.frametype = AST_FRAME_NULL;
05717       p->subs[idx].f.subclass = 0;
05718       *dest = &p->subs[idx].f;
05719    } else if (f->subclass == 'f') {
05720       /* Fax tone -- Handle and return NULL */
05721       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05722          /* If faxbuffers are configured, use them for the fax transmission */
05723          if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05724             struct dahdi_bufferinfo bi = {
05725                .txbufpolicy = p->faxbuf_policy,
05726                .bufsize = p->bufsize,
05727                .numbufs = p->faxbuf_no
05728             };
05729             int res;
05730 
05731             if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05732                ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05733             } else {
05734                p->bufferoverrideinuse = 1;
05735             }
05736          }
05737          p->faxhandled = 1;
05738          if (strcmp(ast->exten, "fax")) {
05739             const char *target_context = S_OR(ast->macrocontext, ast->context);
05740 
05741             /* We need to unlock 'ast' here because ast_exists_extension has the
05742              * potential to start autoservice on the channel. Such action is prone
05743              * to deadlock.
05744              */
05745             ast_mutex_unlock(&p->lock);
05746             ast_channel_unlock(ast);
05747             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05748                ast_channel_lock(ast);
05749                ast_mutex_lock(&p->lock);
05750                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05751                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05752                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05753                if (ast_async_goto(ast, target_context, "fax", 1))
05754                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05755             } else {
05756                ast_channel_lock(ast);
05757                ast_mutex_lock(&p->lock);
05758                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05759             }
05760          } else {
05761             ast_debug(1, "Already in a fax extension, not redirecting\n");
05762          }
05763       } else {
05764          ast_debug(1, "Fax already handled\n");
05765       }
05766       dahdi_confmute(p, 0);
05767       p->subs[idx].f.frametype = AST_FRAME_NULL;
05768       p->subs[idx].f.subclass = 0;
05769       *dest = &p->subs[idx].f;
05770    }
05771 }
05772 
05773 static void handle_alarms(struct dahdi_pvt *p, int alms)
05774 {
05775    const char *alarm_str = alarm2str(alms);
05776 
05777    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05778    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05779       "Alarm: %s\r\n"
05780       "Channel: %d\r\n",
05781       alarm_str, p->channel);
05782 }
05783 
05784 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05785 {
05786    int res, x;
05787    int idx, mysig;
05788    char *c;
05789    struct dahdi_pvt *p = ast->tech_pvt;
05790    pthread_t threadid;
05791    struct ast_channel *chan;
05792    struct ast_frame *f;
05793 
05794    idx = dahdi_get_index(ast, p, 0);
05795    mysig = p->sig;
05796    if (p->outsigmod > -1)
05797       mysig = p->outsigmod;
05798    p->subs[idx].f.frametype = AST_FRAME_NULL;
05799    p->subs[idx].f.subclass = 0;
05800    p->subs[idx].f.datalen = 0;
05801    p->subs[idx].f.samples = 0;
05802    p->subs[idx].f.mallocd = 0;
05803    p->subs[idx].f.offset = 0;
05804    p->subs[idx].f.src = "dahdi_handle_event";
05805    p->subs[idx].f.data.ptr = NULL;
05806    f = &p->subs[idx].f;
05807 
05808    if (idx < 0)
05809       return &p->subs[idx].f;
05810    if (p->fake_event) {
05811       res = p->fake_event;
05812       p->fake_event = 0;
05813    } else
05814       res = dahdi_get_event(p->subs[idx].dfd);
05815 
05816    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05817 
05818    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05819       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05820       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05821 #ifdef HAVE_PRI
05822       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05823          /* absorb event */
05824       } else {
05825 #endif
05826          dahdi_confmute(p, 0);
05827          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05828          p->subs[idx].f.subclass = res & 0xff;
05829 #ifdef HAVE_PRI
05830       }
05831 #endif
05832       dahdi_handle_dtmfup(ast, idx, &f);
05833       return f;
05834    }
05835 
05836    if (res & DAHDI_EVENT_DTMFDOWN) {
05837       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05838       /* Mute conference */
05839       dahdi_confmute(p, 1);
05840       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05841       p->subs[idx].f.subclass = res & 0xff;
05842       return &p->subs[idx].f;
05843    }
05844 
05845    switch (res) {
05846       case DAHDI_EVENT_EC_DISABLED:
05847          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05848          p->echocanon = 0;
05849          break;
05850       case DAHDI_EVENT_BITSCHANGED:
05851 #ifdef HAVE_OPENR2
05852          if (p->sig != SIG_MFCR2) {
05853             ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05854          } else {
05855             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05856             openr2_chan_handle_cas(p->r2chan);
05857          }
05858 #else
05859          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05860 #endif
05861       case DAHDI_EVENT_PULSE_START:
05862          /* Stop tone if there's a pulse start and the PBX isn't started */
05863          if (!ast->pbx)
05864             tone_zone_play_tone(p->subs[idx].dfd, -1);
05865          break;
05866       case DAHDI_EVENT_DIALCOMPLETE:
05867 #ifdef HAVE_OPENR2
05868          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05869             /* we don't need to do anything for this event for R2 signaling
05870                if the call is being setup */
05871             break;
05872          }
05873 #endif
05874          if (p->inalarm) break;
05875          if ((p->radio || (p->oprmode < 0))) break;
05876          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05877             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05878             return NULL;
05879          }
05880          if (!x) { /* if not still dialing in driver */
05881             dahdi_enable_ec(p);
05882             if (p->echobreak) {
05883                dahdi_train_ec(p);
05884                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05885                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05886                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05887                p->echobreak = 0;
05888             } else {
05889                p->dialing = 0;
05890                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05891                   /* if thru with dialing after offhook */
05892                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05893                      ast_setstate(ast, AST_STATE_UP);
05894                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05895                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05896                      break;
05897                   } else { /* if to state wait for offhook to dial rest */
05898                      /* we now wait for off hook */
05899                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05900                   }
05901                }
05902                if (ast->_state == AST_STATE_DIALING) {
05903                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05904                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05905                   } else if (p->confirmanswer || (!p->dialednone
05906                      && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05907                         || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05908                         || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05909                         || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05910                         || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05911                         || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05912                         || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05913                         || (mysig == SIG_SF_FEATB)))) {
05914                      ast_setstate(ast, AST_STATE_RINGING);
05915                   } else if (!p->answeronpolarityswitch) {
05916                      ast_setstate(ast, AST_STATE_UP);
05917                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05918                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05919                      /* If aops=0 and hops=1, this is necessary */
05920                      p->polarity = POLARITY_REV;
05921                   } else {
05922                      /* Start clean, so we can catch the change to REV polarity when party answers */
05923                      p->polarity = POLARITY_IDLE;
05924                   }
05925                }
05926             }
05927          }
05928          break;
05929       case DAHDI_EVENT_ALARM:
05930 #ifdef HAVE_PRI
05931          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05932             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05933                /* T309 is not enabled : hangup calls when alarm occurs */
05934                if (p->call) {
05935                   if (p->pri && p->pri->pri) {
05936                      if (!pri_grab(p, p->pri)) {
05937                         pri_hangup(p->pri->pri, p->call, -1);
05938                         pri_destroycall(p->pri->pri, p->call);
05939                         p->call = NULL;
05940                         pri_rel(p->pri);
05941                      } else
05942                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05943                   } else
05944                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05945                }
05946                if (p->owner)
05947                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05948             }
05949          }
05950          if (p->bearer)
05951             p->bearer->inalarm = 1;
05952          else
05953 #endif
05954          p->inalarm = 1;
05955          res = get_alarms(p);
05956          handle_alarms(p, res);
05957 #ifdef HAVE_PRI
05958          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05959             /* fall through intentionally */
05960          } else {
05961             break;
05962          }
05963 #endif
05964 #ifdef HAVE_SS7
05965          if (p->sig == SIG_SS7)
05966             break;
05967 #endif
05968 #ifdef HAVE_OPENR2
05969          if (p->sig == SIG_MFCR2)
05970             break;
05971 #endif
05972       case DAHDI_EVENT_ONHOOK:
05973          if (p->radio) {
05974             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05975             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05976             break;
05977          }
05978          if (p->oprmode < 0)
05979          {
05980             if (p->oprmode != -1) break;
05981             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05982             {
05983                /* Make sure it starts ringing */
05984                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05985                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05986                save_conference(p->oprpeer);
05987                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05988             }
05989             break;
05990          }
05991          switch (p->sig) {
05992          case SIG_FXOLS:
05993          case SIG_FXOGS:
05994          case SIG_FXOKS:
05995             p->onhooktime = time(NULL);
05996             p->fxsoffhookstate = 0;
05997             p->msgstate = -1;
05998             /* Check for some special conditions regarding call waiting */
05999             if (idx == SUB_REAL) {
06000                /* The normal line was hung up */
06001                if (p->subs[SUB_CALLWAIT].owner) {
06002                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
06003                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06004                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06005                   unalloc_sub(p, SUB_CALLWAIT);
06006 #if 0
06007                   p->subs[idx].needanswer = 0;
06008                   p->subs[idx].needringing = 0;
06009 #endif
06010                   p->callwaitingrepeat = 0;
06011                   p->cidcwexpire = 0;
06012                   p->owner = NULL;
06013                   /* Don't start streaming audio yet if the incoming call isn't up yet */
06014                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06015                      p->dialing = 1;
06016                   dahdi_ring_phone(p);
06017                } else if (p->subs[SUB_THREEWAY].owner) {
06018                   unsigned int mssinceflash;
06019                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
06020                      the private structure -- not especially easy or clean */
06021                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
06022                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
06023                      DLA_UNLOCK(&p->lock);
06024                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
06025                      /* We can grab ast and p in that order, without worry.  We should make sure
06026                         nothing seriously bad has happened though like some sort of bizarre double
06027                         masquerade! */
06028                      DLA_LOCK(&p->lock);
06029                      if (p->owner != ast) {
06030                         ast_log(LOG_WARNING, "This isn't good...\n");
06031                         return NULL;
06032                      }
06033                   }
06034                   if (!p->subs[SUB_THREEWAY].owner) {
06035                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06036                      return NULL;
06037                   }
06038                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06039                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06040                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
06041                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on
06042                         hanging up.  Hangup both channels now */
06043                      if (p->subs[SUB_THREEWAY].owner)
06044                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06045                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06046                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06047                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06048                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06049                      if (p->transfer) {
06050                         /* In any case this isn't a threeway call anymore */
06051                         p->subs[SUB_REAL].inthreeway = 0;
06052                         p->subs[SUB_THREEWAY].inthreeway = 0;
06053                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
06054                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06055                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06056                            /* Swap subs and dis-own channel */
06057                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
06058                            p->owner = NULL;
06059                            /* Ring the phone */
06060                            dahdi_ring_phone(p);
06061                         } else {
06062                            if ((res = attempt_transfer(p)) < 0) {
06063                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06064                               if (p->subs[SUB_THREEWAY].owner)
06065                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06066                            } else if (res) {
06067                               /* Don't actually hang up at this point */
06068                               if (p->subs[SUB_THREEWAY].owner)
06069                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06070                               break;
06071                            }
06072                         }
06073                      } else {
06074                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06075                         if (p->subs[SUB_THREEWAY].owner)
06076                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06077                      }
06078                   } else {
06079                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06080                      /* Swap subs and dis-own channel */
06081                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06082                      p->owner = NULL;
06083                      /* Ring the phone */
06084                      dahdi_ring_phone(p);
06085                   }
06086                }
06087             } else {
06088                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06089             }
06090             /* Fall through */
06091          default:
06092             dahdi_disable_ec(p);
06093             return NULL;
06094          }
06095          break;
06096       case DAHDI_EVENT_RINGOFFHOOK:
06097          if (p->inalarm) break;
06098          if (p->oprmode < 0)
06099          {
06100             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06101             {
06102                /* Make sure it stops ringing */
06103                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06104                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06105                restore_conference(p->oprpeer);
06106             }
06107             break;
06108          }
06109          if (p->radio)
06110          {
06111             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06112             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06113             break;
06114          }
06115          /* for E911, its supposed to wait for offhook then dial
06116             the second half of the dial string */
06117          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06118             c = strchr(p->dialdest, '/');
06119             if (c)
06120                c++;
06121             else
06122                c = p->dialdest;
06123             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06124             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06125             if (strlen(p->dop.dialstr) > 4) {
06126                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06127                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06128                p->echorest[sizeof(p->echorest) - 1] = '\0';
06129                p->echobreak = 1;
06130                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06131             } else
06132                p->echobreak = 0;
06133             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06134                int saveerr = errno;
06135 
06136                x = DAHDI_ONHOOK;
06137                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06138                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06139                return NULL;
06140                }
06141             p->dialing = 1;
06142             return &p->subs[idx].f;
06143          }
06144          switch (p->sig) {
06145          case SIG_FXOLS:
06146          case SIG_FXOGS:
06147          case SIG_FXOKS:
06148             p->fxsoffhookstate = 1;
06149             switch (ast->_state) {
06150             case AST_STATE_RINGING:
06151                dahdi_enable_ec(p);
06152                dahdi_train_ec(p);
06153                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06154                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06155                /* Make sure it stops ringing */
06156                p->subs[SUB_REAL].needringing = 0;
06157                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06158                ast_debug(1, "channel %d answered\n", p->channel);
06159                if (p->cidspill) {
06160                   /* Cancel any running CallerID spill */
06161                   ast_free(p->cidspill);
06162                   p->cidspill = NULL;
06163                }
06164                p->dialing = 0;
06165                p->callwaitcas = 0;
06166                if (p->confirmanswer) {
06167                   /* Ignore answer if "confirm answer" is enabled */
06168                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06169                   p->subs[idx].f.subclass = 0;
06170                } else if (!ast_strlen_zero(p->dop.dialstr)) {
06171                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
06172                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06173                   if (res < 0) {
06174                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06175                      p->dop.dialstr[0] = '\0';
06176                      return NULL;
06177                   } else {
06178                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06179                      p->subs[idx].f.frametype = AST_FRAME_NULL;
06180                      p->subs[idx].f.subclass = 0;
06181                      p->dialing = 1;
06182                   }
06183                   p->dop.dialstr[0] = '\0';
06184                   ast_setstate(ast, AST_STATE_DIALING);
06185                } else
06186                   ast_setstate(ast, AST_STATE_UP);
06187                return &p->subs[idx].f;
06188             case AST_STATE_DOWN:
06189                ast_setstate(ast, AST_STATE_RING);
06190                ast->rings = 1;
06191                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06192                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06193                ast_debug(1, "channel %d picked up\n", p->channel);
06194                return &p->subs[idx].f;
06195             case AST_STATE_UP:
06196                /* Make sure it stops ringing */
06197                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06198                /* Okay -- probably call waiting*/
06199                if (ast_bridged_channel(p->owner))
06200                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06201                p->subs[idx].needunhold = 1;
06202                break;
06203             case AST_STATE_RESERVED:
06204                /* Start up dialtone */
06205                if (has_voicemail(p))
06206                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06207                else
06208                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06209                break;
06210             default:
06211                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06212             }
06213             break;
06214          case SIG_FXSLS:
06215          case SIG_FXSGS:
06216          case SIG_FXSKS:
06217             if (ast->_state == AST_STATE_RING) {
06218                p->ringt = p->ringt_base;
06219             }
06220 
06221             /* If we get a ring then we cannot be in
06222              * reversed polarity. So we reset to idle */
06223             ast_debug(1, "Setting IDLE polarity due "
06224                "to ring. Old polarity was %d\n",
06225                p->polarity);
06226             p->polarity = POLARITY_IDLE;
06227 
06228             /* Fall through */
06229          case SIG_EM:
06230          case SIG_EM_E1:
06231          case SIG_EMWINK:
06232          case SIG_FEATD:
06233          case SIG_FEATDMF:
06234          case SIG_FEATDMF_TA:
06235          case SIG_E911:
06236          case SIG_FGC_CAMA:
06237          case SIG_FGC_CAMAMF:
06238          case SIG_FEATB:
06239          case SIG_SF:
06240          case SIG_SFWINK:
06241          case SIG_SF_FEATD:
06242          case SIG_SF_FEATDMF:
06243          case SIG_SF_FEATB:
06244             if (ast->_state == AST_STATE_PRERING)
06245                ast_setstate(ast, AST_STATE_RING);
06246             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06247                ast_debug(1, "Ring detected\n");
06248                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06249                p->subs[idx].f.subclass = AST_CONTROL_RING;
06250             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06251                ast_debug(1, "Line answered\n");
06252                if (p->confirmanswer) {
06253                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06254                   p->subs[idx].f.subclass = 0;
06255                } else {
06256                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06257                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06258                   ast_setstate(ast, AST_STATE_UP);
06259                }
06260             } else if (ast->_state != AST_STATE_RING)
06261                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06262             break;
06263          default:
06264             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06265          }
06266          break;
06267       case DAHDI_EVENT_RINGBEGIN:
06268          switch (p->sig) {
06269          case SIG_FXSLS:
06270          case SIG_FXSGS:
06271          case SIG_FXSKS:
06272             if (ast->_state == AST_STATE_RING) {
06273                p->ringt = p->ringt_base;
06274             }
06275             break;
06276          }
06277          break;
06278       case DAHDI_EVENT_RINGEROFF:
06279          if (p->inalarm) break;
06280          if ((p->radio || (p->oprmode < 0))) break;
06281          ast->rings++;
06282          if ((ast->rings > p->cidrings) && (p->cidspill)) {
06283             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
06284             ast_free(p->cidspill);
06285             p->cidspill = NULL;
06286             p->callwaitcas = 0;
06287          }
06288          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06289          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06290          break;
06291       case DAHDI_EVENT_RINGERON:
06292          break;
06293       case DAHDI_EVENT_NOALARM:
06294          p->inalarm = 0;
06295 #ifdef HAVE_PRI
06296          /* Extremely unlikely but just in case */
06297          if (p->bearer)
06298             p->bearer->inalarm = 0;
06299 #endif
06300          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06301          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06302                         "Channel: %d\r\n", p->channel);
06303          break;
06304       case DAHDI_EVENT_WINKFLASH:
06305          if (p->inalarm) break;
06306          if (p->radio) break;
06307          if (p->oprmode < 0) break;
06308          if (p->oprmode > 1)
06309          {
06310             struct dahdi_params par;
06311 
06312             memset(&par, 0, sizeof(par));
06313             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06314             {
06315                if (!par.rxisoffhook)
06316                {
06317                   /* Make sure it stops ringing */
06318                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06319                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06320                   save_conference(p);
06321                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06322                }
06323             }
06324             break;
06325          }
06326          /* Remember last time we got a flash-hook */
06327          p->flashtime = ast_tvnow();
06328          switch (mysig) {
06329          case SIG_FXOLS:
06330          case SIG_FXOGS:
06331          case SIG_FXOKS:
06332             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06333                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06334             p->callwaitcas = 0;
06335 
06336             if (idx != SUB_REAL) {
06337                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06338                goto winkflashdone;
06339             }
06340 
06341             if (p->subs[SUB_CALLWAIT].owner) {
06342                /* Swap to call-wait */
06343                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06344                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06345                p->owner = p->subs[SUB_REAL].owner;
06346                ast_debug(1, "Making %s the new owner\n", p->owner->name);
06347                if (p->owner->_state == AST_STATE_RINGING) {
06348                   ast_setstate(p->owner, AST_STATE_UP);
06349                   p->subs[SUB_REAL].needanswer = 1;
06350                }
06351                p->callwaitingrepeat = 0;
06352                p->cidcwexpire = 0;
06353                /* Start music on hold if appropriate */
06354                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06355                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06356                      S_OR(p->mohsuggest, NULL),
06357                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06358                }
06359                p->subs[SUB_CALLWAIT].needhold = 1;
06360                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06361                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06362                      S_OR(p->mohsuggest, NULL),
06363                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06364                }
06365                p->subs[SUB_REAL].needunhold = 1;
06366             } else if (!p->subs[SUB_THREEWAY].owner) {
06367                if (!p->threewaycalling) {
06368                   /* Just send a flash if no 3-way calling */
06369                   p->subs[SUB_REAL].needflash = 1;
06370                   goto winkflashdone;
06371                } else if (!check_for_conference(p)) {
06372                   char cid_num[256];
06373                   char cid_name[256];
06374 
06375                   cid_num[0] = 0;
06376                   cid_name[0] = 0;
06377                   if (p->dahditrcallerid && p->owner) {
06378                      if (p->owner->cid.cid_num)
06379                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06380                      if (p->owner->cid.cid_name)
06381                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06382                   }
06383                   /* XXX This section needs much more error checking!!! XXX */
06384                   /* Start a 3-way call if feasible */
06385                   if (!((ast->pbx) ||
06386                      (ast->_state == AST_STATE_UP) ||
06387                      (ast->_state == AST_STATE_RING))) {
06388                      ast_debug(1, "Flash when call not up or ringing\n");
06389                      goto winkflashdone;
06390                   }
06391                   if (alloc_sub(p, SUB_THREEWAY)) {
06392                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06393                      goto winkflashdone;
06394                   }
06395                   /* Make new channel */
06396                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06397                   if (p->dahditrcallerid) {
06398                      if (!p->origcid_num)
06399                         p->origcid_num = ast_strdup(p->cid_num);
06400                      if (!p->origcid_name)
06401                         p->origcid_name = ast_strdup(p->cid_name);
06402                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06403                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06404                   }
06405                   /* Swap things around between the three-way and real call */
06406                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
06407                   /* Disable echo canceller for better dialing */
06408                   dahdi_disable_ec(p);
06409                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06410                   if (res)
06411                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06412                   p->owner = chan;
06413                   if (!chan) {
06414                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06415                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06416                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06417                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06418                      dahdi_enable_ec(p);
06419                      ast_hangup(chan);
06420                   } else {
06421                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06422                      int way3bridge = 0, cdr3way = 0;
06423 
06424                      if (!other) {
06425                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06426                      } else
06427                         way3bridge = 1;
06428 
06429                      if (p->subs[SUB_THREEWAY].owner->cdr)
06430                         cdr3way = 1;
06431 
06432                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
06433 
06434                      /* Start music on hold if appropriate */
06435                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06436                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06437                            S_OR(p->mohsuggest, NULL),
06438                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06439                      }
06440                      p->subs[SUB_THREEWAY].needhold = 1;
06441                   }
06442                }
06443             } else {
06444                /* Already have a 3 way call */
06445                if (p->subs[SUB_THREEWAY].inthreeway) {
06446                   /* Call is already up, drop the last person */
06447                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06448                   /* If the primary call isn't answered yet, use it */
06449                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06450                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
06451                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06452                      p->owner = p->subs[SUB_REAL].owner;
06453                   }
06454                   /* Drop the last call and stop the conference */
06455                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06456                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06457                   p->subs[SUB_REAL].inthreeway = 0;
06458                   p->subs[SUB_THREEWAY].inthreeway = 0;
06459                } else {
06460                   /* Lets see what we're up to */
06461                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06462                      (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06463                      int otherindex = SUB_THREEWAY;
06464                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06465                      int way3bridge = 0, cdr3way = 0;
06466 
06467                      if (!other) {
06468                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06469                      } else
06470                         way3bridge = 1;
06471 
06472                      if (p->subs[SUB_THREEWAY].owner->cdr)
06473                         cdr3way = 1;
06474 
06475                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06476                      /* Put them in the threeway, and flip */
06477                      p->subs[SUB_THREEWAY].inthreeway = 1;
06478                      p->subs[SUB_REAL].inthreeway = 1;
06479                      if (ast->_state == AST_STATE_UP) {
06480                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
06481                         otherindex = SUB_REAL;
06482                      }
06483                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06484                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06485                      p->subs[otherindex].needunhold = 1;
06486                      p->owner = p->subs[SUB_REAL].owner;
06487                      if (ast->_state == AST_STATE_RINGING) {
06488                         ast_debug(1, "Enabling ringtone on real and threeway\n");
06489                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06490                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06491                      }
06492                   } else {
06493                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06494                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06495                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06496                      p->owner = p->subs[SUB_REAL].owner;
06497                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06498                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06499                      p->subs[SUB_REAL].needunhold = 1;
06500                      dahdi_enable_ec(p);
06501                   }
06502                }
06503             }
06504 winkflashdone:
06505             update_conf(p);
06506             break;
06507          case SIG_EM:
06508          case SIG_EM_E1:
06509          case SIG_FEATD:
06510          case SIG_SF:
06511          case SIG_SFWINK:
06512          case SIG_SF_FEATD:
06513          case SIG_FXSLS:
06514          case SIG_FXSGS:
06515             if (option_debug) {
06516                if (p->dialing)
06517                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06518                else
06519                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06520             }
06521             break;
06522          case SIG_FEATDMF_TA:
06523             switch (p->whichwink) {
06524             case 0:
06525                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06526                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06527                break;
06528             case 1:
06529                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06530                break;
06531             case 2:
06532                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06533                return NULL;
06534             }
06535             p->whichwink++;
06536             /* Fall through */
06537          case SIG_FEATDMF:
06538          case SIG_E911:
06539          case SIG_FGC_CAMAMF:
06540          case SIG_FGC_CAMA:
06541          case SIG_FEATB:
06542          case SIG_SF_FEATDMF:
06543          case SIG_SF_FEATB:
06544          case SIG_EMWINK:
06545             /* FGD MF and EMWINK *Must* wait for wink */
06546             if (!ast_strlen_zero(p->dop.dialstr)) {
06547                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06548                if (res < 0) {
06549                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06550                   p->dop.dialstr[0] = '\0';
06551                   return NULL;
06552                } else
06553                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06554             }
06555             p->dop.dialstr[0] = '\0';
06556             break;
06557          default:
06558             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06559          }
06560          break;
06561       case DAHDI_EVENT_HOOKCOMPLETE:
06562          if (p->inalarm) break;
06563          if ((p->radio || (p->oprmode < 0))) break;
06564          if (p->waitingfordt.tv_sec) break;
06565          switch (mysig) {
06566          case SIG_FXSLS:  /* only interesting for FXS */
06567          case SIG_FXSGS:
06568          case SIG_FXSKS:
06569          case SIG_EM:
06570          case SIG_EM_E1:
06571          case SIG_EMWINK:
06572          case SIG_FEATD:
06573          case SIG_SF:
06574          case SIG_SFWINK:
06575          case SIG_SF_FEATD:
06576             if (!ast_strlen_zero(p->dop.dialstr)) {
06577                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06578                if (res < 0) {
06579                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06580                   p->dop.dialstr[0] = '\0';
06581                   return NULL;
06582                } else
06583                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06584             }
06585             p->dop.dialstr[0] = '\0';
06586             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06587             break;
06588          case SIG_FEATDMF:
06589          case SIG_FEATDMF_TA:
06590          case SIG_E911:
06591          case SIG_FGC_CAMA:
06592          case SIG_FGC_CAMAMF:
06593          case SIG_FEATB:
06594          case SIG_SF_FEATDMF:
06595          case SIG_SF_FEATB:
06596             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06597             break;
06598          default:
06599             break;
06600          }
06601          break;
06602       case DAHDI_EVENT_POLARITY:
06603          /*
06604           * If we get a Polarity Switch event, this could be
06605           * due to line seizure, remote end connect or remote end disconnect.
06606           *
06607           * Check to see if we should change the polarity state and
06608           * mark the channel as UP or if this is an indication
06609           * of remote end disconnect.
06610           */
06611 
06612          if (p->polarityonanswerdelay > 0) {
06613             /* check if event is not too soon after OffHook or Answer */
06614             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06615                switch (ast->_state) {
06616                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06617                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06618                   if (p->answeronpolarityswitch) {
06619                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06620                      ast_setstate(p->owner, AST_STATE_UP);
06621                      p->polarity = POLARITY_REV;
06622                      if (p->hanguponpolarityswitch) {
06623                         p->polaritydelaytv = ast_tvnow();
06624                      }
06625                   } else {
06626                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06627                   }
06628                   break;
06629 
06630                case AST_STATE_UP:         /*!< Line is up */
06631                case AST_STATE_RING:       /*!< Line is ringing */
06632                   if (p->hanguponpolarityswitch) {
06633                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06634                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06635                      p->polarity = POLARITY_IDLE;
06636                   } else {
06637                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06638                   }
06639                   break;
06640 
06641                case AST_STATE_DOWN:       /*!< Channel is down and available */
06642                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
06643                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
06644                case AST_STATE_BUSY:       /*!< Line is busy */
06645                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
06646                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
06647                default:
06648                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06649                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06650                   }
06651                }
06652 
06653             } else {
06654                /* event is too soon after OffHook or Answer */
06655                switch (ast->_state) {
06656                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06657                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06658                   if (p->answeronpolarityswitch) {
06659                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06660                   }
06661                   break;
06662 
06663                case AST_STATE_UP:         /*!< Line is up */
06664                case AST_STATE_RING:       /*!< Line is ringing */
06665                   if (p->hanguponpolarityswitch) {
06666                      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);
06667                   }
06668                   break;
06669 
06670                default: 
06671                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06672                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06673                   }
06674                }
06675             }
06676          }
06677 
06678          /* Added more log_debug information below to provide a better indication of what is going on */
06679          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) );
06680          break;
06681       default:
06682          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06683    }
06684    return &p->subs[idx].f;
06685 }
06686 
06687 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06688 {
06689    struct dahdi_pvt *p = ast->tech_pvt;
06690    int res;
06691    int usedindex=-1;
06692    int idx;
06693    struct ast_frame *f;
06694 
06695 
06696    idx = dahdi_get_index(ast, p, 1);
06697 
06698    p->subs[idx].f.frametype = AST_FRAME_NULL;
06699    p->subs[idx].f.datalen = 0;
06700    p->subs[idx].f.samples = 0;
06701    p->subs[idx].f.mallocd = 0;
06702    p->subs[idx].f.offset = 0;
06703    p->subs[idx].f.subclass = 0;
06704    p->subs[idx].f.delivery = ast_tv(0,0);
06705    p->subs[idx].f.src = "dahdi_exception";
06706    p->subs[idx].f.data.ptr = NULL;
06707 
06708 
06709    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06710       /* If nobody owns us, absorb the event appropriately, otherwise
06711          we loop indefinitely.  This occurs when, during call waiting, the
06712          other end hangs up our channel so that it no longer exists, but we
06713          have neither FLASH'd nor ONHOOK'd to signify our desire to
06714          change to the other channel. */
06715       if (p->fake_event) {
06716          res = p->fake_event;
06717          p->fake_event = 0;
06718       } else
06719          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06720       /* Switch to real if there is one and this isn't something really silly... */
06721       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06722          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06723          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06724          p->owner = p->subs[SUB_REAL].owner;
06725          if (p->owner && ast_bridged_channel(p->owner))
06726             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06727          p->subs[SUB_REAL].needunhold = 1;
06728       }
06729       switch (res) {
06730       case DAHDI_EVENT_ONHOOK:
06731          dahdi_disable_ec(p);
06732          if (p->owner) {
06733             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06734             dahdi_ring_phone(p);
06735             p->callwaitingrepeat = 0;
06736             p->cidcwexpire = 0;
06737          } else
06738             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06739          update_conf(p);
06740          break;
06741       case DAHDI_EVENT_RINGOFFHOOK:
06742          dahdi_enable_ec(p);
06743          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06744          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06745             p->subs[SUB_REAL].needanswer = 1;
06746             p->dialing = 0;
06747          }
06748          break;
06749       case DAHDI_EVENT_HOOKCOMPLETE:
06750       case DAHDI_EVENT_RINGERON:
06751       case DAHDI_EVENT_RINGEROFF:
06752          /* Do nothing */
06753          break;
06754       case DAHDI_EVENT_WINKFLASH:
06755          p->flashtime = ast_tvnow();
06756          if (p->owner) {
06757             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06758             if (p->owner->_state != AST_STATE_UP) {
06759                /* Answer if necessary */
06760                usedindex = dahdi_get_index(p->owner, p, 0);
06761                if (usedindex > -1) {
06762                   p->subs[usedindex].needanswer = 1;
06763                }
06764                ast_setstate(p->owner, AST_STATE_UP);
06765             }
06766             p->callwaitingrepeat = 0;
06767             p->cidcwexpire = 0;
06768             if (ast_bridged_channel(p->owner))
06769                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06770             p->subs[SUB_REAL].needunhold = 1;
06771          } else
06772             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06773          update_conf(p);
06774          break;
06775       default:
06776          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06777       }
06778       f = &p->subs[idx].f;
06779       return f;
06780    }
06781    if (!(p->radio || (p->oprmode < 0)))
06782       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06783    /* If it's not us, return NULL immediately */
06784    if (ast != p->owner) {
06785       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06786       f = &p->subs[idx].f;
06787       return f;
06788    }
06789    f = dahdi_handle_event(ast);
06790    return f;
06791 }
06792 
06793 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06794 {
06795    struct dahdi_pvt *p = ast->tech_pvt;
06796    struct ast_frame *f;
06797    ast_mutex_lock(&p->lock);
06798    f = __dahdi_exception(ast);
06799    ast_mutex_unlock(&p->lock);
06800    return f;
06801 }
06802 
06803 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06804 {
06805    struct dahdi_pvt *p = ast->tech_pvt;
06806    int res;
06807    int idx;
06808    void *readbuf;
06809    struct ast_frame *f;
06810 
06811    while (ast_mutex_trylock(&p->lock)) {
06812       CHANNEL_DEADLOCK_AVOIDANCE(ast);
06813    }
06814 
06815    idx = dahdi_get_index(ast, p, 0);
06816 
06817    /* Hang up if we don't really exist */
06818    if (idx < 0)   {
06819       ast_log(LOG_WARNING, "We don't exist?\n");
06820       ast_mutex_unlock(&p->lock);
06821       return NULL;
06822    }
06823 
06824    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06825       ast_mutex_unlock(&p->lock);
06826       return NULL;
06827    }
06828 
06829    p->subs[idx].f.frametype = AST_FRAME_NULL;
06830    p->subs[idx].f.datalen = 0;
06831    p->subs[idx].f.samples = 0;
06832    p->subs[idx].f.mallocd = 0;
06833    p->subs[idx].f.offset = 0;
06834    p->subs[idx].f.subclass = 0;
06835    p->subs[idx].f.delivery = ast_tv(0,0);
06836    p->subs[idx].f.src = "dahdi_read";
06837    p->subs[idx].f.data.ptr = NULL;
06838 
06839    /* make sure it sends initial key state as first frame */
06840    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06841    {
06842       struct dahdi_params ps;
06843 
06844       memset(&ps, 0, sizeof(ps));
06845       ps.channo = p->channel;
06846       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06847          ast_mutex_unlock(&p->lock);
06848          return NULL;
06849       }
06850       p->firstradio = 1;
06851       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06852       if (ps.rxisoffhook)
06853       {
06854          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06855       }
06856       else
06857       {
06858          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06859       }
06860       ast_mutex_unlock(&p->lock);
06861       return &p->subs[idx].f;
06862    }
06863    if (p->ringt == 1) {
06864       ast_mutex_unlock(&p->lock);
06865       return NULL;
06866    }
06867    else if (p->ringt > 0)
06868       p->ringt--;
06869 
06870 #ifdef HAVE_OPENR2
06871    if (p->mfcr2) {
06872       openr2_chan_process_event(p->r2chan);
06873    }
06874 #endif
06875 
06876    if (p->subs[idx].needringing) {
06877       /* Send ringing frame if requested */
06878       p->subs[idx].needringing = 0;
06879       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06880       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06881       ast_setstate(ast, AST_STATE_RINGING);
06882       ast_mutex_unlock(&p->lock);
06883       return &p->subs[idx].f;
06884    }
06885 
06886    if (p->subs[idx].needbusy) {
06887       /* Send busy frame if requested */
06888       p->subs[idx].needbusy = 0;
06889       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06890       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06891       ast_mutex_unlock(&p->lock);
06892       return &p->subs[idx].f;
06893    }
06894 
06895    if (p->subs[idx].needcongestion) {
06896       /* Send congestion frame if requested */
06897       p->subs[idx].needcongestion = 0;
06898       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06899       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06900       ast_mutex_unlock(&p->lock);
06901       return &p->subs[idx].f;
06902    }
06903 
06904    if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
06905       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06906                      S_OR(p->lastcid_name, NULL),
06907                      S_OR(p->lastcid_num, NULL)
06908                      );
06909       p->subs[idx].needcallerid = 0;
06910    }
06911 
06912    if (p->subs[idx].needanswer) {
06913       /* Send answer frame if requested */
06914       p->subs[idx].needanswer = 0;
06915       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06916       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06917       ast_mutex_unlock(&p->lock);
06918       return &p->subs[idx].f;
06919    }
06920 #ifdef HAVE_OPENR2
06921    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06922       /* openr2 took care of reading and handling any event
06923         (needanswer, needbusy etc), if we continue we will read()
06924         twice, lets just return a null frame. This should only
06925         happen when openr2 is dialing out */
06926       ast_mutex_unlock(&p->lock);
06927       return &ast_null_frame;
06928    }
06929 #endif
06930 
06931    if (p->subs[idx].needflash) {
06932       /* Send answer frame if requested */
06933       p->subs[idx].needflash = 0;
06934       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06935       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06936       ast_mutex_unlock(&p->lock);
06937       return &p->subs[idx].f;
06938    }
06939 
06940    if (p->subs[idx].needhold) {
06941       /* Send answer frame if requested */
06942       p->subs[idx].needhold = 0;
06943       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06944       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06945       ast_mutex_unlock(&p->lock);
06946       ast_debug(1, "Sending hold on '%s'\n", ast->name);
06947       return &p->subs[idx].f;
06948    }
06949 
06950    if (p->subs[idx].needunhold) {
06951       /* Send answer frame if requested */
06952       p->subs[idx].needunhold = 0;
06953       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06954       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06955       ast_mutex_unlock(&p->lock);
06956       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06957       return &p->subs[idx].f;
06958    }
06959 
06960    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06961       if (!p->subs[idx].linear) {
06962          p->subs[idx].linear = 1;
06963          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06964          if (res)
06965             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06966       }
06967    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06968       (ast->rawreadformat == AST_FORMAT_ALAW)) {
06969       if (p->subs[idx].linear) {
06970          p->subs[idx].linear = 0;
06971          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06972          if (res)
06973             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06974       }
06975    } else {
06976       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06977       ast_mutex_unlock(&p->lock);
06978       return NULL;
06979    }
06980    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06981    CHECK_BLOCKING(ast);
06982    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06983    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06984    /* Check for hangup */
06985    if (res < 0) {
06986       f = NULL;
06987       if (res == -1) {
06988          if (errno == EAGAIN) {
06989             /* Return "NULL" frame if there is nobody there */
06990             ast_mutex_unlock(&p->lock);
06991             return &p->subs[idx].f;
06992          } else if (errno == ELAST) {
06993             f = __dahdi_exception(ast);
06994          } else
06995             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06996       }
06997       ast_mutex_unlock(&p->lock);
06998       return f;
06999    }
07000    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07001       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07002       f = __dahdi_exception(ast);
07003       ast_mutex_unlock(&p->lock);
07004       return f;
07005    }
07006    if (p->tdd) { /* if in TDD mode, see if we receive that */
07007       int c;
07008 
07009       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07010       if (c < 0) {
07011          ast_debug(1,"tdd_feed failed\n");
07012          ast_mutex_unlock(&p->lock);
07013          return NULL;
07014       }
07015       if (c) { /* if a char to return */
07016          p->subs[idx].f.subclass = 0;
07017          p->subs[idx].f.frametype = AST_FRAME_TEXT;
07018          p->subs[idx].f.mallocd = 0;
07019          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07020          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07021          p->subs[idx].f.datalen = 1;
07022          *((char *) p->subs[idx].f.data.ptr) = c;
07023          ast_mutex_unlock(&p->lock);
07024          return &p->subs[idx].f;
07025       }
07026    }
07027    /* Ensure the CW timer decrements only on a single subchannel */
07028    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
07029       p->callwaitingrepeat--;
07030    }
07031    if (p->cidcwexpire)
07032       p->cidcwexpire--;
07033    /* Repeat callwaiting */
07034    if (p->callwaitingrepeat == 1) {
07035       p->callwaitrings++;
07036       dahdi_callwait(ast);
07037    }
07038    /* Expire CID/CW */
07039    if (p->cidcwexpire == 1) {
07040       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07041       restore_conference(p);
07042    }
07043    if (p->subs[idx].linear) {
07044       p->subs[idx].f.datalen = READ_SIZE * 2;
07045    } else
07046       p->subs[idx].f.datalen = READ_SIZE;
07047 
07048    /* Handle CallerID Transmission */
07049    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07050       send_callerid(p);
07051    }
07052 
07053    p->subs[idx].f.frametype = AST_FRAME_VOICE;
07054    p->subs[idx].f.subclass = ast->rawreadformat;
07055    p->subs[idx].f.samples = READ_SIZE;
07056    p->subs[idx].f.mallocd = 0;
07057    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07058    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07059 #if 0
07060    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07061 #endif
07062    if (p->dialing || /* Transmitting something */
07063       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
07064       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
07065       ) {
07066       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
07067          don't send anything */
07068       p->subs[idx].f.frametype = AST_FRAME_NULL;
07069       p->subs[idx].f.subclass = 0;
07070       p->subs[idx].f.samples = 0;
07071       p->subs[idx].f.mallocd = 0;
07072       p->subs[idx].f.offset = 0;
07073       p->subs[idx].f.data.ptr = NULL;
07074       p->subs[idx].f.datalen= 0;
07075    }
07076    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07077       /* Perform busy detection etc on the dahdi line */
07078       int mute;
07079 
07080       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07081 
07082       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
07083       mute = ast_dsp_was_muted(p->dsp);
07084       if (p->muting != mute) {
07085          p->muting = mute;
07086          dahdi_confmute(p, mute);
07087       }
07088 
07089       if (f) {
07090          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07091             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07092                /* Treat this as a "hangup" instead of a "busy" on the assumption that
07093                   a busy */
07094                f = NULL;
07095             }
07096          } else if (f->frametype == AST_FRAME_DTMF) {
07097 #ifdef HAVE_PRI
07098             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07099                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07100                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07101                /* Don't accept in-band DTMF when in overlap dial mode */
07102                f->frametype = AST_FRAME_NULL;
07103                f->subclass = 0;
07104             }
07105 #endif
07106             /* DSP clears us of being pulse */
07107             p->pulsedial = 0;
07108          } else if (p->waitingfordt.tv_sec) {
07109             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07110                p->waitingfordt.tv_sec = 0;
07111                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07112                f=NULL;
07113             } else if (f->frametype == AST_FRAME_VOICE) {
07114                f->frametype = AST_FRAME_NULL;
07115                f->subclass = 0;
07116                if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
07117                   p->waitingfordt.tv_sec = 0;
07118                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07119                   ast_dsp_set_features(p->dsp, p->dsp_features);
07120                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07121                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
07122                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07123                      if (res < 0) {
07124                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07125                         p->dop.dialstr[0] = '\0';
07126                         ast_mutex_unlock(&p->lock);
07127                         return NULL;
07128                      } else {
07129                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07130                         p->dialing = 1;
07131                         p->dop.dialstr[0] = '\0';
07132                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
07133                         ast_setstate(ast, AST_STATE_DIALING);
07134                      }
07135                   }
07136                }
07137             }
07138          }
07139       }
07140    } else
07141       f = &p->subs[idx].f;
07142 
07143    if (f && (f->frametype == AST_FRAME_DTMF))
07144       dahdi_handle_dtmfup(ast, idx, &f);
07145 
07146    /* If we have a fake_event, trigger exception to handle it */
07147    if (p->fake_event)
07148       ast_set_flag(ast, AST_FLAG_EXCEPTION);
07149 
07150    ast_mutex_unlock(&p->lock);
07151    return f;
07152 }
07153 
07154 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07155 {
07156    int sent=0;
07157    int size;
07158    int res;
07159    int fd;
07160    fd = p->subs[idx].dfd;
07161    while (len) {
07162       size = len;
07163       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07164          size = (linear ? READ_SIZE * 2 : READ_SIZE);
07165       res = write(fd, buf, size);
07166       if (res != size) {
07167          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07168          return sent;
07169       }
07170       len -= size;
07171       buf += size;
07172    }
07173    return sent;
07174 }
07175 
07176 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07177 {
07178    struct dahdi_pvt *p = ast->tech_pvt;
07179    int res;
07180    int idx;
07181    idx = dahdi_get_index(ast, p, 0);
07182    if (idx < 0) {
07183       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07184       return -1;
07185    }
07186 
07187 #if 0
07188 #ifdef HAVE_PRI
07189    ast_mutex_lock(&p->lock);
07190    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07191       if (p->pri->pri) {
07192          if (!pri_grab(p, p->pri)) {
07193                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07194                pri_rel(p->pri);
07195          } else
07196                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07197       }
07198       p->proceeding=1;
07199    }
07200    ast_mutex_unlock(&p->lock);
07201 #endif
07202 #endif
07203    /* Write a frame of (presumably voice) data */
07204    if (frame->frametype != AST_FRAME_VOICE) {
07205       if (frame->frametype != AST_FRAME_IMAGE)
07206          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07207       return 0;
07208    }
07209    if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07210       (frame->subclass != AST_FORMAT_ULAW) &&
07211       (frame->subclass != AST_FORMAT_ALAW)) {
07212       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07213       return -1;
07214    }
07215    if (p->dialing) {
07216       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07217       return 0;
07218    }
07219    if (!p->owner) {
07220       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07221       return 0;
07222    }
07223    if (p->cidspill) {
07224       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07225       return 0;
07226    }
07227    /* Return if it's not valid data */
07228    if (!frame->data.ptr || !frame->datalen)
07229       return 0;
07230 
07231    if (frame->subclass == AST_FORMAT_SLINEAR) {
07232       if (!p->subs[idx].linear) {
07233          p->subs[idx].linear = 1;
07234          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07235          if (res)
07236             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07237       }
07238       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07239    } else {
07240       /* x-law already */
07241       if (p->subs[idx].linear) {
07242          p->subs[idx].linear = 0;
07243          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07244          if (res)
07245             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07246       }
07247       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07248    }
07249    if (res < 0) {
07250       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07251       return -1;
07252    }
07253    return 0;
07254 }
07255 
07256 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07257 {
07258    struct dahdi_pvt *p = chan->tech_pvt;
07259    int res=-1;
07260    int idx;
07261    int func = DAHDI_FLASH;
07262    ast_mutex_lock(&p->lock);
07263    idx = dahdi_get_index(chan, p, 0);
07264    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07265 #ifdef HAVE_OPENR2
07266    if (p->mfcr2 && !p->mfcr2_call_accepted) {
07267       ast_mutex_unlock(&p->lock);
07268       /* if this is an R2 call and the call is not yet accepted, we don't want the
07269          tone indications to mess up with the MF tones */
07270       return 0;
07271    }
07272 #endif
07273    if (idx == SUB_REAL) {
07274       switch (condition) {
07275       case AST_CONTROL_BUSY:
07276 #ifdef HAVE_PRI
07277          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07278             chan->hangupcause = AST_CAUSE_USER_BUSY;
07279             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07280             res = 0;
07281          } else if (!p->progress &&
07282                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07283                && p->pri && !p->outgoing) {
07284             if (p->pri->pri) {
07285                if (!pri_grab(p, p->pri)) {
07286 #ifdef HAVE_PRI_PROG_W_CAUSE
07287                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
07288 #else
07289                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07290 #endif
07291                   pri_rel(p->pri);
07292                }
07293                else
07294                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07295             }
07296             p->progress = 1;
07297             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07298          } else
07299 #endif
07300             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07301          break;
07302       case AST_CONTROL_RINGING:
07303 #ifdef HAVE_PRI
07304          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07305                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07306             if (p->pri->pri) {
07307                if (!pri_grab(p, p->pri)) {
07308                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07309                   pri_rel(p->pri);
07310                }
07311                else
07312                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07313             }
07314             p->alerting = 1;
07315          }
07316 
07317 #endif
07318 #ifdef HAVE_SS7
07319          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07320             if (p->ss7->ss7) {
07321                ss7_grab(p, p->ss7);
07322 
07323                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07324                   p->rlt = 1;
07325                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
07326                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07327                p->alerting = 1;
07328                ss7_rel(p->ss7);
07329             }
07330          }
07331 #endif
07332 
07333          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07334 
07335          if (chan->_state != AST_STATE_UP) {
07336             if ((chan->_state != AST_STATE_RING) ||
07337                ((p->sig != SIG_FXSKS) &&
07338              (p->sig != SIG_FXSLS) &&
07339              (p->sig != SIG_FXSGS)))
07340             ast_setstate(chan, AST_STATE_RINGING);
07341          }
07342          break;
07343       case AST_CONTROL_PROCEEDING:
07344          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07345 #ifdef HAVE_PRI
07346          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07347                && p->pri && !p->outgoing) {
07348             if (p->pri->pri) {
07349                if (!pri_grab(p, p->pri)) {
07350                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07351                   pri_rel(p->pri);
07352                }
07353                else
07354                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07355             }
07356             p->proceeding = 1;
07357             p->dialing = 0;
07358          }
07359 #endif
07360 #ifdef HAVE_SS7
07361          /* This IF sends the FAR for an answered ALEG call */
07362          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07363             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07364                p->rlt = 1;
07365          }
07366 
07367          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07368             if (p->ss7->ss7) {
07369                ss7_grab(p, p->ss7);
07370                isup_acm(p->ss7->ss7, p->ss7call);
07371                p->proceeding = 1;
07372                ss7_rel(p->ss7);
07373 
07374             }
07375          }
07376 #endif
07377          /* don't continue in ast_indicate */
07378          res = 0;
07379          break;
07380       case AST_CONTROL_PROGRESS:
07381          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07382 #ifdef HAVE_PRI
07383          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
07384          if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07385                && p->pri && !p->outgoing) {
07386             if (p->pri->pri) {
07387                if (!pri_grab(p, p->pri)) {
07388 #ifdef HAVE_PRI_PROG_W_CAUSE
07389                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07390 #else
07391                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07392 #endif
07393                   pri_rel(p->pri);
07394                }
07395                else
07396                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07397             }
07398             p->progress = 1;
07399          }
07400 #endif
07401 #ifdef HAVE_SS7
07402          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07403             if (p->ss7->ss7) {
07404                ss7_grab(p, p->ss7);
07405                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07406                p->progress = 1;
07407                ss7_rel(p->ss7);
07408                /* enable echo canceler here on SS7 calls */
07409                dahdi_enable_ec(p);
07410 
07411             }
07412          }
07413 #endif
07414          /* don't continue in ast_indicate */
07415          res = 0;
07416          break;
07417       case AST_CONTROL_CONGESTION:
07418          chan->hangupcause = AST_CAUSE_CONGESTION;
07419 #ifdef HAVE_PRI
07420          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07421             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07422             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07423             res = 0;
07424          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07425                && p->pri && !p->outgoing) {
07426             if (p->pri) {
07427                if (!pri_grab(p, p->pri)) {
07428 #ifdef HAVE_PRI_PROG_W_CAUSE
07429                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
07430 #else
07431                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07432 #endif
07433                   pri_rel(p->pri);
07434                } else
07435                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07436             }
07437             p->progress = 1;
07438             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07439          } else
07440 #endif
07441             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07442          break;
07443       case AST_CONTROL_HOLD:
07444 #ifdef HAVE_PRI
07445          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07446             if (!pri_grab(p, p->pri)) {
07447                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07448                pri_rel(p->pri);
07449             } else
07450                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07451          } else
07452 #endif
07453             ast_moh_start(chan, data, p->mohinterpret);
07454          break;
07455       case AST_CONTROL_UNHOLD:
07456 #ifdef HAVE_PRI
07457          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07458             if (!pri_grab(p, p->pri)) {
07459                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07460                pri_rel(p->pri);
07461             } else
07462                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07463          } else
07464 #endif
07465             ast_moh_stop(chan);
07466          break;
07467       case AST_CONTROL_RADIO_KEY:
07468          if (p->radio)
07469             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07470          res = 0;
07471          break;
07472       case AST_CONTROL_RADIO_UNKEY:
07473          if (p->radio)
07474             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07475          res = 0;
07476          break;
07477       case AST_CONTROL_FLASH:
07478          /* flash hookswitch */
07479          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07480             /* Clear out the dial buffer */
07481             p->dop.dialstr[0] = '\0';
07482             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07483                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07484                   chan->name, strerror(errno));
07485             } else
07486                res = 0;
07487          } else
07488             res = 0;
07489          break;
07490       case AST_CONTROL_SRCUPDATE:
07491          res = 0;
07492          break;
07493       case -1:
07494          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07495          break;
07496       }
07497    } else
07498       res = 0;
07499    ast_mutex_unlock(&p->lock);
07500    return res;
07501 }
07502 
07503 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07504 {
07505    struct ast_channel *tmp;
07506    int deflaw;
07507    int res;
07508    int x,y;
07509    int features;
07510    struct ast_str *chan_name;
07511    struct ast_variable *v;
07512    struct dahdi_params ps;
07513    if (i->subs[idx].owner) {
07514       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07515       return NULL;
07516    }
07517    y = 1;
07518    chan_name = ast_str_alloca(32);
07519    do {
07520 #ifdef HAVE_PRI
07521       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07522          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07523       else
07524 #endif
07525       if (i->channel == CHAN_PSEUDO)
07526          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07527       else
07528          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07529       for (x = 0; x < 3; x++) {
07530          if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07531             break;
07532       }
07533       y++;
07534    } while (x < 3);
07535    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
07536    if (!tmp)
07537       return NULL;
07538    tmp->tech = &dahdi_tech;
07539    memset(&ps, 0, sizeof(ps));
07540    ps.channo = i->channel;
07541    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07542    if (res) {
07543       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07544       ps.curlaw = DAHDI_LAW_MULAW;
07545    }
07546    if (ps.curlaw == DAHDI_LAW_ALAW)
07547       deflaw = AST_FORMAT_ALAW;
07548    else
07549       deflaw = AST_FORMAT_ULAW;
07550    if (law) {
07551       if (law == DAHDI_LAW_ALAW)
07552          deflaw = AST_FORMAT_ALAW;
07553       else
07554          deflaw = AST_FORMAT_ULAW;
07555    }
07556    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07557    tmp->nativeformats = deflaw;
07558    /* Start out assuming ulaw since it's smaller :) */
07559    tmp->rawreadformat = deflaw;
07560    tmp->readformat = deflaw;
07561    tmp->rawwriteformat = deflaw;
07562    tmp->writeformat = deflaw;
07563    i->subs[idx].linear = 0;
07564    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07565    features = 0;
07566    if (idx == SUB_REAL) {
07567       if (i->busydetect && CANBUSYDETECT(i))
07568          features |= DSP_FEATURE_BUSY_DETECT;
07569       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07570          features |= DSP_FEATURE_CALL_PROGRESS;
07571       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07572          features |= DSP_FEATURE_WAITDIALTONE;
07573       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07574          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07575          features |= DSP_FEATURE_FAX_DETECT;
07576       }
07577       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07578       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07579          i->hardwaredtmf = 0;
07580          features |= DSP_FEATURE_DIGIT_DETECT;
07581       } else if (NEED_MFDETECT(i)) {
07582          i->hardwaredtmf = 1;
07583          features |= DSP_FEATURE_DIGIT_DETECT;
07584       }
07585    }
07586    if (features) {
07587       if (i->dsp) {
07588          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07589       } else {
07590          if (i->channel != CHAN_PSEUDO)
07591             i->dsp = ast_dsp_new();
07592          else
07593             i->dsp = NULL;
07594          if (i->dsp) {
07595             i->dsp_features = features;
07596 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07597             /* We cannot do progress detection until receives PROGRESS message */
07598             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07599                /* Remember requested DSP features, don't treat
07600                   talking as ANSWER */
07601                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07602                features = 0;
07603             }
07604 #endif
07605             ast_dsp_set_features(i->dsp, features);
07606             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07607             if (!ast_strlen_zero(progzone))
07608                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07609             if (i->busydetect && CANBUSYDETECT(i)) {
07610                ast_dsp_set_busy_count(i->dsp, i->busycount);
07611                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07612             }
07613          }
07614       }
07615    }
07616 
07617    if (state == AST_STATE_RING)
07618       tmp->rings = 1;
07619    tmp->tech_pvt = i;
07620    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07621       /* Only FXO signalled stuff can be picked up */
07622       tmp->callgroup = i->callgroup;
07623       tmp->pickupgroup = i->pickupgroup;
07624    }
07625    if (!ast_strlen_zero(i->parkinglot))
07626       ast_string_field_set(tmp, parkinglot, i->parkinglot);
07627    if (!ast_strlen_zero(i->language))
07628       ast_string_field_set(tmp, language, i->language);
07629    if (!i->owner)
07630       i->owner = tmp;
07631    if (!ast_strlen_zero(i->accountcode))
07632       ast_string_field_set(tmp, accountcode, i->accountcode);
07633    if (i->amaflags)
07634       tmp->amaflags = i->amaflags;
07635    i->subs[idx].owner = tmp;
07636    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07637    ast_string_field_set(tmp, call_forward, i->call_forward);
07638    /* If we've been told "no ADSI" then enforce it */
07639    if (!i->adsi)
07640       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07641    if (!ast_strlen_zero(i->exten))
07642       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07643    if (!ast_strlen_zero(i->rdnis))
07644       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07645    if (!ast_strlen_zero(i->dnid))
07646       tmp->cid.cid_dnid = ast_strdup(i->dnid);
07647 
07648    /* Don't use ast_set_callerid() here because it will
07649     * generate a needless NewCallerID event */
07650 #ifdef PRI_ANI
07651    if (!ast_strlen_zero(i->cid_ani))
07652       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07653    else
07654       tmp->cid.cid_ani = ast_strdup(i->cid_num);
07655 #else
07656    tmp->cid.cid_ani = ast_strdup(i->cid_num);
07657 #endif
07658    tmp->cid.cid_pres = i->callingpres;
07659    tmp->cid.cid_ton = i->cid_ton;
07660    tmp->cid.cid_ani2 = i->cid_ani2;
07661 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07662    tmp->transfercapability = transfercapability;
07663    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07664    if (transfercapability & AST_TRANS_CAP_DIGITAL)
07665       i->digital = 1;
07666    /* Assume calls are not idle calls unless we're told differently */
07667    i->isidlecall = 0;
07668    i->alreadyhungup = 0;
07669 #endif
07670    /* clear the fake event in case we posted one before we had ast_channel */
07671    i->fake_event = 0;
07672    /* Assure there is no confmute on this channel */
07673    dahdi_confmute(i, 0);
07674    i->muting = 0;
07675    /* Configure the new channel jb */
07676    ast_jb_configure(tmp, &global_jbconf);
07677 
07678    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07679 
07680    for (v = i->vars ; v ; v = v->next)
07681       pbx_builtin_setvar_helper(tmp, v->name, v->value);
07682 
07683    if (startpbx) {
07684 #ifdef HAVE_OPENR2
07685       if (i->mfcr2call) {
07686          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07687       }
07688 #endif
07689       if (ast_pbx_start(tmp)) {
07690          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07691          ast_hangup(tmp);
07692          i->owner = NULL;
07693          return NULL;
07694       }
07695    }
07696 
07697    ast_module_ref(ast_module_info->self);
07698    return tmp;
07699 }
07700 
07701 
07702 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07703 {
07704    char c;
07705 
07706    *str = 0; /* start with empty output buffer */
07707    for (;;)
07708    {
07709       /* Wait for the first digit (up to specified ms). */
07710       c = ast_waitfordigit(chan, ms);
07711       /* if timeout, hangup or error, return as such */
07712       if (c < 1)
07713          return c;
07714       *str++ = c;
07715       *str = 0;
07716       if (strchr(term, c))
07717          return 1;
07718    }
07719 }
07720 
07721 static int dahdi_wink(struct dahdi_pvt *p, int idx)
07722 {
07723    int j;
07724    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07725    for (;;)
07726    {
07727       /* set bits of interest */
07728       j = DAHDI_IOMUX_SIGEVENT;
07729       /* wait for some happening */
07730       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07731       /* exit loop if we have it */
07732       if (j & DAHDI_IOMUX_SIGEVENT) break;
07733    }
07734    /* get the event info */
07735    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07736    return 0;
07737 }
07738 
07739 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
07740  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
07741  * \param on 1 to enable, 0 to disable
07742  *
07743  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
07744  * DAHDI channel). Use this to enable or disable it.
07745  *
07746  * \bug the use of the word "channel" for those dahdichans is really confusing.
07747  */
07748 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
07749 {
07750    /* Do not disturb */
07751    dahdichan->dnd = on;
07752    ast_verb(3, "%s DND on channel %d\n",
07753          on? "Enabled" : "Disabled",
07754          dahdichan->channel);
07755    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07756          "Channel: DAHDI/%d\r\n"
07757          "Status: %s\r\n", dahdichan->channel,
07758          on? "enabled" : "disabled");
07759 }
07760 
07761 static void *ss_thread(void *data)
07762 {
07763    struct ast_channel *chan = data;
07764    struct dahdi_pvt *p = chan->tech_pvt;
07765    char exten[AST_MAX_EXTENSION] = "";
07766    char exten2[AST_MAX_EXTENSION] = "";
07767    unsigned char buf[256];
07768    char dtmfcid[300];
07769    char dtmfbuf[300];
07770    struct callerid_state *cs = NULL;
07771    char *name = NULL, *number = NULL;
07772    int distMatches;
07773    int curRingData[3];
07774    int receivedRingT;
07775    int counter1;
07776    int counter;
07777    int samples = 0;
07778    struct ast_smdi_md_message *smdi_msg = NULL;
07779    int flags = 0;
07780    int i;
07781    int timeout;
07782    int getforward = 0;
07783    char *s1, *s2;
07784    int len = 0;
07785    int res;
07786    int idx;
07787 
07788    ast_mutex_lock(&ss_thread_lock);
07789    ss_thread_count++;
07790    ast_mutex_unlock(&ss_thread_lock);
07791    /* in the bizarre case where the channel has become a zombie before we
07792       even get started here, abort safely
07793    */
07794    if (!p) {
07795       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07796       ast_hangup(chan);
07797       goto quit;
07798    }
07799    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07800    idx = dahdi_get_index(chan, p, 1);
07801    if (idx < 0) {
07802       ast_log(LOG_WARNING, "Huh?\n");
07803       ast_hangup(chan);
07804       goto quit;
07805    }
07806    if (p->dsp)
07807       ast_dsp_digitreset(p->dsp);
07808    switch (p->sig) {
07809 #ifdef HAVE_PRI
07810    case SIG_PRI:
07811    case SIG_BRI:
07812    case SIG_BRI_PTMP:
07813       /* Now loop looking for an extension */
07814       ast_copy_string(exten, p->exten, sizeof(exten));
07815       len = strlen(exten);
07816       res = 0;
07817       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07818          if (len && !ast_ignore_pattern(chan->context, exten))
07819             tone_zone_play_tone(p->subs[idx].dfd, -1);
07820          else
07821             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07822          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07823             timeout = matchdigittimeout;
07824          else
07825             timeout = gendigittimeout;
07826          res = ast_waitfordigit(chan, timeout);
07827          if (res < 0) {
07828             ast_debug(1, "waitfordigit returned < 0...\n");
07829             ast_hangup(chan);
07830             goto quit;
07831          } else if (res) {
07832             exten[len++] = res;
07833             exten[len] = '\0';
07834          } else
07835             break;
07836       }
07837       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
07838       if (ast_strlen_zero(exten)) {
07839          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07840          exten[0] = 's';
07841          exten[1] = '\0';
07842       }
07843       tone_zone_play_tone(p->subs[idx].dfd, -1);
07844       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07845          /* Start the real PBX */
07846          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07847          if (p->dsp) {
07848             ast_dsp_digitreset(p->dsp);
07849          }
07850          if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07851             ast_mutex_lock(&p->lock);
07852             if (p->pri->pri) {      
07853                if (!pri_grab(p, p->pri)) {
07854                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07855                   p->proceeding = 1;
07856                   pri_rel(p->pri);
07857                } else {
07858                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07859                }
07860             }
07861             ast_mutex_unlock(&p->lock);
07862          }
07863          dahdi_enable_ec(p);
07864          ast_setstate(chan, AST_STATE_RING);
07865          res = ast_pbx_run(chan);
07866          if (res) {
07867             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07868          }
07869       } else {
07870          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07871          chan->hangupcause = AST_CAUSE_UNALLOCATED;
07872          ast_hangup(chan);
07873          p->exten[0] = '\0';
07874          /* Since we send release complete here, we won't get one */
07875          p->call = NULL;
07876       }
07877       goto quit;
07878       break;
07879 #endif
07880    case SIG_FEATD:
07881    case SIG_FEATDMF:
07882    case SIG_FEATDMF_TA:
07883    case SIG_E911:
07884    case SIG_FGC_CAMAMF:
07885    case SIG_FEATB:
07886    case SIG_EMWINK:
07887    case SIG_SF_FEATD:
07888    case SIG_SF_FEATDMF:
07889    case SIG_SF_FEATB:
07890    case SIG_SFWINK:
07891       if (dahdi_wink(p, idx))
07892          goto quit;
07893       /* Fall through */
07894    case SIG_EM:
07895    case SIG_EM_E1:
07896    case SIG_SF:
07897    case SIG_FGC_CAMA:
07898       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07899       if (p->dsp)
07900          ast_dsp_digitreset(p->dsp);
07901       /* set digit mode appropriately */
07902       if (p->dsp) {
07903          if (NEED_MFDETECT(p))
07904             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07905          else
07906             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07907       }
07908       memset(dtmfbuf, 0, sizeof(dtmfbuf));
07909       /* Wait for the first digit only if immediate=no */
07910       if (!p->immediate)
07911          /* Wait for the first digit (up to 5 seconds). */
07912          res = ast_waitfordigit(chan, 5000);
07913       else
07914          res = 0;
07915       if (res > 0) {
07916          /* save first char */
07917          dtmfbuf[0] = res;
07918          switch (p->sig) {
07919          case SIG_FEATD:
07920          case SIG_SF_FEATD:
07921             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07922             if (res > 0)
07923                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07924             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07925             break;
07926          case SIG_FEATDMF_TA:
07927             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07928             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07929             if (dahdi_wink(p, idx)) goto quit;
07930             dtmfbuf[0] = 0;
07931             /* Wait for the first digit (up to 5 seconds). */
07932             res = ast_waitfordigit(chan, 5000);
07933             if (res <= 0) break;
07934             dtmfbuf[0] = res;
07935             /* fall through intentionally */
07936          case SIG_FEATDMF:
07937          case SIG_E911:
07938          case SIG_FGC_CAMAMF:
07939          case SIG_SF_FEATDMF:
07940             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07941             /* if international caca, do it again to get real ANO */
07942             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07943             {
07944                if (dahdi_wink(p, idx)) goto quit;
07945                dtmfbuf[0] = 0;
07946                /* Wait for the first digit (up to 5 seconds). */
07947                res = ast_waitfordigit(chan, 5000);
07948                if (res <= 0) break;
07949                dtmfbuf[0] = res;
07950                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07951             }
07952             if (res > 0) {
07953                /* if E911, take off hook */
07954                if (p->sig == SIG_E911)
07955                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07956                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07957             }
07958             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07959             break;
07960          case SIG_FEATB:
07961          case SIG_SF_FEATB:
07962             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07963             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07964             break;
07965          case SIG_EMWINK:
07966             /* if we received a '*', we are actually receiving Feature Group D
07967                dial syntax, so use that mode; otherwise, fall through to normal
07968                mode
07969             */
07970             if (res == '*') {
07971                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07972                if (res > 0)
07973                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07974                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07975                break;
07976             }
07977          default:
07978             /* If we got the first digit, get the rest */
07979             len = 1;
07980             dtmfbuf[len] = '\0';
07981             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07982                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07983                   timeout = matchdigittimeout;
07984                } else {
07985                   timeout = gendigittimeout;
07986                }
07987                res = ast_waitfordigit(chan, timeout);
07988                if (res < 0) {
07989                   ast_debug(1, "waitfordigit returned < 0...\n");
07990                   ast_hangup(chan);
07991                   goto quit;
07992                } else if (res) {
07993                   dtmfbuf[len++] = res;
07994                   dtmfbuf[len] = '\0';
07995                } else {
07996                   break;
07997                }
07998             }
07999             break;
08000          }
08001       }
08002       if (res == -1) {
08003          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08004          ast_hangup(chan);
08005          goto quit;
08006       } else if (res < 0) {
08007          ast_debug(1, "Got hung up before digits finished\n");
08008          ast_hangup(chan);
08009          goto quit;
08010       }
08011 
08012       if (p->sig == SIG_FGC_CAMA) {
08013          char anibuf[100];
08014 
08015          if (ast_safe_sleep(chan,1000) == -1) {
08016             ast_hangup(chan);
08017             goto quit;
08018          }
08019          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08020          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08021          res = my_getsigstr(chan, anibuf, "#", 10000);
08022          if ((res > 0) && (strlen(anibuf) > 2)) {
08023             if (anibuf[strlen(anibuf) - 1] == '#')
08024                anibuf[strlen(anibuf) - 1] = 0;
08025             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08026          }
08027          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08028       }
08029 
08030       ast_copy_string(exten, dtmfbuf, sizeof(exten));
08031       if (ast_strlen_zero(exten))
08032          ast_copy_string(exten, "s", sizeof(exten));
08033       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08034          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
08035          if (exten[0] == '*') {
08036             char *stringp=NULL;
08037             ast_copy_string(exten2, exten, sizeof(exten2));
08038             /* Parse out extension and callerid */
08039             stringp=exten2 +1;
08040             s1 = strsep(&stringp, "*");
08041             s2 = strsep(&stringp, "*");
08042             if (s2) {
08043                if (!ast_strlen_zero(p->cid_num))
08044                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08045                else
08046                   ast_set_callerid(chan, s1, NULL, s1);
08047                ast_copy_string(exten, s2, sizeof(exten));
08048             } else
08049                ast_copy_string(exten, s1, sizeof(exten));
08050          } else if (p->sig == SIG_FEATD)
08051             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08052       }
08053       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08054          if (exten[0] == '*') {
08055             char *stringp=NULL;
08056             ast_copy_string(exten2, exten, sizeof(exten2));
08057             /* Parse out extension and callerid */
08058             stringp=exten2 +1;
08059             s1 = strsep(&stringp, "#");
08060             s2 = strsep(&stringp, "#");
08061             if (s2) {
08062                if (!ast_strlen_zero(p->cid_num))
08063                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08064                else
08065                   if (*(s1 + 2))
08066                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08067                ast_copy_string(exten, s2 + 1, sizeof(exten));
08068             } else
08069                ast_copy_string(exten, s1 + 2, sizeof(exten));
08070          } else
08071             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08072       }
08073       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08074          if (exten[0] == '*') {
08075             char *stringp=NULL;
08076             ast_copy_string(exten2, exten, sizeof(exten2));
08077             /* Parse out extension and callerid */
08078             stringp=exten2 +1;
08079             s1 = strsep(&stringp, "#");
08080             s2 = strsep(&stringp, "#");
08081             if (s2 && (*(s2 + 1) == '0')) {
08082                if (*(s2 + 2))
08083                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08084             }
08085             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
08086             else ast_copy_string(exten, "911", sizeof(exten));
08087          } else
08088             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08089       }
08090       if (p->sig == SIG_FEATB) {
08091          if (exten[0] == '*') {
08092             char *stringp=NULL;
08093             ast_copy_string(exten2, exten, sizeof(exten2));
08094             /* Parse out extension and callerid */
08095             stringp=exten2 +1;
08096             s1 = strsep(&stringp, "#");
08097             ast_copy_string(exten, exten2 + 1, sizeof(exten));
08098          } else
08099             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08100       }
08101       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08102          dahdi_wink(p, idx);
08103          /* some switches require a minimum guard time between
08104             the last FGD wink and something that answers
08105             immediately. This ensures it */
08106          if (ast_safe_sleep(chan,100)) goto quit;
08107       }
08108       dahdi_enable_ec(p);
08109       if (NEED_MFDETECT(p)) {
08110          if (p->dsp) {
08111             if (!p->hardwaredtmf)
08112                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08113             else {
08114                ast_dsp_free(p->dsp);
08115                p->dsp = NULL;
08116             }
08117          }
08118       }
08119 
08120       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08121          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08122          if (p->dsp) ast_dsp_digitreset(p->dsp);
08123          res = ast_pbx_run(chan);
08124          if (res) {
08125             ast_log(LOG_WARNING, "PBX exited non-zero\n");
08126             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08127          }
08128          goto quit;
08129       } else {
08130          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08131          sleep(2);
08132          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08133          if (res < 0)
08134             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08135          else
08136             sleep(1);
08137          res = ast_streamfile(chan, "ss-noservice", chan->language);
08138          if (res >= 0)
08139             ast_waitstream(chan, "");
08140          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08141          ast_hangup(chan);
08142          goto quit;
08143       }
08144       break;
08145    case SIG_FXOLS:
08146    case SIG_FXOGS:
08147    case SIG_FXOKS:
08148       /* Read the first digit */
08149       timeout = firstdigittimeout;
08150       /* If starting a threeway call, never timeout on the first digit so someone
08151          can use flash-hook as a "hold" feature */
08152       if (p->subs[SUB_THREEWAY].owner)
08153          timeout = 999999;
08154       while (len < AST_MAX_EXTENSION-1) {
08155          /* Read digit unless it's supposed to be immediate, in which case the
08156             only answer is 's' */
08157          if (p->immediate)
08158             res = 's';
08159          else
08160             res = ast_waitfordigit(chan, timeout);
08161          timeout = 0;
08162          if (res < 0) {
08163             ast_debug(1, "waitfordigit returned < 0...\n");
08164             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08165             ast_hangup(chan);
08166             goto quit;
08167          } else if (res) {
08168             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08169             exten[len++]=res;
08170             exten[len] = '\0';
08171          }
08172          if (!ast_ignore_pattern(chan->context, exten))
08173             tone_zone_play_tone(p->subs[idx].dfd, -1);
08174          else
08175             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08176          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08177             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08178                if (getforward) {
08179                   /* Record this as the forwarding extension */
08180                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08181                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08182                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08183                   if (res)
08184                      break;
08185                   usleep(500000);
08186                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08187                   sleep(1);
08188                   memset(exten, 0, sizeof(exten));
08189                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08190                   len = 0;
08191                   getforward = 0;
08192                } else {
08193                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08194                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08195                   if (!ast_strlen_zero(p->cid_num)) {
08196                      if (!p->hidecallerid)
08197                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08198                      else
08199                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
08200                   }
08201                   if (!ast_strlen_zero(p->cid_name)) {
08202                      if (!p->hidecallerid)
08203                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
08204                   }
08205                   ast_setstate(chan, AST_STATE_RING);
08206                   dahdi_enable_ec(p);
08207                   res = ast_pbx_run(chan);
08208                   if (res) {
08209                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
08210                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08211                   }
08212                   goto quit;
08213                }
08214             } else {
08215                /* It's a match, but they just typed a digit, and there is an ambiguous match,
08216                   so just set the timeout to matchdigittimeout and wait some more */
08217                timeout = matchdigittimeout;
08218             }
08219          } else if (res == 0) {
08220             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08221             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08222             dahdi_wait_event(p->subs[idx].dfd);
08223             ast_hangup(chan);
08224             goto quit;
08225          } else if (p->callwaiting && !strcmp(exten, "*70")) {
08226             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08227             /* Disable call waiting if enabled */
08228             p->callwaiting = 0;
08229             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08230             if (res) {
08231                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08232                   chan->name, strerror(errno));
08233             }
08234             len = 0;
08235             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08236             memset(exten, 0, sizeof(exten));
08237             timeout = firstdigittimeout;
08238 
08239          } else if (!strcmp(exten,ast_pickup_ext())) {
08240             /* Scan all channels and see if there are any
08241              * ringing channels that have call groups
08242              * that equal this channels pickup group
08243              */
08244             if (idx == SUB_REAL) {
08245                /* Switch us from Third call to Call Wait */
08246                if (p->subs[SUB_THREEWAY].owner) {
08247                   /* If you make a threeway call and the *8# a call, it should actually
08248                      look like a callwait */
08249                   alloc_sub(p, SUB_CALLWAIT);
08250                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08251                   unalloc_sub(p, SUB_THREEWAY);
08252                }
08253                dahdi_enable_ec(p);
08254                if (ast_pickup_call(chan)) {
08255                   ast_debug(1, "No call pickup possible...\n");
08256                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08257                   dahdi_wait_event(p->subs[idx].dfd);
08258                }
08259                ast_hangup(chan);
08260                goto quit;
08261             } else {
08262                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
08263                ast_hangup(chan);
08264                goto quit;
08265             }
08266 
08267          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08268             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08269             /* Disable Caller*ID if enabled */
08270             p->hidecallerid = 1;
08271             if (chan->cid.cid_num)
08272                ast_free(chan->cid.cid_num);
08273             chan->cid.cid_num = NULL;
08274             if (chan->cid.cid_name)
08275                ast_free(chan->cid.cid_name);
08276             chan->cid.cid_name = NULL;
08277             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08278             if (res) {
08279                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08280                   chan->name, strerror(errno));
08281             }
08282             len = 0;
08283             memset(exten, 0, sizeof(exten));
08284             timeout = firstdigittimeout;
08285          } else if (p->callreturn && !strcmp(exten, "*69")) {
08286             res = 0;
08287             if (!ast_strlen_zero(p->lastcid_num)) {
08288                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08289             }
08290             if (!res)
08291                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08292             break;
08293          } else if (!strcmp(exten, "*78")) {
08294             dahdi_dnd(p, 1);
08295             /* Do not disturb */
08296             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08297             getforward = 0;
08298             memset(exten, 0, sizeof(exten));
08299             len = 0;
08300          } else if (!strcmp(exten, "*79")) {
08301             dahdi_dnd(p, 0);
08302             /* Do not disturb */
08303             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08304             getforward = 0;
08305             memset(exten, 0, sizeof(exten));
08306             len = 0;
08307          } else if (p->cancallforward && !strcmp(exten, "*72")) {
08308             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08309             getforward = 1;
08310             memset(exten, 0, sizeof(exten));
08311             len = 0;
08312          } else if (p->cancallforward && !strcmp(exten, "*73")) {
08313             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08314             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08315             memset(p->call_forward, 0, sizeof(p->call_forward));
08316             getforward = 0;
08317             memset(exten, 0, sizeof(exten));
08318             len = 0;
08319          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08320                   p->subs[SUB_THREEWAY].owner &&
08321                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08322             /* This is a three way call, the main call being a real channel,
08323                and we're parking the first call. */
08324             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08325             ast_verb(3, "Parking call to '%s'\n", chan->name);
08326             break;
08327          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08328             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08329             res = ast_db_put("blacklist", p->lastcid_num, "1");
08330             if (!res) {
08331                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08332                memset(exten, 0, sizeof(exten));
08333                len = 0;
08334             }
08335          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08336             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08337             /* Enable Caller*ID if enabled */
08338             p->hidecallerid = 0;
08339             if (chan->cid.cid_num)
08340                ast_free(chan->cid.cid_num);
08341             chan->cid.cid_num = NULL;
08342             if (chan->cid.cid_name)
08343                ast_free(chan->cid.cid_name);
08344             chan->cid.cid_name = NULL;
08345             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08346             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08347             if (res) {
08348                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08349                   chan->name, strerror(errno));
08350             }
08351             len = 0;
08352             memset(exten, 0, sizeof(exten));
08353             timeout = firstdigittimeout;
08354          } else if (!strcmp(exten, "*0")) {
08355             struct ast_channel *nbridge =
08356                p->subs[SUB_THREEWAY].owner;
08357             struct dahdi_pvt *pbridge = NULL;
08358             /* set up the private struct of the bridged one, if any */
08359             if (nbridge && ast_bridged_channel(nbridge))
08360                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08361             if (nbridge && pbridge &&
08362                (nbridge->tech == &dahdi_tech) &&
08363                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08364                ISTRUNK(pbridge)) {
08365                int func = DAHDI_FLASH;
08366                /* Clear out the dial buffer */
08367                p->dop.dialstr[0] = '\0';
08368                /* flash hookswitch */
08369                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08370                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08371                      nbridge->name, strerror(errno));
08372                }
08373                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08374                unalloc_sub(p, SUB_THREEWAY);
08375                p->owner = p->subs[SUB_REAL].owner;
08376                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08377                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08378                ast_hangup(chan);
08379                goto quit;
08380             } else {
08381                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08382                dahdi_wait_event(p->subs[idx].dfd);
08383                tone_zone_play_tone(p->subs[idx].dfd, -1);
08384                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08385                unalloc_sub(p, SUB_THREEWAY);
08386                p->owner = p->subs[SUB_REAL].owner;
08387                ast_hangup(chan);
08388                goto quit;
08389             }
08390          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08391                      ((exten[0] != '*') || (strlen(exten) > 2))) {
08392             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
08393             break;
08394          }
08395          if (!timeout)
08396             timeout = gendigittimeout;
08397          if (len && !ast_ignore_pattern(chan->context, exten))
08398             tone_zone_play_tone(p->subs[idx].dfd, -1);
08399       }
08400       break;
08401    case SIG_FXSLS:
08402    case SIG_FXSGS:
08403    case SIG_FXSKS:
08404 #ifdef HAVE_PRI
08405       if (p->pri) {
08406          /* This is a GR-303 trunk actually.  Wait for the first ring... */
08407          struct ast_frame *f;
08408          int res;
08409          time_t start;
08410 
08411          time(&start);
08412          ast_setstate(chan, AST_STATE_RING);
08413          while (time(NULL) < start + 3) {
08414             res = ast_waitfor(chan, 1000);
08415             if (res) {
08416                f = ast_read(chan);
08417                if (!f) {
08418                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08419                   ast_hangup(chan);
08420                   goto quit;
08421                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08422                   res = 1;
08423                } else
08424                   res = 0;
08425                ast_frfree(f);
08426                if (res) {
08427                   ast_debug(1, "Got ring!\n");
08428                   res = 0;
08429                   break;
08430                }
08431             }
08432          }
08433       }
08434 #endif
08435       /* check for SMDI messages */
08436       if (p->use_smdi && p->smdi_iface) {
08437          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08438 
08439          if (smdi_msg != NULL) {
08440             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08441 
08442             if (smdi_msg->type == 'B')
08443                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08444             else if (smdi_msg->type == 'N')
08445                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08446 
08447             ast_debug(1, "Received SMDI message on %s\n", chan->name);
08448          } else {
08449             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08450          }
08451       }
08452 
08453       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08454          number = smdi_msg->calling_st;
08455 
08456       /* If we want caller id, we're in a prering state due to a polarity reversal
08457        * and we're set to use a polarity reversal to trigger the start of caller id,
08458        * grab the caller id and wait for ringing to start... */
08459       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08460          /* If set to use DTMF CID signalling, listen for DTMF */
08461          if (p->cid_signalling == CID_SIG_DTMF) {
08462             int k = 0;
08463             cs = NULL;
08464             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08465             dahdi_setlinear(p->subs[idx].dfd, 0);
08466             /*
08467              * We are the only party interested in the Rx stream since
08468              * we have not answered yet.  We don't need or even want DTMF
08469              * emulation.  The DTMF digits can come so fast that emulation
08470              * can drop some of them.
08471              */
08472             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08473             res = 4000;/* This is a typical OFF time between rings. */
08474             for (;;) {
08475                struct ast_frame *f;
08476                res = ast_waitfor(chan, res);
08477                if (res <= 0) {
08478                   /*
08479                    * We do not need to restore the dahdi_setlinear()
08480                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
08481                    * are hanging up the channel.
08482                    */
08483                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08484                      "Exiting simple switch\n");
08485                   ast_hangup(chan);
08486                   goto quit;
08487                }
08488                f = ast_read(chan);
08489                if (!f)
08490                   break;
08491                if (f->frametype == AST_FRAME_DTMF) {
08492                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
08493                      dtmfbuf[k++] = f->subclass;
08494                   }
08495                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
08496                   res = 4000;/* This is a typical OFF time between rings. */
08497                }
08498                ast_frfree(f);
08499                if (chan->_state == AST_STATE_RING ||
08500                   chan->_state == AST_STATE_RINGING)
08501                   break; /* Got ring */
08502             }
08503             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08504             dtmfbuf[k] = '\0';
08505             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08506             /* Got cid and ring. */
08507             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08508             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08509             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08510             /* If first byte is NULL, we have no cid */
08511             if (!ast_strlen_zero(dtmfcid))
08512                number = dtmfcid;
08513             else
08514                number = NULL;
08515          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08516          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08517             cs = callerid_new(p->cid_signalling);
08518             if (cs) {
08519                samples = 0;
08520 #if 1
08521                bump_gains(p);
08522 #endif
08523                /* Take out of linear mode for Caller*ID processing */
08524                dahdi_setlinear(p->subs[idx].dfd, 0);
08525 
08526                /* First we wait and listen for the Caller*ID */
08527                for (;;) {
08528                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08529                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08530                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08531                      callerid_free(cs);
08532                      ast_hangup(chan);
08533                      goto quit;
08534                   }
08535                   if (i & DAHDI_IOMUX_SIGEVENT) {
08536                      res = dahdi_get_event(p->subs[idx].dfd);
08537                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08538                      if (res == DAHDI_EVENT_NOALARM) {
08539                         p->inalarm = 0;
08540                      }
08541 
08542                      if (p->cid_signalling == CID_SIG_V23_JP) {
08543                         if (res == DAHDI_EVENT_RINGBEGIN) {
08544                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08545                            usleep(1);
08546                         }
08547                      } else {
08548                         res = 0;
08549                         break;
08550                      }
08551                   } else if (i & DAHDI_IOMUX_READ) {
08552                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08553                      if (res < 0) {
08554                         if (errno != ELAST) {
08555                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08556                            callerid_free(cs);
08557                            ast_hangup(chan);
08558                            goto quit;
08559                         }
08560                         break;
08561                      }
08562                      samples += res;
08563 
08564                      if (p->cid_signalling == CID_SIG_V23_JP) {
08565                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08566                      } else {
08567                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08568                      }
08569                      if (res < 0) {
08570                         /*
08571                          * The previous diagnostic message output likely
08572                          * explains why it failed.
08573                          */
08574                         ast_log(LOG_WARNING,
08575                            "Failed to decode CallerID on channel '%s'\n",
08576                            chan->name);
08577                         break;
08578                      } else if (res)
08579                         break;
08580                      else if (samples > (8000 * 10))
08581                         break;
08582                   }
08583                }
08584                if (res == 1) {
08585                   callerid_get(cs, &name, &number, &flags);
08586                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08587                }
08588 
08589                if (p->cid_signalling == CID_SIG_V23_JP) {
08590                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08591                   usleep(1);
08592                }
08593 
08594                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08595                res = 4000;/* This is a typical OFF time between rings. */
08596                for (;;) {
08597                   struct ast_frame *f;
08598                   res = ast_waitfor(chan, res);
08599                   if (res <= 0) {
08600                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08601                         "Exiting simple switch\n");
08602                      ast_hangup(chan);
08603                      goto quit;
08604                   }
08605                   if (!(f = ast_read(chan))) {
08606                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08607                      ast_hangup(chan);
08608                      goto quit;
08609                   }
08610                   ast_frfree(f);
08611                   if (chan->_state == AST_STATE_RING ||
08612                      chan->_state == AST_STATE_RINGING)
08613                      break; /* Got ring */
08614                }
08615 
08616                /* We must have a ring by now, so, if configured, lets try to listen for
08617                 * distinctive ringing */
08618                if (p->usedistinctiveringdetection) {
08619                   len = 0;
08620                   distMatches = 0;
08621                   /* Clear the current ring data array so we dont have old data in it. */
08622                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08623                      curRingData[receivedRingT] = 0;
08624                   receivedRingT = 0;
08625                   counter = 0;
08626                   counter1 = 0;
08627                   /* Check to see if context is what it should be, if not set to be. */
08628                   if (strcmp(p->context,p->defcontext) != 0) {
08629                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08630                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08631                   }
08632 
08633                   for (;;) {
08634                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08635                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08636                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08637                         callerid_free(cs);
08638                         ast_hangup(chan);
08639                         goto quit;
08640                      }
08641                      if (i & DAHDI_IOMUX_SIGEVENT) {
08642                         res = dahdi_get_event(p->subs[idx].dfd);
08643                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08644                         if (res == DAHDI_EVENT_NOALARM) {
08645                            p->inalarm = 0;
08646                         }
08647                         res = 0;
08648                         /* Let us detect distinctive ring */
08649 
08650                         curRingData[receivedRingT] = p->ringt;
08651 
08652                         if (p->ringt < p->ringt_base/2)
08653                            break;
08654                         /* Increment the ringT counter so we can match it against
08655                            values in chan_dahdi.conf for distinctive ring */
08656                         if (++receivedRingT == ARRAY_LEN(curRingData))
08657                            break;
08658                      } else if (i & DAHDI_IOMUX_READ) {
08659                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08660                         if (res < 0) {
08661                            if (errno != ELAST) {
08662                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08663                               callerid_free(cs);
08664                               ast_hangup(chan);
08665                               goto quit;
08666                            }
08667                            break;
08668                         }
08669                         if (p->ringt)
08670                            p->ringt--;
08671                         if (p->ringt == 1) {
08672                            res = -1;
08673                            break;
08674                         }
08675                      }
08676                   }
08677                      /* this only shows up if you have n of the dring patterns filled in */
08678                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08679                   for (counter = 0; counter < 3; counter++) {
08680                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08681                      channel */
08682                      distMatches = 0;
08683                      for (counter1 = 0; counter1 < 3; counter1++) {
08684                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08685                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08686                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08687                            curRingData[counter1]);
08688                            distMatches++;
08689                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08690                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08691                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08692                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08693                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08694                            distMatches++;
08695                         }
08696                      }
08697 
08698                      if (distMatches == 3) {
08699                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08700                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08701                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08702                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08703                         break;
08704                      }
08705                   }
08706                }
08707                /* Restore linear mode (if appropriate) for Caller*ID processing */
08708                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08709 #if 1
08710                restore_gains(p);
08711 #endif
08712             } else
08713                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08714          } else {
08715             ast_log(LOG_WARNING, "Channel %s in prering "
08716                "state, but I have nothing to do. "
08717                "Terminating simple switch, should be "
08718                "restarted by the actual ring.\n",
08719                chan->name);
08720             ast_hangup(chan);
08721             goto quit;
08722          }
08723       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08724          if (p->cid_signalling == CID_SIG_DTMF) {
08725             int k = 0;
08726             cs = NULL;
08727             dahdi_setlinear(p->subs[idx].dfd, 0);
08728             res = 2000;
08729             for (;;) {
08730                struct ast_frame *f;
08731                res = ast_waitfor(chan, res);
08732                if (res <= 0) {
08733                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08734                      "Exiting simple switch\n");
08735                   ast_hangup(chan);
08736                   return NULL;
08737                }
08738                f = ast_read(chan);
08739                if (f->frametype == AST_FRAME_DTMF) {
08740                   dtmfbuf[k++] = f->subclass;
08741                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08742                   res = 2000;
08743                }
08744                ast_frfree(f);
08745 
08746                if (p->ringt_base == p->ringt)
08747                   break;
08748             }
08749             dtmfbuf[k] = '\0';
08750             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08751             /* Got cid and ring. */
08752             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08753             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08754                dtmfcid, flags);
08755             /* If first byte is NULL, we have no cid */
08756             if (!ast_strlen_zero(dtmfcid))
08757                number = dtmfcid;
08758             else
08759                number = NULL;
08760             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08761          } else {
08762             /* FSK Bell202 callerID */
08763             cs = callerid_new(p->cid_signalling);
08764             if (cs) {
08765 #if 1
08766                bump_gains(p);
08767 #endif
08768                samples = 0;
08769                len = 0;
08770                distMatches = 0;
08771                /* Clear the current ring data array so we dont have old data in it. */
08772                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08773                   curRingData[receivedRingT] = 0;
08774                receivedRingT = 0;
08775                counter = 0;
08776                counter1 = 0;
08777                /* Check to see if context is what it should be, if not set to be. */
08778                if (strcmp(p->context,p->defcontext) != 0) {
08779                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08780                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08781                }
08782 
08783                /* Take out of linear mode for Caller*ID processing */
08784                dahdi_setlinear(p->subs[idx].dfd, 0);
08785                for (;;) {
08786                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08787                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08788                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08789                      callerid_free(cs);
08790                      ast_hangup(chan);
08791                      goto quit;
08792                   }
08793                   if (i & DAHDI_IOMUX_SIGEVENT) {
08794                      res = dahdi_get_event(p->subs[idx].dfd);
08795                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08796                      if (res == DAHDI_EVENT_NOALARM) {
08797                         p->inalarm = 0;
08798                      }
08799                      /* If we get a PR event, they hung up while processing calerid */
08800                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08801                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08802                         p->polarity = POLARITY_IDLE;
08803                         callerid_free(cs);
08804                         ast_hangup(chan);
08805                         goto quit;
08806                      }
08807                      res = 0;
08808                      /* Let us detect callerid when the telco uses distinctive ring */
08809 
08810                      curRingData[receivedRingT] = p->ringt;
08811 
08812                      if (p->ringt < p->ringt_base/2)
08813                         break;
08814                      /* Increment the ringT counter so we can match it against
08815                         values in chan_dahdi.conf for distinctive ring */
08816                      if (++receivedRingT == ARRAY_LEN(curRingData))
08817                         break;
08818                   } else if (i & DAHDI_IOMUX_READ) {
08819                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08820                      if (res < 0) {
08821                         if (errno != ELAST) {
08822                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08823                            callerid_free(cs);
08824                            ast_hangup(chan);
08825                            goto quit;
08826                         }
08827                         break;
08828                      }
08829                      if (p->ringt)
08830                         p->ringt--;
08831                      if (p->ringt == 1) {
08832                         res = -1;
08833                         break;
08834                      }
08835                      samples += res;
08836                      res = callerid_feed(cs, buf, res, AST_LAW(p));
08837                      if (res < 0) {
08838                         /*
08839                          * The previous diagnostic message output likely
08840                          * explains why it failed.
08841                          */
08842                         ast_log(LOG_WARNING,
08843                            "Failed to decode CallerID on channel '%s'\n",
08844                            chan->name);
08845                         break;
08846                      } else if (res)
08847                         break;
08848                      else if (samples > (8000 * 10))
08849                         break;
08850                   }
08851                }
08852                if (res == 1) {
08853                   callerid_get(cs, &name, &number, &flags);
08854                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08855                }
08856                if (distinctiveringaftercid == 1) {
08857                   /* Clear the current ring data array so we dont have old data in it. */
08858                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08859                      curRingData[receivedRingT] = 0;
08860                   }
08861                   receivedRingT = 0;
08862                   ast_verb(3, "Detecting post-CID distinctive ring\n");
08863                   for (;;) {
08864                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08865                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08866                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08867                         callerid_free(cs);
08868                         ast_hangup(chan);
08869                         goto quit;
08870                      }
08871                      if (i & DAHDI_IOMUX_SIGEVENT) {
08872                         res = dahdi_get_event(p->subs[idx].dfd);
08873                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08874                         if (res == DAHDI_EVENT_NOALARM) {
08875                            p->inalarm = 0;
08876                         }
08877                         res = 0;
08878                         /* Let us detect callerid when the telco uses distinctive ring */
08879 
08880                         curRingData[receivedRingT] = p->ringt;
08881 
08882                         if (p->ringt < p->ringt_base/2)
08883                            break;
08884                         /* Increment the ringT counter so we can match it against
08885                            values in chan_dahdi.conf for distinctive ring */
08886                         if (++receivedRingT == ARRAY_LEN(curRingData))
08887                            break;
08888                      } else if (i & DAHDI_IOMUX_READ) {
08889                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08890                         if (res < 0) {
08891                            if (errno != ELAST) {
08892                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08893                               callerid_free(cs);
08894                               ast_hangup(chan);
08895                               goto quit;
08896                            }
08897                            break;
08898                         }
08899                      if (p->ringt)
08900                         p->ringt--;
08901                         if (p->ringt == 1) {
08902                            res = -1;
08903                            break;
08904                         }
08905                      }
08906                   }
08907                }
08908                if (p->usedistinctiveringdetection) {
08909                   /* this only shows up if you have n of the dring patterns filled in */
08910                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08911 
08912                   for (counter = 0; counter < 3; counter++) {
08913                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08914                      channel */
08915                      /* this only shows up if you have n of the dring patterns filled in */
08916                      ast_verb(3, "Checking %d,%d,%d\n",
08917                            p->drings.ringnum[counter].ring[0],
08918                            p->drings.ringnum[counter].ring[1],
08919                            p->drings.ringnum[counter].ring[2]);
08920                      distMatches = 0;
08921                      for (counter1 = 0; counter1 < 3; counter1++) {
08922                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08923                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08924                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08925                            curRingData[counter1]);
08926                            distMatches++;
08927                         }
08928                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08929                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08930                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08931                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08932                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08933                            distMatches++;
08934                         }
08935                      }
08936                      if (distMatches == 3) {
08937                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08938                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08939                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08940                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08941                         break;
08942                      }
08943                   }
08944                }
08945                /* Restore linear mode (if appropriate) for Caller*ID processing */
08946                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08947 #if 1
08948                restore_gains(p);
08949 #endif
08950                if (res < 0) {
08951                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08952                }
08953             } else
08954                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08955          }
08956       } else
08957          cs = NULL;
08958 
08959       if (number)
08960          ast_shrink_phone_number(number);
08961       ast_set_callerid(chan, number, name, number);
08962 
08963       if (smdi_msg)
08964          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08965 
08966       if (cs)
08967          callerid_free(cs);
08968       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
08969       if (flags & CID_MSGWAITING) {
08970          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08971          notify_message(p->mailbox, 1);
08972          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08973          if (p->mwimonitor_rpas) {
08974             ast_hangup(chan);
08975             return NULL;
08976          }
08977       } else if (flags & CID_NOMSGWAITING) {
08978          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08979          notify_message(p->mailbox, 0);
08980          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08981          if (p->mwimonitor_rpas) {
08982             ast_hangup(chan);
08983             return NULL;
08984          }
08985       }
08986 
08987       ast_setstate(chan, AST_STATE_RING);
08988       chan->rings = 1;
08989       p->ringt = p->ringt_base;
08990       res = ast_pbx_run(chan);
08991       if (res) {
08992          ast_hangup(chan);
08993          ast_log(LOG_WARNING, "PBX exited non-zero\n");
08994       }
08995       goto quit;
08996    default:
08997       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08998       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08999       if (res < 0)
09000             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09001    }
09002    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09003    if (res < 0)
09004          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09005    ast_hangup(chan);
09006 quit:
09007    ast_mutex_lock(&ss_thread_lock);
09008    ss_thread_count--;
09009    ast_cond_signal(&ss_thread_complete);
09010    ast_mutex_unlock(&ss_thread_lock);
09011    return NULL;
09012 }
09013 
09014 struct mwi_thread_data {
09015    struct dahdi_pvt *pvt;
09016    unsigned char buf[READ_SIZE];
09017    size_t len;
09018 };
09019 
09020 static int calc_energy(const unsigned char *buf, int len, int law)
09021 {
09022    int x;
09023    int sum = 0;
09024 
09025    if (!len)
09026       return 0;
09027 
09028    for (x = 0; x < len; x++)
09029       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09030 
09031    return sum / len;
09032 }
09033 
09034 static void *mwi_thread(void *data)
09035 {
09036    struct mwi_thread_data *mtd = data;
09037    struct callerid_state *cs;
09038    pthread_t threadid;
09039    int samples = 0;
09040    char *name, *number;
09041    int flags;
09042    int i, res;
09043    unsigned int spill_done = 0;
09044    int spill_result = -1;
09045 
09046    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09047       mtd->pvt->mwimonitoractive = 0;
09048 
09049       return NULL;
09050    }
09051 
09052    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09053 
09054    bump_gains(mtd->pvt);
09055 
09056    for (;;) {
09057       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09058       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09059          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09060          goto quit;
09061       }
09062 
09063       if (i & DAHDI_IOMUX_SIGEVENT) {
09064          struct ast_channel *chan;
09065 
09066          /* If we get an event, screen out events that we do not act on.
09067           * Otherwise, cancel and go to the simple switch to let it deal with it.
09068           */
09069          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09070 
09071          switch (res) {
09072          case DAHDI_EVENT_NEONMWI_ACTIVE:
09073          case DAHDI_EVENT_NEONMWI_INACTIVE:
09074          case DAHDI_EVENT_NONE:
09075          case DAHDI_EVENT_BITSCHANGED:
09076             break;
09077          case DAHDI_EVENT_NOALARM:
09078             mtd->pvt->inalarm = 0;
09079             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09080             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09081                "Channel: %d\r\n", mtd->pvt->channel);
09082             break;
09083          case DAHDI_EVENT_ALARM:
09084             mtd->pvt->inalarm = 1;
09085             res = get_alarms(mtd->pvt);
09086             handle_alarms(mtd->pvt, res);
09087             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
09088          default:
09089             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
09090             callerid_free(cs);
09091 
09092             restore_gains(mtd->pvt);
09093             mtd->pvt->ringt = mtd->pvt->ringt_base;
09094 
09095             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09096                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09097                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09098                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09099                   if (res < 0)
09100                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09101                   ast_hangup(chan);
09102                   goto quit;
09103                }
09104                goto quit_no_clean;
09105 
09106             } else {
09107                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09108             }
09109          }
09110       } else if (i & DAHDI_IOMUX_READ) {
09111          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09112             if (errno != ELAST) {
09113                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09114                goto quit;
09115             }
09116             break;
09117          }
09118          samples += res;
09119          if (!spill_done) {
09120             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09121                /*
09122                 * The previous diagnostic message output likely
09123                 * explains why it failed.
09124                 */
09125                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09126                break;
09127             } else if (spill_result) {
09128                spill_done = 1;
09129             }
09130          } else {
09131             /* keep reading data until the energy level drops below the threshold
09132                so we don't get another 'trigger' on the remaining carrier signal
09133             */
09134             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09135                break;
09136          }
09137          if (samples > (8000 * 4)) /*Termination case - time to give up*/
09138             break;
09139       }
09140    }
09141 
09142    if (spill_result == 1) {
09143       callerid_get(cs, &name, &number, &flags);
09144       if (flags & CID_MSGWAITING) {
09145          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09146          notify_message(mtd->pvt->mailbox, 1);
09147       } else if (flags & CID_NOMSGWAITING) {
09148          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09149          notify_message(mtd->pvt->mailbox, 0);
09150       } else {
09151          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09152       }
09153    }
09154 
09155 
09156 quit:
09157    callerid_free(cs);
09158 
09159    restore_gains(mtd->pvt);
09160 
09161 quit_no_clean:
09162    mtd->pvt->mwimonitoractive = 0;
09163 
09164    ast_free(mtd);
09165 
09166    return NULL;
09167 }
09168 
09169 /*
09170 * The following three functions (mwi_send_init, mwi_send_process_buffer,
09171 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
09172 * that are sent out via FXA port on voicemail state change.  The execution of
09173 * the mwi send is state driven and can either generate a ring pulse prior to
09174 * sending the fsk spill or simply send an fsk spill.
09175 */
09176 static int mwi_send_init(struct dahdi_pvt * pvt)
09177 {
09178    int x, res;
09179 
09180 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09181    /* Determine how this spill is to be sent */
09182    if (pvt->mwisend_rpas) {
09183       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09184       pvt->mwisendactive = 1;
09185    } else if (pvt->mwisend_fsk) {
09186       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09187       pvt->mwisendactive = 1;
09188    } else {
09189       pvt->mwisendactive = 0;
09190       return 0;
09191    }
09192 #else
09193    if (mwisend_rpas) {
09194       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09195    } else {
09196       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09197    }
09198    pvt->mwisendactive = 1;
09199 #endif
09200 
09201    if (pvt->cidspill) {
09202       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09203       ast_free(pvt->cidspill);
09204       pvt->cidspill = NULL;
09205       pvt->cidpos = 0;
09206       pvt->cidlen = 0;
09207    }
09208    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09209    if (!pvt->cidspill) {
09210       pvt->mwisendactive = 0;
09211       return -1;
09212    }
09213    x = DAHDI_FLUSH_BOTH;
09214    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09215    x = 3000;
09216    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09217 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09218    if (pvt->mwisend_fsk) {
09219 #endif
09220       pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09221                         AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09222       pvt->cidpos = 0;
09223 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09224    }
09225 #endif
09226    return 0;
09227 }
09228 
09229 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09230 {
09231    struct timeval    now;
09232    int         res;
09233 
09234    /* sanity check to catch if this had been interrupted previously
09235    *  i.e. state says there is more to do but there is no spill allocated
09236    */
09237    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09238       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09239    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09240       /* Normal processing -- Perform mwi send action */
09241       switch ( pvt->mwisend_data.mwisend_current) {
09242       case MWI_SEND_SA:
09243          /* Send the Ring Pulse Signal Alert */
09244          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09245          if (res) {
09246             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09247             goto quit;
09248          }
09249          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09250          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09251          break;
09252       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
09253          break;
09254       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
09255 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09256          if (pvt->mwisend_fsk) {
09257 #endif
09258             gettimeofday(&now, NULL);
09259             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09260                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09261             }
09262 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09263          } else { /* support for mwisendtype=nofsk */
09264             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09265          }
09266 #endif
09267          break;
09268       case MWI_SEND_SPILL:
09269          /* We read some number of bytes.  Write an equal amount of data */
09270          if(0 < num_read) {
09271             if (num_read > pvt->cidlen - pvt->cidpos)
09272                num_read = pvt->cidlen - pvt->cidpos;
09273             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09274             if (res > 0) {
09275                pvt->cidpos += res;
09276                if (pvt->cidpos >= pvt->cidlen) {
09277                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09278                }
09279             } else {
09280                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09281                goto quit;
09282             }
09283          }
09284          break;
09285       case MWI_SEND_CLEANUP:
09286          /* For now, do nothing */
09287          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09288          break;
09289       default:
09290          /* Should not get here, punt*/
09291          goto quit;
09292       }
09293    }
09294 
09295    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09296       if (pvt->cidspill) {
09297          ast_free(pvt->cidspill);
09298          pvt->cidspill = NULL;
09299          pvt->cidpos = 0;
09300          pvt->cidlen = 0;
09301       }
09302       pvt->mwisendactive = 0;
09303    }
09304    return 0;
09305 quit:
09306    if (pvt->cidspill) {
09307       ast_free(pvt->cidspill);
09308       pvt->cidspill = NULL;
09309       pvt->cidpos = 0;
09310       pvt->cidlen = 0;
09311    }
09312    pvt->mwisendactive = 0;
09313    return -1;
09314 }
09315 
09316 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09317 {
09318    int handled = 0;
09319 
09320    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09321       switch (event) {
09322       case DAHDI_EVENT_RINGEROFF:
09323          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09324             handled = 1;
09325 
09326             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09327                ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09328                if(pvt->cidspill) {
09329                   ast_free(pvt->cidspill);
09330                   pvt->cidspill = NULL;
09331                }
09332                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09333                pvt->mwisendactive = 0;
09334             } else {
09335                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09336                gettimeofday(&pvt->mwisend_data.pause, NULL);
09337             }
09338          }
09339          break;
09340       /* Going off hook, I need to punt this spill */
09341       case DAHDI_EVENT_RINGOFFHOOK:
09342          if (pvt->cidspill) {
09343             ast_free(pvt->cidspill);
09344             pvt->cidspill = NULL;
09345             pvt->cidpos = 0;
09346             pvt->cidlen = 0;
09347          }
09348          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09349          pvt->mwisendactive = 0;
09350          break;
09351       case DAHDI_EVENT_RINGERON:
09352       case DAHDI_EVENT_HOOKCOMPLETE:
09353          break;
09354       default:
09355          break;
09356       }
09357    }
09358    return handled;
09359 }
09360 
09361 /* destroy a DAHDI channel, identified by its number */
09362 static int dahdi_destroy_channel_bynum(int channel)
09363 {
09364    struct dahdi_pvt *tmp = NULL;
09365    struct dahdi_pvt *prev = NULL;
09366 
09367    tmp = iflist;
09368    while (tmp) {
09369       if (tmp->channel == channel) {
09370          int x = DAHDI_FLASH;
09371          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
09372          destroy_channel(prev, tmp, 1);
09373          ast_module_unref(ast_module_info->self);
09374          return RESULT_SUCCESS;
09375       }
09376       prev = tmp;
09377       tmp = tmp->next;
09378    }
09379    return RESULT_FAILURE;
09380 }
09381 
09382 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09383 {
09384    int res;
09385    pthread_t threadid;
09386    struct ast_channel *chan;
09387 
09388    /* Handle an event on a given channel for the monitor thread. */
09389 
09390    switch (event) {
09391    case DAHDI_EVENT_NONE:
09392    case DAHDI_EVENT_BITSCHANGED:
09393       break;
09394    case DAHDI_EVENT_WINKFLASH:
09395    case DAHDI_EVENT_RINGOFFHOOK:
09396       if (i->inalarm) break;
09397       if (i->radio) break;
09398       /* Got a ring/answer.  What kind of channel are we? */
09399       switch (i->sig) {
09400       case SIG_FXOLS:
09401       case SIG_FXOGS:
09402       case SIG_FXOKS:
09403          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09404          i->fxsoffhookstate = 1;
09405          if (res && (errno == EBUSY))
09406             break;
09407          if (i->cidspill) {
09408             /* Cancel VMWI spill */
09409             ast_free(i->cidspill);
09410             i->cidspill = NULL;
09411          }
09412          if (i->immediate) {
09413             dahdi_enable_ec(i);
09414             /* The channel is immediately up.  Start right away */
09415             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09416             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09417             if (!chan) {
09418                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09419                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09420                if (res < 0)
09421                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09422             }
09423          } else {
09424             /* Check for callerid, digits, etc */
09425             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09426             if (chan) {
09427                if (has_voicemail(i))
09428                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09429                else
09430                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09431                if (res < 0)
09432                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09433                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09434                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09435                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09436                   if (res < 0)
09437                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09438                   ast_hangup(chan);
09439                }
09440             } else
09441                ast_log(LOG_WARNING, "Unable to create channel\n");
09442          }
09443          break;
09444       case SIG_FXSLS:
09445       case SIG_FXSGS:
09446       case SIG_FXSKS:
09447             i->ringt = i->ringt_base;
09448             /* Fall through */
09449       case SIG_EMWINK:
09450       case SIG_FEATD:
09451       case SIG_FEATDMF:
09452       case SIG_FEATDMF_TA:
09453       case SIG_E911:
09454       case SIG_FGC_CAMA:
09455       case SIG_FGC_CAMAMF:
09456       case SIG_FEATB:
09457       case SIG_EM:
09458       case SIG_EM_E1:
09459       case SIG_SFWINK:
09460       case SIG_SF_FEATD:
09461       case SIG_SF_FEATDMF:
09462       case SIG_SF_FEATB:
09463       case SIG_SF:
09464          /* Check for callerid, digits, etc */
09465          if (i->cid_start == CID_START_POLARITY_IN) {
09466             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09467          } else {
09468             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09469          }
09470 
09471          if (!chan) {
09472             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09473          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09474             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09475             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09476             if (res < 0) {
09477                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09478             }
09479             ast_hangup(chan);
09480          }
09481          break;
09482       default:
09483          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09484          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09485          if (res < 0)
09486             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09487          return NULL;
09488       }
09489       break;
09490    case DAHDI_EVENT_NOALARM:
09491       i->inalarm = 0;
09492       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09493       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09494          "Channel: %d\r\n", i->channel);
09495       break;
09496    case DAHDI_EVENT_ALARM:
09497       i->inalarm = 1;
09498       res = get_alarms(i);
09499       handle_alarms(i, res);
09500       /* fall thru intentionally */
09501    case DAHDI_EVENT_ONHOOK:
09502       if (i->radio)
09503          break;
09504       /* Back on hook.  Hang up. */
09505       switch (i->sig) {
09506       case SIG_FXOLS:
09507       case SIG_FXOGS:
09508       case SIG_FEATD:
09509       case SIG_FEATDMF:
09510       case SIG_FEATDMF_TA:
09511       case SIG_E911:
09512       case SIG_FGC_CAMA:
09513       case SIG_FGC_CAMAMF:
09514       case SIG_FEATB:
09515       case SIG_EM:
09516       case SIG_EM_E1:
09517       case SIG_EMWINK:
09518       case SIG_SF_FEATD:
09519       case SIG_SF_FEATDMF:
09520       case SIG_SF_FEATB:
09521       case SIG_SF:
09522       case SIG_SFWINK:
09523       case SIG_FXSLS:
09524       case SIG_FXSGS:
09525       case SIG_FXSKS:
09526       case SIG_GR303FXSKS:
09527          dahdi_disable_ec(i);
09528          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09529          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09530          break;
09531       case SIG_GR303FXOKS:
09532       case SIG_FXOKS:
09533          dahdi_disable_ec(i);
09534          /* Diddle the battery for the zhone */
09535 #ifdef ZHONE_HACK
09536          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09537          usleep(1);
09538 #endif
09539          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09540          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09541          break;
09542       case SIG_PRI:
09543       case SIG_SS7:
09544       case SIG_BRI:
09545       case SIG_BRI_PTMP:
09546          dahdi_disable_ec(i);
09547          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09548          break;
09549       default:
09550          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09551          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09552          return NULL;
09553       }
09554       if (i->sig & __DAHDI_SIG_FXO) {
09555          i->fxsoffhookstate = 0;
09556       }
09557       break;
09558    case DAHDI_EVENT_POLARITY:
09559       switch (i->sig) {
09560       case SIG_FXSLS:
09561       case SIG_FXSKS:
09562       case SIG_FXSGS:
09563          /* We have already got a PR before the channel was
09564             created, but it wasn't handled. We need polarity
09565             to be REV for remote hangup detection to work.
09566             At least in Spain */
09567          if (i->hanguponpolarityswitch)
09568             i->polarity = POLARITY_REV;
09569          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09570             i->polarity = POLARITY_REV;
09571             ast_verb(2, "Starting post polarity "
09572                "CID detection on channel %d\n",
09573                i->channel);
09574             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09575             if (!chan) {
09576                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09577             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09578                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09579             }
09580          }
09581          break;
09582       default:
09583          ast_log(LOG_WARNING, "handle_init_event detected "
09584             "polarity reversal on non-FXO (SIG_FXS) "
09585             "interface %d\n", i->channel);
09586       }
09587       break;
09588    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
09589       ast_log(LOG_NOTICE,
09590             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09591             i->channel);
09592       return i;
09593    case DAHDI_EVENT_NEONMWI_ACTIVE:
09594       if (i->mwimonitor_neon) {
09595          notify_message(i->mailbox, 1);
09596          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09597       }
09598       break;
09599    case DAHDI_EVENT_NEONMWI_INACTIVE:
09600       if (i->mwimonitor_neon) {
09601          notify_message(i->mailbox, 0);
09602          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09603       }
09604       break;
09605    }
09606    return NULL;
09607 }
09608 
09609 static void *do_monitor(void *data)
09610 {
09611    int count, res, res2, spoint, pollres=0;
09612    struct dahdi_pvt *i;
09613    struct dahdi_pvt *last = NULL;
09614    struct dahdi_pvt *doomed;
09615    time_t thispass = 0, lastpass = 0;
09616    int found;
09617    char buf[1024];
09618    struct pollfd *pfds=NULL;
09619    int lastalloc = -1;
09620    /* This thread monitors all the frame relay interfaces which are not yet in use
09621       (and thus do not have a separate thread) indefinitely */
09622    /* From here on out, we die whenever asked */
09623 #if 0
09624    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09625       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09626       return NULL;
09627    }
09628    ast_debug(1, "Monitor starting...\n");
09629 #endif
09630    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09631 
09632    for (;;) {
09633       /* Lock the interface list */
09634       ast_mutex_lock(&iflock);
09635       if (!pfds || (lastalloc != ifcount)) {
09636          if (pfds) {
09637             ast_free(pfds);
09638             pfds = NULL;
09639          }
09640          if (ifcount) {
09641             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09642                ast_mutex_unlock(&iflock);
09643                return NULL;
09644             }
09645          }
09646          lastalloc = ifcount;
09647       }
09648       /* Build the stuff we're going to poll on, that is the socket of every
09649          dahdi_pvt that does not have an associated owner channel */
09650       count = 0;
09651       i = iflist;
09652       while (i) {
09653          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09654             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09655                /* This needs to be watched, as it lacks an owner */
09656                pfds[count].fd = i->subs[SUB_REAL].dfd;
09657                pfds[count].events = POLLPRI;
09658                pfds[count].revents = 0;
09659                /* If we are monitoring for VMWI or sending CID, we need to
09660                   read from the channel as well */
09661                if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09662                   pfds[count].events |= POLLIN;
09663                count++;
09664             }
09665          }
09666          i = i->next;
09667       }
09668       /* Okay, now that we know what to do, release the interface lock */
09669       ast_mutex_unlock(&iflock);
09670 
09671       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09672       pthread_testcancel();
09673       /* Wait at least a second for something to happen */
09674       res = poll(pfds, count, 1000);
09675       pthread_testcancel();
09676       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09677 
09678       /* Okay, poll has finished.  Let's see what happened.  */
09679       if (res < 0) {
09680          if ((errno != EAGAIN) && (errno != EINTR))
09681             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09682          continue;
09683       }
09684       /* Alright, lock the interface list again, and let's look and see what has
09685          happened */
09686       ast_mutex_lock(&iflock);
09687       found = 0;
09688       spoint = 0;
09689       lastpass = thispass;
09690       thispass = time(NULL);
09691       i = iflist;
09692       doomed = NULL;
09693       for (i = iflist;; i = i->next) {
09694          if (doomed) {
09695             int res;
09696             res = dahdi_destroy_channel_bynum(doomed->channel);
09697             if (!res) {
09698                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09699             }
09700             doomed = NULL;
09701          }
09702          if (!i) {
09703             break;
09704          }
09705 
09706          if (thispass != lastpass) {
09707             if (!found && ((i == last) || ((i == iflist) && !last))) {
09708                last = i;
09709                if (last) {
09710                   /* Only allow MWI to be initiated on a quiescent fxs port */
09711                   if (!last->mwisendactive &&   last->sig & __DAHDI_SIG_FXO &&
09712                         !last->fxsoffhookstate && !last->owner &&
09713                         !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09714                      res = has_voicemail(last);
09715                      if (last->msgstate != res) {
09716                         /* Set driver resources for signalling VMWI */
09717                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09718                         if (res2) {
09719                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
09720                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09721                         }
09722                         /* If enabled for FSK spill then initiate it */
09723                         if (mwi_send_init(last)) {
09724                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09725                         }
09726                         last->msgstate = res;
09727                         found ++;
09728                      }
09729                   }
09730                   last = last->next;
09731                }
09732             }
09733          }
09734          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09735             if (i->radio && !i->owner)
09736             {
09737                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09738                if (res)
09739                {
09740                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09741                   /* Don't hold iflock while handling init events */
09742                   ast_mutex_unlock(&iflock);
09743                   doomed = handle_init_event(i, res);
09744                   ast_mutex_lock(&iflock);
09745                }
09746                continue;
09747             }
09748             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09749             if (pollres & POLLIN) {
09750                if (i->owner || i->subs[SUB_REAL].owner) {
09751 #ifdef HAVE_PRI
09752                   if (!i->pri)
09753 #endif
09754                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09755                   continue;
09756                }
09757                if (!i->mwimonitor_fsk && !i->mwisendactive) {
09758                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09759                   continue;
09760                }
09761                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09762                if (res > 0) {
09763                   if (i->mwimonitor_fsk) {
09764                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09765                         pthread_attr_t attr;
09766                         pthread_t threadid;
09767                         struct mwi_thread_data *mtd;
09768 
09769                         pthread_attr_init(&attr);
09770                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09771 
09772                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09773                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09774                            mtd->pvt = i;
09775                            memcpy(mtd->buf, buf, res);
09776                            mtd->len = res;
09777                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09778                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09779                               ast_free(mtd);
09780                            }
09781                            i->mwimonitoractive = 1;
09782                         }
09783                      }
09784                   }
09785                   if (i->mwisendactive) {
09786                      mwi_send_process_buffer(i, res);
09787                   }
09788                } else {
09789                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09790                }
09791             }
09792             if (pollres & POLLPRI) {
09793                if (i->owner || i->subs[SUB_REAL].owner) {
09794 #ifdef HAVE_PRI
09795                   if (!i->pri)
09796 #endif
09797                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09798                   continue;
09799                }
09800                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09801                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09802                /* Don't hold iflock while handling init events */
09803                ast_mutex_unlock(&iflock);
09804                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09805                   doomed = handle_init_event(i, res);
09806                }
09807                ast_mutex_lock(&iflock);
09808             }
09809          }
09810       }
09811       ast_mutex_unlock(&iflock);
09812    }
09813    /* Never reached */
09814    return NULL;
09815 
09816 }
09817 
09818 static int restart_monitor(void)
09819 {
09820    /* If we're supposed to be stopped -- stay stopped */
09821    if (monitor_thread == AST_PTHREADT_STOP)
09822       return 0;
09823    ast_mutex_lock(&monlock);
09824    if (monitor_thread == pthread_self()) {
09825       ast_mutex_unlock(&monlock);
09826       ast_log(LOG_WARNING, "Cannot kill myself\n");
09827       return -1;
09828    }
09829    if (monitor_thread != AST_PTHREADT_NULL) {
09830       /* Wake up the thread */
09831       pthread_kill(monitor_thread, SIGURG);
09832    } else {
09833       /* Start a new monitor */
09834       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09835          ast_mutex_unlock(&monlock);
09836          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09837          return -1;
09838       }
09839    }
09840    ast_mutex_unlock(&monlock);
09841    return 0;
09842 }
09843 
09844 #if defined(HAVE_PRI)
09845 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
09846 {
09847    int x;
09848    int trunkgroup;
09849    /* Get appropriate trunk group if there is one */
09850    trunkgroup = pris[*span].mastertrunkgroup;
09851    if (trunkgroup) {
09852       /* Select a specific trunk group */
09853       for (x = 0; x < NUM_SPANS; x++) {
09854          if (pris[x].trunkgroup == trunkgroup) {
09855             *span = x;
09856             return 0;
09857          }
09858       }
09859       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09860       *span = -1;
09861    } else {
09862       if (pris[*span].trunkgroup) {
09863          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09864          *span = -1;
09865       } else if (pris[*span].mastertrunkgroup) {
09866          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09867          *span = -1;
09868       } else {
09869          if (si->totalchans == 31) {
09870             /* E1 */
09871             pris[*span].dchannels[0] = 16 + offset;
09872          } else if (si->totalchans == 24) {
09873             /* T1 or J1 */
09874             pris[*span].dchannels[0] = 24 + offset;
09875          } else if (si->totalchans == 3) {
09876             /* BRI */
09877             pris[*span].dchannels[0] = 3 + offset;
09878          } else {
09879             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
09880             *span = -1;
09881             return 0;
09882          }
09883          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09884          pris[*span].offset = offset;
09885          pris[*span].span = *span + 1;
09886       }
09887    }
09888    return 0;
09889 }
09890 #endif   /* defined(HAVE_PRI) */
09891 
09892 #if defined(HAVE_PRI)
09893 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09894 {
09895    struct dahdi_spaninfo si;
09896    struct dahdi_params p;
09897    int fd;
09898    int span;
09899    int ospan=0;
09900    int x,y;
09901    for (x = 0; x < NUM_SPANS; x++) {
09902       if (pris[x].trunkgroup == trunkgroup) {
09903          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09904          return -1;
09905       }
09906    }
09907    for (y = 0; y < NUM_DCHANS; y++) {
09908       if (!channels[y])
09909          break;
09910       memset(&si, 0, sizeof(si));
09911       memset(&p, 0, sizeof(p));
09912       fd = open("/dev/dahdi/channel", O_RDWR);
09913       if (fd < 0) {
09914          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09915          return -1;
09916       }
09917       x = channels[y];
09918       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09919          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09920          close(fd);
09921          return -1;
09922       }
09923       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09924          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09925          return -1;
09926       }
09927       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09928          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09929          close(fd);
09930          return -1;
09931       }
09932       span = p.spanno - 1;
09933       if (pris[span].trunkgroup) {
09934          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09935          close(fd);
09936          return -1;
09937       }
09938       if (pris[span].pvts[0]) {
09939          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09940          close(fd);
09941          return -1;
09942       }
09943       if (!y) {
09944          pris[span].trunkgroup = trunkgroup;
09945          pris[span].offset = channels[y] - p.chanpos;
09946          ospan = span;
09947       }
09948       pris[ospan].dchannels[y] = channels[y];
09949       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09950       pris[span].span = span + 1;
09951       close(fd);
09952    }
09953    return 0;
09954 }
09955 #endif   /* defined(HAVE_PRI) */
09956 
09957 #if defined(HAVE_PRI)
09958 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09959 {
09960    if (pris[span].mastertrunkgroup) {
09961       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
09962       return -1;
09963    }
09964    pris[span].mastertrunkgroup = trunkgroup;
09965    pris[span].prilogicalspan = logicalspan;
09966    return 0;
09967 }
09968 #endif   /* defined(HAVE_PRI) */
09969 
09970 #if defined(HAVE_SS7)
09971 static unsigned int parse_pointcode(const char *pcstring)
09972 {
09973    unsigned int code1, code2, code3;
09974    int numvals;
09975 
09976    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09977    if (numvals == 1)
09978       return code1;
09979    if (numvals == 3)
09980       return (code1 << 16) | (code2 << 8) | code3;
09981 
09982    return 0;
09983 }
09984 #endif   /* defined(HAVE_SS7) */
09985 
09986 #if defined(HAVE_SS7)
09987 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
09988 {
09989    if ((linkset < 0) || (linkset >= NUM_SPANS))
09990       return NULL;
09991    else
09992       return &linksets[linkset - 1];
09993 }
09994 #endif   /* defined(HAVE_SS7) */
09995 
09996 #ifdef HAVE_OPENR2
09997 static void dahdi_r2_destroy_links(void)
09998 {
09999    int i = 0;
10000    if (!r2links) {
10001       return;
10002    }
10003    for (; i < r2links_count; i++) {
10004       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10005          pthread_cancel(r2links[i]->r2master);
10006          pthread_join(r2links[i]->r2master, NULL);
10007          openr2_context_delete(r2links[i]->protocol_context);
10008       }
10009       ast_free(r2links[i]);
10010    }
10011    ast_free(r2links);
10012    r2links = NULL;
10013    r2links_count = 0;
10014 }
10015 
10016 #define R2_LINK_CAPACITY 10
10017 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10018 {
10019    struct dahdi_mfcr2 *new_r2link = NULL;
10020    struct dahdi_mfcr2 **new_r2links = NULL;
10021    /* this function is called just when starting up and no monitor threads have been launched,
10022       no need to lock monitored_count member */
10023    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10024       new_r2link = ast_calloc(1, sizeof(**r2links));
10025       if (!new_r2link) {
10026          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10027          return NULL;
10028       }
10029       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10030       if (!new_r2links) {
10031          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10032          ast_free(new_r2link);
10033          return NULL;
10034       }
10035       r2links = new_r2links;
10036       new_r2link->r2master = AST_PTHREADT_NULL;
10037       r2links[r2links_count] = new_r2link;
10038       r2links_count++;
10039       ast_log(LOG_DEBUG, "Created new R2 link!\n");
10040    }
10041    return r2links[r2links_count - 1];
10042 }
10043 
10044 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10045 {
10046    char tmplogdir[] = "/tmp";
10047    char logdir[OR2_MAX_PATH];
10048    int threshold = 0;
10049    int snres = 0;
10050    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10051          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10052          conf->mfcr2.max_dnis);
10053    if (!r2_link->protocol_context) {
10054       return -1;
10055    }
10056    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10057    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10058 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10059    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10060 #endif
10061    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10062    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10063    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10064    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10065    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10066    if (ast_strlen_zero(conf->mfcr2.logdir)) {
10067       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10068          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10069       }
10070    } else {
10071       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10072       if (snres >= sizeof(logdir)) {
10073          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10074          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10075             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10076          }
10077       } else {
10078          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10079             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10080          }
10081       }
10082    }
10083    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10084       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10085          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10086       }
10087    }
10088    r2_link->monitored_count = 0;
10089    return 0;
10090 }
10091 #endif
10092 
10093 /* converts a DAHDI sigtype to signalling as can be configured from
10094  * chan_dahdi.conf.
10095  * While both have basically the same values, this will later be the
10096  * place to add filters and sanity checks
10097  */
10098 static int sigtype_to_signalling(int sigtype)
10099 {
10100    return sigtype;
10101 }
10102 
10103 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10104 {
10105    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
10106    struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10107    char fn[80];
10108    struct dahdi_bufferinfo bi;
10109 
10110    int res;
10111    int span = 0;
10112    int here = 0;
10113    int x;
10114    struct dahdi_pvt **wlist;
10115    struct dahdi_pvt **wend;
10116    struct dahdi_params p;
10117 
10118    wlist = &iflist;
10119    wend = &ifend;
10120 
10121 #ifdef HAVE_PRI
10122    if (pri) {
10123       wlist = &pri->crvs;
10124       wend = &pri->crvend;
10125    }
10126 #endif
10127 
10128    tmp2 = *wlist;
10129    prev = NULL;
10130 
10131    while (tmp2) {
10132       if (!tmp2->destroy) {
10133          if (tmp2->channel == channel) {
10134             tmp = tmp2;
10135             here = 1;
10136             break;
10137          }
10138          if (tmp2->channel > channel) {
10139             break;
10140          }
10141       }
10142       prev = tmp2;
10143       tmp2 = tmp2->next;
10144    }
10145 
10146    if (!here && reloading != 1) {
10147       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10148          if (tmp)
10149             free(tmp);
10150          return NULL;
10151       }
10152       ast_mutex_init(&tmp->lock);
10153       ifcount++;
10154       for (x = 0; x < 3; x++)
10155          tmp->subs[x].dfd = -1;
10156       tmp->channel = channel;
10157       tmp->priindication_oob = conf->chan.priindication_oob;
10158    }
10159 
10160    if (tmp) {
10161       int chan_sig = conf->chan.sig;
10162       if (!here) {
10163          if ((channel != CHAN_PSEUDO) && !pri) {
10164             int count = 0;
10165             snprintf(fn, sizeof(fn), "%d", channel);
10166             /* Open non-blocking */
10167             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10168             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
10169                usleep(1);
10170                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10171                count++;
10172             }
10173             /* Allocate a DAHDI structure */
10174             if (tmp->subs[SUB_REAL].dfd < 0) {
10175                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
10176                destroy_dahdi_pvt(&tmp);
10177                return NULL;
10178             }
10179             memset(&p, 0, sizeof(p));
10180             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10181             if (res < 0) {
10182                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10183                destroy_dahdi_pvt(&tmp);
10184                return NULL;
10185             }
10186             if (conf->is_sig_auto)
10187                chan_sig = sigtype_to_signalling(p.sigtype);
10188             if (p.sigtype != (chan_sig & 0x3ffff)) {
10189                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
10190                destroy_dahdi_pvt(&tmp);
10191                return NULL;
10192             }
10193             tmp->law = p.curlaw;
10194             tmp->span = p.spanno;
10195             span = p.spanno - 1;
10196          } else {
10197             if (channel == CHAN_PSEUDO)
10198                chan_sig = 0;
10199             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10200                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10201                return NULL;
10202             }
10203          }
10204          tmp->outsigmod = conf->chan.outsigmod;
10205 
10206 #ifdef HAVE_SS7
10207          if (chan_sig == SIG_SS7) {
10208             struct dahdi_ss7 *ss7;
10209             int clear = 0;
10210             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10211                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10212                destroy_dahdi_pvt(&tmp);
10213                return NULL;
10214             }
10215 
10216             ss7 = ss7_resolve_linkset(cur_linkset);
10217             if (!ss7) {
10218                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10219                destroy_dahdi_pvt(&tmp);
10220                return NULL;
10221             }
10222             if (cur_cicbeginswith < 0) {
10223                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10224                destroy_dahdi_pvt(&tmp);
10225                return NULL;
10226             }
10227 
10228             tmp->cic = cur_cicbeginswith++;
10229 
10230             /* DB: Add CIC's DPC information */
10231             tmp->dpc = cur_defaultdpc;
10232 
10233             tmp->ss7 = ss7;
10234             tmp->ss7call = NULL;
10235             ss7->pvts[ss7->numchans++] = tmp;
10236 
10237             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10238             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10239             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10240             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10241 
10242             ss7->called_nai = conf->ss7.called_nai;
10243             ss7->calling_nai = conf->ss7.calling_nai;
10244          }
10245 #endif
10246 #ifdef HAVE_OPENR2
10247          if (chan_sig == SIG_MFCR2 && reloading != 1) {
10248             struct dahdi_mfcr2 *r2_link;
10249             r2_link = dahdi_r2_get_link();
10250             if (!r2_link) {
10251                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10252                destroy_dahdi_pvt(&tmp);
10253                return NULL;
10254             }
10255             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10256                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10257                destroy_dahdi_pvt(&tmp);
10258                return NULL;
10259             }
10260             if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10261                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10262                destroy_dahdi_pvt(&tmp);
10263                return NULL;
10264             }
10265             r2_link->pvts[r2_link->numchans++] = tmp;
10266             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10267                                         tmp->subs[SUB_REAL].dfd,
10268                                         NULL, NULL);
10269             if (!tmp->r2chan) {
10270                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10271                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10272                destroy_dahdi_pvt(&tmp);
10273                return NULL;
10274             }
10275             tmp->mfcr2 = r2_link;
10276             if (conf->mfcr2.call_files) {
10277                openr2_chan_enable_call_files(tmp->r2chan);
10278             }
10279             openr2_chan_set_client_data(tmp->r2chan, tmp);
10280             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10281             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10282             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10283             tmp->mfcr2_category = conf->mfcr2.category;
10284             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10285             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10286             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10287             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10288             tmp->mfcr2call = 0;
10289             tmp->mfcr2_dnis_index = 0;
10290             tmp->mfcr2_ani_index = 0;
10291             r2_link->monitored_count++;
10292          }
10293 #endif
10294 #ifdef HAVE_PRI
10295          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10296             int offset;
10297             int myswitchtype;
10298             int matchesdchan;
10299             int x,y;
10300             offset = 0;
10301             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10302                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10303                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10304                destroy_dahdi_pvt(&tmp);
10305                return NULL;
10306             }
10307             if (span >= NUM_SPANS) {
10308                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10309                destroy_dahdi_pvt(&tmp);
10310                return NULL;
10311             } else {
10312                struct dahdi_spaninfo si;
10313                si.spanno = 0;
10314                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10315                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10316                   destroy_dahdi_pvt(&tmp);
10317                   return NULL;
10318                }
10319                /* Store the logical span first based upon the real span */
10320                tmp->logicalspan = pris[span].prilogicalspan;
10321                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10322                if (span < 0) {
10323                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10324                   destroy_dahdi_pvt(&tmp);
10325                   return NULL;
10326                }
10327                if ((chan_sig == SIG_PRI) ||
10328                      (chan_sig == SIG_BRI) ||
10329                      (chan_sig == SIG_BRI_PTMP))
10330                   myswitchtype = conf->pri.switchtype;
10331                else
10332                   myswitchtype = PRI_SWITCH_GR303_TMC;
10333                /* Make sure this isn't a d-channel */
10334                matchesdchan=0;
10335                for (x = 0; x < NUM_SPANS; x++) {
10336                   for (y = 0; y < NUM_DCHANS; y++) {
10337                      if (pris[x].dchannels[y] == tmp->channel) {
10338                         matchesdchan = 1;
10339                         break;
10340                      }
10341                   }
10342                }
10343                offset = p.chanpos;
10344                if (!matchesdchan) {
10345                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10346                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10347                      destroy_dahdi_pvt(&tmp);
10348                      return NULL;
10349                   }
10350                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10351                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10352                      destroy_dahdi_pvt(&tmp);
10353                      return NULL;
10354                   }
10355                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10356                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10357                      destroy_dahdi_pvt(&tmp);
10358                      return NULL;
10359                   }
10360                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10361                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10362                      destroy_dahdi_pvt(&tmp);
10363                      return NULL;
10364                   }
10365                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10366                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10367                      destroy_dahdi_pvt(&tmp);
10368                      return NULL;
10369                   }
10370                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10371                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10372                      destroy_dahdi_pvt(&tmp);
10373                      return NULL;
10374                   }
10375                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10376                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10377                      destroy_dahdi_pvt(&tmp);
10378                      return NULL;
10379                   }
10380                   if (pris[span].numchans >= MAX_CHANNELS) {
10381                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10382                         pris[span].trunkgroup);
10383                      destroy_dahdi_pvt(&tmp);
10384                      return NULL;
10385                   }
10386 
10387                   pris[span].sig = chan_sig;
10388                   pris[span].nodetype = conf->pri.nodetype;
10389                   pris[span].switchtype = myswitchtype;
10390                   pris[span].nsf = conf->pri.nsf;
10391                   pris[span].dialplan = conf->pri.dialplan;
10392                   pris[span].localdialplan = conf->pri.localdialplan;
10393                   pris[span].pvts[pris[span].numchans++] = tmp;
10394                   pris[span].minunused = conf->pri.minunused;
10395                   pris[span].minidle = conf->pri.minidle;
10396                   pris[span].overlapdial = conf->pri.overlapdial;
10397                   pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10398                   pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10399 #ifdef HAVE_PRI_INBANDDISCONNECT
10400                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10401 #endif
10402                   pris[span].facilityenable = conf->pri.facilityenable;
10403                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10404                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10405                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10406                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10407                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10408                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10409                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10410                   pris[span].resetinterval = conf->pri.resetinterval;
10411 
10412                   tmp->pri = &pris[span];
10413                   tmp->prioffset = offset;
10414                   tmp->call = NULL;
10415 
10416                   tmp->priexclusive = conf->chan.priexclusive;
10417                } else {
10418                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10419                   destroy_dahdi_pvt(&tmp);
10420                   return NULL;
10421                }
10422             }
10423          } else {
10424             tmp->prioffset = 0;
10425          }
10426 #endif
10427       } else {
10428          chan_sig = tmp->sig;
10429          if (tmp->subs[SUB_REAL].dfd > -1) {
10430             memset(&p, 0, sizeof(p));
10431             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10432          }
10433       }
10434       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10435       switch (chan_sig) {
10436       case SIG_FXSKS:
10437       case SIG_FXSLS:
10438       case SIG_EM:
10439       case SIG_EM_E1:
10440       case SIG_EMWINK:
10441       case SIG_FEATD:
10442       case SIG_FEATDMF:
10443       case SIG_FEATDMF_TA:
10444       case SIG_FEATB:
10445       case SIG_E911:
10446       case SIG_SF:
10447       case SIG_SFWINK:
10448       case SIG_FGC_CAMA:
10449       case SIG_FGC_CAMAMF:
10450       case SIG_SF_FEATD:
10451       case SIG_SF_FEATDMF:
10452       case SIG_SF_FEATB:
10453          p.starttime = 250;
10454          break;
10455       }
10456 
10457       if (tmp->radio) {
10458          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10459          p.channo = channel;
10460          p.rxwinktime = 1;
10461          p.rxflashtime = 1;
10462          p.starttime = 1;
10463          p.debouncetime = 5;
10464       }
10465       if (!tmp->radio) {
10466          p.channo = channel;
10467          /* Override timing settings based on config file */
10468          if (conf->timing.prewinktime >= 0)
10469             p.prewinktime = conf->timing.prewinktime;
10470          if (conf->timing.preflashtime >= 0)
10471             p.preflashtime = conf->timing.preflashtime;
10472          if (conf->timing.winktime >= 0)
10473             p.winktime = conf->timing.winktime;
10474          if (conf->timing.flashtime >= 0)
10475             p.flashtime = conf->timing.flashtime;
10476          if (conf->timing.starttime >= 0)
10477             p.starttime = conf->timing.starttime;
10478          if (conf->timing.rxwinktime >= 0)
10479             p.rxwinktime = conf->timing.rxwinktime;
10480          if (conf->timing.rxflashtime >= 0)
10481             p.rxflashtime = conf->timing.rxflashtime;
10482          if (conf->timing.debouncetime >= 0)
10483             p.debouncetime = conf->timing.debouncetime;
10484       }
10485 
10486       /* dont set parms on a pseudo-channel (or CRV) */
10487       if (tmp->subs[SUB_REAL].dfd >= 0)
10488       {
10489          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10490          if (res < 0) {
10491             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10492             destroy_dahdi_pvt(&tmp);
10493             return NULL;
10494          }
10495       }
10496 #if 1
10497       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10498          memset(&bi, 0, sizeof(bi));
10499          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10500          if (!res) {
10501             bi.txbufpolicy = conf->chan.buf_policy;
10502             bi.rxbufpolicy = conf->chan.buf_policy;
10503             bi.numbufs = conf->chan.buf_no;
10504             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10505             if (res < 0) {
10506                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10507             }
10508          } else {
10509             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10510          }
10511          tmp->buf_policy = conf->chan.buf_policy;
10512          tmp->buf_no = conf->chan.buf_no;
10513          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10514          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10515          tmp->faxbuf_no = conf->chan.faxbuf_no;
10516          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10517           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10518           * The reason the ioctl call above failed should to be determined before worrying about the
10519           * faxbuffer-related ioctl calls */
10520          tmp->bufsize = bi.bufsize;
10521       }
10522 #endif
10523       tmp->immediate = conf->chan.immediate;
10524       tmp->transfertobusy = conf->chan.transfertobusy;
10525       if (chan_sig & __DAHDI_SIG_FXS) {
10526          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10527          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10528          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10529       }
10530       tmp->sig = chan_sig;
10531       tmp->ringt_base = ringt_base;
10532       tmp->firstradio = 0;
10533       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10534          tmp->permcallwaiting = conf->chan.callwaiting;
10535       else
10536          tmp->permcallwaiting = 0;
10537       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10538       tmp->destroy = 0;
10539       tmp->drings = conf->chan.drings;
10540 
10541       /* 10 is a nice default. */
10542       if (tmp->drings.ringnum[0].range == 0)
10543          tmp->drings.ringnum[0].range = 10;
10544       if (tmp->drings.ringnum[1].range == 0)
10545          tmp->drings.ringnum[1].range = 10;
10546       if (tmp->drings.ringnum[2].range == 0)
10547          tmp->drings.ringnum[2].range = 10;
10548 
10549       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10550       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10551       tmp->threewaycalling = conf->chan.threewaycalling;
10552       tmp->adsi = conf->chan.adsi;
10553       tmp->use_smdi = conf->chan.use_smdi;
10554       tmp->permhidecallerid = conf->chan.hidecallerid;
10555       tmp->hidecalleridname = conf->chan.hidecalleridname;
10556       tmp->callreturn = conf->chan.callreturn;
10557       tmp->echocancel = conf->chan.echocancel;
10558       tmp->echotraining = conf->chan.echotraining;
10559       tmp->pulse = conf->chan.pulse;
10560       if (tmp->echocancel.head.tap_length) {
10561          tmp->echocanbridged = conf->chan.echocanbridged;
10562       } else {
10563          if (conf->chan.echocanbridged)
10564             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10565          tmp->echocanbridged = 0;
10566       }
10567       tmp->busydetect = conf->chan.busydetect;
10568       tmp->busycount = conf->chan.busycount;
10569       tmp->busy_tonelength = conf->chan.busy_tonelength;
10570       tmp->busy_quietlength = conf->chan.busy_quietlength;
10571       tmp->callprogress = conf->chan.callprogress;
10572       tmp->waitfordialtone = conf->chan.waitfordialtone;
10573       tmp->cancallforward = conf->chan.cancallforward;
10574       tmp->dtmfrelax = conf->chan.dtmfrelax;
10575       tmp->callwaiting = tmp->permcallwaiting;
10576       tmp->hidecallerid = tmp->permhidecallerid;
10577       tmp->channel = channel;
10578       tmp->stripmsd = conf->chan.stripmsd;
10579       tmp->use_callerid = conf->chan.use_callerid;
10580       tmp->cid_signalling = conf->chan.cid_signalling;
10581       tmp->cid_start = conf->chan.cid_start;
10582       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10583       tmp->restrictcid = conf->chan.restrictcid;
10584       tmp->use_callingpres = conf->chan.use_callingpres;
10585       if (tmp->usedistinctiveringdetection) {
10586          if (!tmp->use_callerid) {
10587             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10588             tmp->use_callerid = 1;
10589          }
10590       }
10591 
10592       if (tmp->cid_signalling == CID_SIG_SMDI) {
10593          if (!tmp->use_smdi) {
10594             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10595             tmp->use_smdi = 1;
10596          }
10597       }
10598       if (tmp->use_smdi) {
10599          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10600          if (!(tmp->smdi_iface)) {
10601             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10602             tmp->use_smdi = 0;
10603          }
10604       }
10605 
10606       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10607       tmp->amaflags = conf->chan.amaflags;
10608       if (!here) {
10609          tmp->confno = -1;
10610          tmp->propconfno = -1;
10611       }
10612       tmp->canpark = conf->chan.canpark;
10613       tmp->transfer = conf->chan.transfer;
10614       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10615       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10616       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10617       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10618       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10619       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10620       tmp->cid_ton = 0;
10621       switch (tmp->sig) {
10622       case SIG_PRI:
10623       case SIG_BRI:
10624       case SIG_BRI_PTMP:
10625       case SIG_SS7:
10626       case SIG_MFCR2:
10627          tmp->cid_num[0] = '\0';
10628          tmp->cid_name[0] = '\0';
10629          break;
10630       default:
10631          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10632          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10633          break;
10634       }
10635       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10636       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10637          char *mailbox, *context;
10638          mailbox = context = ast_strdupa(tmp->mailbox);
10639          strsep(&context, "@");
10640          if (ast_strlen_zero(context))
10641             context = "default";
10642          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10643             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10644             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10645             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10646             AST_EVENT_IE_END);
10647       }
10648       tmp->msgstate = -1;
10649 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10650       tmp->mwisend_setting = conf->chan.mwisend_setting;
10651       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
10652       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10653 #endif
10654       if (chan_sig & __DAHDI_SIG_FXO) {
10655          memset(&p, 0, sizeof(p));
10656          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10657          if (!res) {
10658             tmp->fxsoffhookstate = p.rxisoffhook;
10659          }
10660 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10661          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10662 #endif
10663       }
10664       tmp->onhooktime = time(NULL);
10665       tmp->group = conf->chan.group;
10666       tmp->callgroup = conf->chan.callgroup;
10667       tmp->pickupgroup= conf->chan.pickupgroup;
10668       if (conf->chan.vars) {
10669          struct ast_variable *v, *tmpvar;
10670                    for (v = conf->chan.vars ; v ; v = v->next) {
10671                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10672                                   tmpvar->next = tmp->vars;
10673                                    tmp->vars = tmpvar;
10674                            }
10675                   }
10676       }
10677       tmp->cid_rxgain = conf->chan.cid_rxgain;
10678       tmp->rxgain = conf->chan.rxgain;
10679       tmp->txgain = conf->chan.txgain;
10680       tmp->tonezone = conf->chan.tonezone;
10681       if (tmp->subs[SUB_REAL].dfd > -1) {
10682          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10683          if (tmp->dsp)
10684             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10685          update_conf(tmp);
10686          if (!here) {
10687             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10688                 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10689                /* Hang it up to be sure it's good */
10690                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10691          }
10692          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10693 #ifdef HAVE_PRI
10694          /* the dchannel is down so put the channel in alarm */
10695          if (tmp->pri && !pri_is_up(tmp->pri))
10696             tmp->inalarm = 1;
10697 #endif
10698          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10699             tmp->inalarm = 1;
10700             handle_alarms(tmp, res);
10701          }
10702       }
10703 
10704       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10705       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10706       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10707       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10708       if (!here) {
10709          tmp->locallyblocked = tmp->remotelyblocked = 0;
10710          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10711             tmp->inservice = 0;
10712          else /* We default to in service on protocols that don't have a reset */
10713             tmp->inservice = 1;
10714       }
10715    }
10716    if (tmp && !here) {
10717       /* nothing on the iflist */
10718       if (!*wlist) {
10719          *wlist = tmp;
10720          tmp->prev = NULL;
10721          tmp->next = NULL;
10722          *wend = tmp;
10723       } else {
10724          /* at least one member on the iflist */
10725          struct dahdi_pvt *working = *wlist;
10726 
10727          /* check if we maybe have to put it on the begining */
10728          if (working->channel > tmp->channel) {
10729             tmp->next = *wlist;
10730             tmp->prev = NULL;
10731             (*wlist)->prev = tmp;
10732             *wlist = tmp;
10733          } else {
10734          /* go through all the members and put the member in the right place */
10735             while (working) {
10736                /* in the middle */
10737                if (working->next) {
10738                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10739                      tmp->next = working->next;
10740                      tmp->prev = working;
10741                      working->next->prev = tmp;
10742                      working->next = tmp;
10743                      break;
10744                   }
10745                } else {
10746                /* the last */
10747                   if (working->channel < tmp->channel) {
10748                      working->next = tmp;
10749                      tmp->next = NULL;
10750                      tmp->prev = working;
10751                      *wend = tmp;
10752                      break;
10753                   }
10754                }
10755                working = working->next;
10756             }
10757          }
10758       }
10759    }
10760    return tmp;
10761 }
10762 
10763 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10764 {
10765    int res;
10766    struct dahdi_params par;
10767 
10768    /* First, check group matching */
10769    if (groupmatch) {
10770       if ((p->group & groupmatch) != groupmatch)
10771          return 0;
10772       *groupmatched = 1;
10773    }
10774    /* Check to see if we have a channel match */
10775    if (channelmatch != -1) {
10776       if (p->channel != channelmatch)
10777          return 0;
10778       *channelmatched = 1;
10779    }
10780    /* We're at least busy at this point */
10781    if (busy) {
10782       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10783          *busy = 1;
10784    }
10785    /* If do not disturb, definitely not */
10786    if (p->dnd)
10787       return 0;
10788    /* If guard time, definitely not */
10789    if (p->guardtime && (time(NULL) < p->guardtime))
10790       return 0;
10791 
10792    if (p->locallyblocked || p->remotelyblocked)
10793       return 0;
10794 
10795    /* If no owner definitely available */
10796    if (!p->owner) {
10797 #ifdef HAVE_PRI
10798       /* Trust PRI */
10799       if (p->pri) {
10800          if (p->resetting || p->call)
10801             return 0;
10802          else
10803             return 1;
10804       }
10805 #endif
10806 #ifdef HAVE_SS7
10807       /* Trust SS7 */
10808       if (p->ss7) {
10809          if (p->ss7call)
10810             return 0;
10811          else
10812             return 1;
10813       }
10814 #endif
10815 #ifdef HAVE_OPENR2
10816       /* Trust MFC/R2 */
10817       if (p->mfcr2) {
10818          if (p->mfcr2call)
10819             return 0;
10820          else
10821             return 1;
10822       }
10823 #endif
10824 
10825       /* Trust hook state */
10826       if (p->sig && !(p->radio || (p->oprmode < 0)))
10827       {
10828          /* Check hook state */
10829          if (p->subs[SUB_REAL].dfd > -1) {
10830             memset(&par, 0, sizeof(par));
10831             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10832          } else {
10833             /* Assume not off hook on CVRS */
10834             res = 0;
10835             par.rxisoffhook = 0;
10836          }
10837 
10838          if (res) {
10839             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10840          }
10841          else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
10842             if (par.rxisoffhook) {
10843                ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10844                /* Not available when the other end is off hook */
10845                return 0;
10846             }
10847          }
10848 #ifdef DAHDI_CHECK_HOOKSTATE
10849          } else { /* FXO channel case (SIG_FXS--) */
10850             /* Channel bank (using CAS), "onhook" does not necessarily means out of service, so return 1 */
10851             if (par.rxbits > -1)
10852                return 1;
10853             /* TDM FXO card, "onhook" means out of service (no battery on the line) */
10854             if (par.rxisoffhook)
10855                return 1;
10856             else
10857                return 0;
10858 #endif
10859       }
10860 
10861       return 1;
10862    }
10863 
10864    /* If it's not an FXO, forget about call wait */
10865    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10866       return 0;
10867 
10868    if (!p->callwaiting) {
10869       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
10870       return 0;
10871    }
10872 
10873    if (p->subs[SUB_CALLWAIT].dfd > -1) {
10874       /* If there is already a call waiting call, then we can't take a second one */
10875       return 0;
10876    }
10877 
10878    if ((p->owner->_state != AST_STATE_UP) &&
10879       ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10880       /* If the current call is not up, then don't allow the call */
10881       return 0;
10882    }
10883    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10884       /* Can't take a call wait when the three way calling hasn't been merged yet. */
10885       return 0;
10886    }
10887    /* We're cool */
10888    return 1;
10889 }
10890 
10891 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
10892    structures; it makes no attempt to safely copy regular channel private
10893    structures that might contain reference-counted object pointers and other
10894    scary bits
10895 */
10896 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10897 {
10898    struct dahdi_pvt *p;
10899    struct dahdi_bufferinfo bi;
10900    int res;
10901 
10902    if ((p = ast_malloc(sizeof(*p)))) {
10903       memcpy(p, src, sizeof(struct dahdi_pvt));
10904       ast_mutex_init(&p->lock);
10905       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10906       if (p->subs[SUB_REAL].dfd < 0) {
10907          ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10908          destroy_dahdi_pvt(&p);
10909          return NULL;
10910       }
10911       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10912       if (!res) {
10913          bi.txbufpolicy = src->buf_policy;
10914          bi.rxbufpolicy = src->buf_policy;
10915          bi.numbufs = src->buf_no;
10916          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10917          if (res < 0) {
10918             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10919          }
10920       } else
10921          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10922    }
10923    p->destroy = 1;
10924    p->next = iflist;
10925    p->prev = NULL;
10926    iflist = p;
10927    if (iflist->next)
10928       iflist->next->prev = p;
10929    return p;
10930 }
10931 
10932 #if defined(HAVE_PRI)
10933 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10934 {
10935    int x;
10936    if (backwards)
10937       x = pri->numchans;
10938    else
10939       x = 0;
10940    for (;;) {
10941       if (backwards && (x < 0))
10942          break;
10943       if (!backwards && (x >= pri->numchans))
10944          break;
10945       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10946          ast_debug(1, "Found empty available channel %d/%d\n",
10947             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10948          return x;
10949       }
10950       if (backwards)
10951          x--;
10952       else
10953          x++;
10954    }
10955    return -1;
10956 }
10957 #endif   /* defined(HAVE_PRI) */
10958 
10959 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10960 {
10961    ast_group_t groupmatch = 0;
10962    int channelmatch = -1;
10963    int roundrobin = 0;
10964    int callwait = 0;
10965    int busy = 0;
10966    struct dahdi_pvt *p;
10967    struct ast_channel *tmp = NULL;
10968    char *dest=NULL;
10969    int x;
10970    char *s;
10971    char opt=0;
10972    int res=0, y=0;
10973    int backwards = 0;
10974 #ifdef HAVE_PRI
10975    int crv;
10976    int bearer = -1;
10977    int trunkgroup;
10978    struct dahdi_pri *pri=NULL;
10979 #endif
10980    struct dahdi_pvt *exitpvt, *start, *end;
10981    ast_mutex_t *lock;
10982    int channelmatched = 0;
10983    int groupmatched = 0;
10984 
10985    /*
10986     * data is ---v
10987     * Dial(DAHDI/pseudo[/extension])
10988     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
10989     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
10990     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
10991     *
10992     * g - channel group allocation search forward
10993     * G - channel group allocation search backward
10994     * r - channel group allocation round robin search forward
10995     * R - channel group allocation round robin search backward
10996     *
10997     * c - Wait for DTMF digit to confirm answer
10998     * r<cadance#> - Set distintive ring cadance number
10999     * d - Force bearer capability for ISDN/SS7 call to digital.
11000     */
11001 
11002    /* Assume we're locking the iflock */
11003    lock = &iflock;
11004    start = iflist;
11005    end = ifend;
11006    if (data) {
11007       dest = ast_strdupa((char *)data);
11008    } else {
11009       ast_log(LOG_WARNING, "Channel requested with no data\n");
11010       return NULL;
11011    }
11012    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11013       /* Retrieve the group number */
11014       char *stringp;
11015 
11016       stringp = dest + 1;
11017       s = strsep(&stringp, "/");
11018       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11019          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11020          return NULL;
11021       }
11022       groupmatch = ((ast_group_t) 1 << x);
11023       if (toupper(dest[0]) == 'G') {
11024          if (dest[0] == 'G') {
11025             backwards = 1;
11026             p = ifend;
11027          } else
11028             p = iflist;
11029       } else {
11030          if (dest[0] == 'R') {
11031             backwards = 1;
11032             p = round_robin[x]?round_robin[x]->prev:ifend;
11033             if (!p)
11034                p = ifend;
11035          } else {
11036             p = round_robin[x]?round_robin[x]->next:iflist;
11037             if (!p)
11038                p = iflist;
11039          }
11040          roundrobin = 1;
11041       }
11042    } else {
11043       char *stringp;
11044 
11045       stringp = dest;
11046       s = strsep(&stringp, "/");
11047       p = iflist;
11048       if (!strcasecmp(s, "pseudo")) {
11049          /* Special case for pseudo */
11050          x = CHAN_PSEUDO;
11051          channelmatch = x;
11052       }
11053 #ifdef HAVE_PRI
11054       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11055          if ((trunkgroup < 1) || (crv < 1)) {
11056             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11057             return NULL;
11058          }
11059          res--;
11060          for (x = 0; x < NUM_SPANS; x++) {
11061             if (pris[x].trunkgroup == trunkgroup) {
11062                pri = pris + x;
11063                lock = &pri->lock;
11064                start = pri->crvs;
11065                end = pri->crvend;
11066                break;
11067             }
11068          }
11069          if (!pri) {
11070             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11071             return NULL;
11072          }
11073          channelmatch = crv;
11074          p = pris[x].crvs;
11075       }
11076 #endif
11077       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11078          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11079          return NULL;
11080       } else {
11081          channelmatch = x;
11082       }
11083    }
11084    /* Search for an unowned channel */
11085    ast_mutex_lock(lock);
11086    exitpvt = p;
11087    while (p && !tmp) {
11088       if (roundrobin)
11089          round_robin[x] = p;
11090 #if 0
11091       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11092 #endif
11093 
11094       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11095          ast_debug(1, "Using channel %d\n", p->channel);
11096          if (p->inalarm)
11097             goto next;
11098 
11099          callwait = (p->owner != NULL);
11100 #ifdef HAVE_PRI
11101          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11102             if (p->sig != SIG_FXSKS) {
11103                /* Gotta find an actual channel to use for this
11104                   CRV if this isn't a callwait */
11105                bearer = pri_find_empty_chan(pri, 0);
11106                if (bearer < 0) {
11107                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11108                   p = NULL;
11109                   break;
11110                }
11111                pri_assign_bearer(p, pri, pri->pvts[bearer]);
11112             } else {
11113                if (alloc_sub(p, 0)) {
11114                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11115                   p = NULL;
11116                   break;
11117                } else
11118                   ast_debug(1, "Allocated placeholder pseudo channel\n");
11119 
11120                p->pri = pri;
11121             }
11122          }
11123 #endif
11124 #ifdef HAVE_OPENR2
11125          if (p->mfcr2) {
11126             ast_mutex_lock(&p->lock);
11127             if (p->mfcr2call) {
11128                ast_mutex_unlock(&p->lock);
11129                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11130                goto next;
11131             }
11132             p->mfcr2call = 1;
11133             ast_mutex_unlock(&p->lock);
11134          }
11135 #endif
11136          if (p->channel == CHAN_PSEUDO) {
11137             p = duplicate_pseudo(p);
11138             if (!p) {
11139                break;
11140             }
11141          }
11142          if (p->owner) {
11143             if (alloc_sub(p, SUB_CALLWAIT)) {
11144                p = NULL;
11145                break;
11146             }
11147          }
11148          p->outgoing = 1;
11149          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11150          if (!tmp) {
11151             p->outgoing = 0;
11152          }
11153 #ifdef HAVE_PRI
11154          if (p->bearer) {
11155             /* Log owner to bearer channel, too */
11156             p->bearer->owner = tmp;
11157          }
11158 #endif
11159          /* Make special notes */
11160          if (res > 1) {
11161             if (opt == 'c') {
11162                /* Confirm answer */
11163                p->confirmanswer = 1;
11164             } else if (opt == 'r') {
11165                /* Distinctive ring */
11166                if (res < 3)
11167                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11168                else
11169                   p->distinctivering = y;
11170             } else if (opt == 'd') {
11171                /* If this is an ISDN call, make it digital */
11172                p->digital = 1;
11173                if (tmp)
11174                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11175             } else {
11176                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11177             }
11178          }
11179          /* Note if the call is a call waiting call */
11180          if (tmp && callwait)
11181             tmp->cdrflags |= AST_CDR_CALLWAIT;
11182          break;
11183       }
11184 next:
11185       if (backwards) {
11186          p = p->prev;
11187          if (!p)
11188             p = end;
11189       } else {
11190          p = p->next;
11191          if (!p)
11192             p = start;
11193       }
11194       /* stop when you roll to the one that we started from */
11195       if (p == exitpvt)
11196          break;
11197    }
11198    ast_mutex_unlock(lock);
11199    restart_monitor();
11200    if (callwait)
11201       *cause = AST_CAUSE_BUSY;
11202    else if (!tmp) {
11203       if (channelmatched) {
11204          if (busy)
11205             *cause = AST_CAUSE_BUSY;
11206       } else if (groupmatched) {
11207          *cause = AST_CAUSE_CONGESTION;
11208       }
11209    }
11210 
11211    return tmp;
11212 }
11213 
11214 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11215 static int dahdi_setlaw(int dfd, int law)
11216 {
11217    return ioctl(dfd, DAHDI_SETLAW, &law);
11218 }
11219 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
11220 
11221 #if defined(HAVE_SS7)
11222 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11223 {
11224    int i;
11225    int winner = -1;
11226    for (i = 0; i < linkset->numchans; i++) {
11227       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11228          winner = i;
11229          break;
11230       }
11231    }
11232    return winner;
11233 }
11234 #endif   /* defined(HAVE_SS7) */
11235 
11236 #if defined(HAVE_SS7)
11237 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11238 {
11239    unsigned char status[32];
11240    struct dahdi_pvt *p = NULL;
11241    int i, offset;
11242 
11243    for (i = 0; i < linkset->numchans; i++) {
11244       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11245          p = linkset->pvts[i];
11246          offset = p->cic - startcic;
11247          status[offset] = 0;
11248          if (p->locallyblocked)
11249             status[offset] |= (1 << 0) | (1 << 4);
11250          if (p->remotelyblocked)
11251             status[offset] |= (1 << 1) | (1 << 5);
11252          if (p->ss7call) {
11253             if (p->outgoing)
11254                status[offset] |= (1 << 3);
11255             else
11256                status[offset] |= (1 << 2);
11257          } else
11258             status[offset] |= 0x3 << 2;
11259       }
11260    }
11261 
11262    if (p)
11263       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11264    else
11265       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11266 
11267 }
11268 #endif   /* defined(HAVE_SS7) */
11269 
11270 #if defined(HAVE_SS7)
11271 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11272 {
11273    int i;
11274 
11275    for (i = 0; i < linkset->numchans; i++) {
11276       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11277          ast_mutex_lock(&linkset->pvts[i]->lock);
11278          if (linkset->pvts[i]->owner)
11279             linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11280          ast_mutex_unlock(&linkset->pvts[i]->lock);
11281       }
11282    }
11283 }
11284 #endif   /* defined(HAVE_SS7) */
11285 
11286 #if defined(HAVE_SS7)
11287 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11288 {
11289    int i;
11290 
11291    for (i = 0; i < linkset->numchans; i++) {
11292       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11293          if (state) {
11294             if (state[i])
11295                linkset->pvts[i]->remotelyblocked = block;
11296          } else
11297             linkset->pvts[i]->remotelyblocked = block;
11298       }
11299    }
11300 }
11301 #endif   /* defined(HAVE_SS7) */
11302 
11303 #if defined(HAVE_SS7)
11304 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11305 {
11306    int i;
11307 
11308    for (i = 0; i < linkset->numchans; i++) {
11309       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11310          linkset->pvts[i]->inservice = 1;
11311    }
11312 }
11313 #endif   /* defined(HAVE_SS7) */
11314 
11315 #if defined(HAVE_SS7)
11316 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11317 {
11318    int i, startcic = -1, endcic, dpc;
11319 
11320    if (linkset->numchans <= 0)
11321       return;
11322 
11323    startcic = linkset->pvts[0]->cic;
11324    /* DB: CIC's DPC fix */
11325    dpc = linkset->pvts[0]->dpc;
11326 
11327    for (i = 0; i < linkset->numchans; i++) {
11328       if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
11329          continue;
11330       } else {
11331          endcic = linkset->pvts[i]->cic;
11332          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11333          isup_grs(linkset->ss7, startcic, endcic, dpc);
11334 
11335          /* DB: CIC's DPC fix */
11336          if (linkset->pvts[i+1]) {
11337             startcic = linkset->pvts[i+1]->cic;
11338             dpc = linkset->pvts[i+1]->dpc;
11339          }
11340       }
11341    }
11342 }
11343 #endif   /* defined(HAVE_SS7) */
11344 
11345 #if defined(HAVE_SS7)
11346 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11347 {
11348    if (p->loopedback != enable) {
11349       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11350          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11351          return;
11352       }
11353       p->loopedback = enable;
11354    }
11355 }
11356 #endif   /* defined(HAVE_SS7) */
11357 
11358 #if defined(HAVE_SS7)
11359 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
11360 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11361 {
11362    struct ss7 *ss7 = linkset->ss7;
11363    int res;
11364    int law = 1;
11365    struct ast_channel *c;
11366    char tmp[256];
11367 
11368    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11369       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11370 
11371    if (linkset->type == SS7_ITU)
11372       law = DAHDI_LAW_ALAW;
11373    else
11374       law = DAHDI_LAW_MULAW;
11375 
11376    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11377    if (res < 0)
11378       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11379 
11380    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11381       p->proceeding = 1;
11382       isup_acm(ss7, p->ss7call);
11383    }
11384 
11385    ast_mutex_unlock(&linkset->lock);
11386    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11387 
11388    if (!c) {
11389       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11390       /* Holding this lock is assumed entering the function */
11391       ast_mutex_lock(&linkset->lock);
11392       return;
11393    } else
11394       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11395 
11396    dahdi_enable_ec(p);
11397 
11398    /* We only reference these variables in the context of the ss7_linkset function
11399     * when receiving either and IAM or a COT message.  Since they are only accessed
11400     * from this context, we should be safe to unlock around them */
11401 
11402    ast_mutex_unlock(&p->lock);
11403 
11404    if (!ast_strlen_zero(p->charge_number)) {
11405       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11406       /* Clear this after we set it */
11407       p->charge_number[0] = 0;
11408    }
11409    if (!ast_strlen_zero(p->gen_add_number)) {
11410       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11411       /* Clear this after we set it */
11412       p->gen_add_number[0] = 0;
11413    }
11414    if (!ast_strlen_zero(p->jip_number)) {
11415       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11416       /* Clear this after we set it */
11417       p->jip_number[0] = 0;
11418    }
11419    if (!ast_strlen_zero(p->gen_dig_number)) {
11420       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11421       /* Clear this after we set it */
11422       p->gen_dig_number[0] = 0;
11423    }
11424    if (!ast_strlen_zero(p->orig_called_num)) {
11425       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11426       /* Clear this after we set it */
11427       p->orig_called_num[0] = 0;
11428    }
11429 
11430    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11431    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11432    /* Clear this after we set it */
11433    p->gen_dig_type = 0;
11434 
11435    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11436    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11437    /* Clear this after we set it */
11438    p->gen_dig_scheme = 0;
11439 
11440    if (!ast_strlen_zero(p->lspi_ident)) {
11441       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11442       /* Clear this after we set it */
11443       p->lspi_ident[0] = 0;
11444    }
11445 
11446    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11447    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11448    /* Clear this after we set it */
11449    p->call_ref_ident = 0;
11450 
11451    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11452    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11453    /* Clear this after we set it */
11454    p->call_ref_pc = 0;
11455 
11456    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11457    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11458    /* Clear this after we set it */
11459    p->calling_party_cat = 0;
11460 
11461    if (!ast_strlen_zero(p->redirecting_num)) {
11462       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11463       /* Clear this after we set it */
11464       p->redirecting_num[0] = 0;
11465    }
11466    if (!ast_strlen_zero(p->generic_name)) {
11467       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11468       /* Clear this after we set it */
11469       p->generic_name[0] = 0;
11470    }
11471 
11472    ast_mutex_lock(&p->lock);
11473    ast_mutex_lock(&linkset->lock);
11474 }
11475 #endif   /* defined(HAVE_SS7) */
11476 
11477 #if defined(HAVE_SS7)
11478 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11479 {
11480    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
11481       if (size) {
11482          *buf = '\0';
11483       }
11484       return;
11485    }
11486    switch (nai) {
11487    case SS7_NAI_INTERNATIONAL:
11488       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11489       break;
11490    case SS7_NAI_NATIONAL:
11491       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11492       break;
11493    case SS7_NAI_SUBSCRIBER:
11494       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11495       break;
11496    case SS7_NAI_UNKNOWN:
11497       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11498       break;
11499    default:
11500       snprintf(buf, size, "%s", number);
11501       break;
11502    }
11503 }
11504 #endif   /* defined(HAVE_SS7) */
11505 
11506 #if defined(HAVE_SS7)
11507 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11508 {
11509    return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11510 }
11511 #endif   /* defined(HAVE_SS7) */
11512 
11513 #if defined(HAVE_SS7)
11514 static void *ss7_linkset(void *data)
11515 {
11516    int res, i;
11517    struct timeval *next = NULL, tv;
11518    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11519    struct ss7 *ss7 = linkset->ss7;
11520    ss7_event *e = NULL;
11521    struct dahdi_pvt *p;
11522    int chanpos;
11523    struct pollfd pollers[NUM_DCHANS];
11524    int cic;
11525    unsigned int dpc;
11526    int nextms = 0;
11527 
11528    ss7_start(ss7);
11529 
11530    while(1) {
11531       ast_mutex_lock(&linkset->lock);
11532       if ((next = ss7_schedule_next(ss7))) {
11533          tv = ast_tvnow();
11534          tv.tv_sec = next->tv_sec - tv.tv_sec;
11535          tv.tv_usec = next->tv_usec - tv.tv_usec;
11536          if (tv.tv_usec < 0) {
11537             tv.tv_usec += 1000000;
11538             tv.tv_sec -= 1;
11539          }
11540          if (tv.tv_sec < 0) {
11541             tv.tv_sec = 0;
11542             tv.tv_usec = 0;
11543          }
11544          nextms = tv.tv_sec * 1000;
11545          nextms += tv.tv_usec / 1000;
11546       }
11547       ast_mutex_unlock(&linkset->lock);
11548 
11549       for (i = 0; i < linkset->numsigchans; i++) {
11550          pollers[i].fd = linkset->fds[i];
11551          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11552          pollers[i].revents = 0;
11553       }
11554 
11555       res = poll(pollers, linkset->numsigchans, nextms);
11556       if ((res < 0) && (errno != EINTR)) {
11557          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11558       } else if (!res) {
11559          ast_mutex_lock(&linkset->lock);
11560          ss7_schedule_run(ss7);
11561          ast_mutex_unlock(&linkset->lock);
11562          continue;
11563       }
11564 
11565       ast_mutex_lock(&linkset->lock);
11566       for (i = 0; i < linkset->numsigchans; i++) {
11567          if (pollers[i].revents & POLLPRI) {
11568             int x;
11569             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11570                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11571             }
11572             switch (x) {
11573             case DAHDI_EVENT_OVERRUN:
11574                ast_debug(1, "Overrun detected!\n");
11575                break;
11576             case DAHDI_EVENT_BADFCS:
11577                ast_debug(1, "Bad FCS\n");
11578                break;
11579             case DAHDI_EVENT_ABORT:
11580                ast_debug(1, "HDLC Abort\n");
11581                break;
11582             case DAHDI_EVENT_ALARM:
11583                ast_log(LOG_ERROR, "Alarm on link!\n");
11584                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11585                linkset->linkstate[i] &= ~LINKSTATE_UP;
11586                ss7_link_alarm(ss7, pollers[i].fd);
11587                break;
11588             case DAHDI_EVENT_NOALARM:
11589                ast_log(LOG_ERROR, "Alarm cleared on link\n");
11590                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11591                linkset->linkstate[i] |= LINKSTATE_STARTING;
11592                ss7_link_noalarm(ss7, pollers[i].fd);
11593                break;
11594             default:
11595                ast_log(LOG_ERROR, "Got exception %d!\n", x);
11596                break;
11597             }
11598          }
11599 
11600          if (pollers[i].revents & POLLIN) {
11601             res = ss7_read(ss7, pollers[i].fd);
11602          }
11603 
11604          if (pollers[i].revents & POLLOUT) {
11605             res = ss7_write(ss7, pollers[i].fd);
11606             if (res < 0) {
11607                ast_debug(1, "Error in write %s\n", strerror(errno));
11608             }
11609          }
11610       }
11611 
11612       while ((e = ss7_check_event(ss7))) {
11613          switch (e->e) {
11614          case SS7_EVENT_UP:
11615             if (linkset->state != LINKSET_STATE_UP) {
11616                ast_verbose("--- SS7 Up ---\n");
11617                ss7_reset_linkset(linkset);
11618             }
11619             linkset->state = LINKSET_STATE_UP;
11620             break;
11621          case SS7_EVENT_DOWN:
11622             ast_verbose("--- SS7 Down ---\n");
11623             linkset->state = LINKSET_STATE_DOWN;
11624             for (i = 0; i < linkset->numchans; i++) {
11625                struct dahdi_pvt *p = linkset->pvts[i];
11626                if (p)
11627                   p->inalarm = 1;
11628             }
11629             break;
11630          case MTP2_LINK_UP:
11631             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11632             break;
11633          case MTP2_LINK_DOWN:
11634             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11635             break;
11636          case ISUP_EVENT_CPG:
11637             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11638             if (chanpos < 0) {
11639                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11640                break;
11641             }
11642             p = linkset->pvts[chanpos];
11643             ast_mutex_lock(&p->lock);
11644             switch (e->cpg.event) {
11645             case CPG_EVENT_ALERTING:
11646                p->alerting = 1;
11647                p->subs[SUB_REAL].needringing = 1;
11648                break;
11649             case CPG_EVENT_PROGRESS:
11650             case CPG_EVENT_INBANDINFO:
11651                {
11652                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11653                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11654                   dahdi_queue_frame(p, &f, linkset);
11655                   p->progress = 1;
11656                   p->dialing = 0;
11657                   if (p->dsp && p->dsp_features) {
11658                      ast_dsp_set_features(p->dsp, p->dsp_features);
11659                      p->dsp_features = 0;
11660                   }
11661                }
11662                break;
11663             default:
11664                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11665             }
11666 
11667             ast_mutex_unlock(&p->lock);
11668             break;
11669          case ISUP_EVENT_RSC:
11670             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11671             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11672             if (chanpos < 0) {
11673                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11674                break;
11675             }
11676             p = linkset->pvts[chanpos];
11677             ast_mutex_lock(&p->lock);
11678             p->inservice = 1;
11679             p->remotelyblocked = 0;
11680             dpc = p->dpc;
11681             isup_set_call_dpc(e->rsc.call, dpc);
11682             if (p->ss7call)
11683                p->ss7call = NULL;
11684             if (p->owner)
11685                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11686             ast_mutex_unlock(&p->lock);
11687             isup_rlc(ss7, e->rsc.call);
11688             break;
11689          case ISUP_EVENT_GRS:
11690             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11691             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11692             if (chanpos < 0) {
11693                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11694                break;
11695             }
11696             p = linkset->pvts[chanpos];
11697             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11698             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11699             ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11700             break;
11701          case ISUP_EVENT_CQM:
11702             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11703             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11704             break;
11705          case ISUP_EVENT_GRA:
11706             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11707             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11708             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11709             break;
11710          case ISUP_EVENT_IAM:
11711             ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
11712             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11713             if (chanpos < 0) {
11714                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11715                isup_rel(ss7, e->iam.call, -1);
11716                break;
11717             }
11718             p = linkset->pvts[chanpos];
11719             ast_mutex_lock(&p->lock);
11720             if (p->owner) {
11721                if (p->ss7call == e->iam.call) {
11722                   ast_mutex_unlock(&p->lock);
11723                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11724                   break;
11725                } else {
11726                   ast_mutex_unlock(&p->lock);
11727                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11728                   break;
11729                }
11730             }
11731 
11732             dpc = p->dpc;
11733             p->ss7call = e->iam.call;
11734             isup_set_call_dpc(p->ss7call, dpc);
11735 
11736             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11737                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11738                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11739             } else
11740                p->cid_num[0] = 0;
11741 
11742             if (p->immediate) {
11743                p->exten[0] = 's';
11744                p->exten[1] = '\0';
11745             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11746                char *st;
11747                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11748                st = strchr(p->exten, '#');
11749                if (st)
11750                   *st = '\0';
11751                } else
11752                   p->exten[0] = '\0';
11753 
11754             p->cid_ani[0] = '\0';
11755             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11756                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11757             else
11758                p->cid_name[0] = '\0';
11759 
11760             p->cid_ani2 = e->iam.oli_ani2;
11761             p->cid_ton = 0;
11762             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11763             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11764             p->gen_add_type = e->iam.gen_add_type;
11765             p->gen_add_nai = e->iam.gen_add_nai;
11766             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11767             p->gen_add_num_plan = e->iam.gen_add_num_plan;
11768             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11769             p->gen_dig_type = e->iam.gen_dig_type;
11770             p->gen_dig_scheme = e->iam.gen_dig_scheme;
11771             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11772             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11773             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11774             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11775             p->calling_party_cat = e->iam.calling_party_cat;
11776 
11777             /* Set DNID */
11778             if (!ast_strlen_zero(e->iam.called_party_num))
11779                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11780 
11781             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11782 
11783                if (e->iam.cot_check_required) {
11784                   dahdi_loopback(p, 1);
11785                } else
11786                   ss7_start_call(p, linkset);
11787             } else {
11788                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11789                p->alreadyhungup = 1;
11790                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11791             }
11792             ast_mutex_unlock(&p->lock);
11793             break;
11794          case ISUP_EVENT_COT:
11795             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11796             if (chanpos < 0) {
11797                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11798                isup_rel(ss7, e->cot.call, -1);
11799                break;
11800             }
11801             p = linkset->pvts[chanpos];
11802 
11803             ast_mutex_lock(&p->lock);
11804 
11805             if (p->loopedback) {
11806                dahdi_loopback(p, 0);
11807                ss7_start_call(p, linkset);
11808             }
11809 
11810             ast_mutex_unlock(&p->lock);
11811 
11812             break;
11813          case ISUP_EVENT_CCR:
11814             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11815             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11816             if (chanpos < 0) {
11817                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11818                break;
11819             }
11820 
11821             p = linkset->pvts[chanpos];
11822 
11823             ast_mutex_lock(&p->lock);
11824             dahdi_loopback(p, 1);
11825             ast_mutex_unlock(&p->lock);
11826 
11827             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11828             break;
11829          case ISUP_EVENT_CVT:
11830             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11831             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11832             if (chanpos < 0) {
11833                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11834                break;
11835             }
11836 
11837             p = linkset->pvts[chanpos];
11838 
11839             ast_mutex_lock(&p->lock);
11840             dahdi_loopback(p, 1);
11841             ast_mutex_unlock(&p->lock);
11842 
11843             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11844             break;
11845          case ISUP_EVENT_REL:
11846             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11847             if (chanpos < 0) {
11848                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11849                break;
11850             }
11851             p = linkset->pvts[chanpos];
11852             ast_mutex_lock(&p->lock);
11853             if (p->owner) {
11854                p->owner->hangupcause = e->rel.cause;
11855                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11856             } else if (!p->restartpending)
11857                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11858 
11859             /* End the loopback if we have one */
11860             dahdi_loopback(p, 0);
11861 
11862             isup_rlc(ss7, e->rel.call);
11863             p->ss7call = NULL;
11864 
11865             ast_mutex_unlock(&p->lock);
11866             break;
11867          case ISUP_EVENT_ACM:
11868             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11869             if (chanpos < 0) {
11870                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11871                isup_rel(ss7, e->acm.call, -1);
11872                break;
11873             } else {
11874                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11875 
11876                p = linkset->pvts[chanpos];
11877 
11878                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11879 
11880                if (e->acm.call_ref_ident > 0) {
11881                   p->rlt = 1; /* Setting it but not using it here*/
11882                }
11883 
11884                ast_mutex_lock(&p->lock);
11885                dahdi_queue_frame(p, &f, linkset);
11886                p->proceeding = 1;
11887                p->dialing = 0;
11888                /* Send alerting if subscriber is free */
11889                if (e->acm.called_party_status_ind == 1) {
11890                   p->alerting = 1;
11891                   p->subs[SUB_REAL].needringing = 1;
11892                }
11893                ast_mutex_unlock(&p->lock);
11894             }
11895             break;
11896          case ISUP_EVENT_CGB:
11897             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11898             if (chanpos < 0) {
11899                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11900                break;
11901             }
11902             p = linkset->pvts[chanpos];
11903             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11904             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11905             break;
11906          case ISUP_EVENT_CGU:
11907             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11908             if (chanpos < 0) {
11909                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11910                break;
11911             }
11912             p = linkset->pvts[chanpos];
11913             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11914             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11915             break;
11916          case ISUP_EVENT_UCIC:
11917             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11918             if (chanpos < 0) {
11919                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11920                break;
11921             }
11922             p = linkset->pvts[chanpos];
11923             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11924             ast_mutex_lock(&p->lock);
11925             p->remotelyblocked = 1;
11926             p->inservice = 0;
11927             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
11928             break;
11929          case ISUP_EVENT_BLO:
11930             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11931             if (chanpos < 0) {
11932                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11933                break;
11934             }
11935             p = linkset->pvts[chanpos];
11936             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11937             ast_mutex_lock(&p->lock);
11938             p->remotelyblocked = 1;
11939             ast_mutex_unlock(&p->lock);
11940             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11941             break;
11942          case ISUP_EVENT_BLA:
11943             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11944             if (chanpos < 0) {
11945                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11946                break;
11947             }
11948             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11949             p = linkset->pvts[chanpos];
11950             ast_mutex_lock(&p->lock);
11951             p->locallyblocked = 1;
11952             ast_mutex_unlock(&p->lock);
11953             break;
11954          case ISUP_EVENT_UBL:
11955             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11956             if (chanpos < 0) {
11957                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11958                break;
11959             }
11960             p = linkset->pvts[chanpos];
11961             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11962             ast_mutex_lock(&p->lock);
11963             p->remotelyblocked = 0;
11964             ast_mutex_unlock(&p->lock);
11965             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11966             break;
11967          case ISUP_EVENT_UBA:
11968             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11969             if (chanpos < 0) {
11970                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11971                break;
11972             }
11973             p = linkset->pvts[chanpos];
11974             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11975             ast_mutex_lock(&p->lock);
11976             p->locallyblocked = 0;
11977             ast_mutex_unlock(&p->lock);
11978             break;
11979          case ISUP_EVENT_CON:
11980          case ISUP_EVENT_ANM:
11981             if (e->e == ISUP_EVENT_CON)
11982                cic = e->con.cic;
11983             else
11984                cic = e->anm.cic;
11985 
11986             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11987             if (chanpos < 0) {
11988                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11989                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11990                break;
11991             } else {
11992                p = linkset->pvts[chanpos];
11993                ast_mutex_lock(&p->lock);
11994                p->subs[SUB_REAL].needanswer = 1;
11995                if (p->dsp && p->dsp_features) {
11996                   ast_dsp_set_features(p->dsp, p->dsp_features);
11997                   p->dsp_features = 0;
11998                }
11999                dahdi_enable_ec(p);
12000                ast_mutex_unlock(&p->lock);
12001             }
12002             break;
12003          case ISUP_EVENT_RLC:
12004             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12005             if (chanpos < 0) {
12006                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12007                break;
12008             } else {
12009                p = linkset->pvts[chanpos];
12010                ast_mutex_lock(&p->lock);
12011                if (p->alreadyhungup)
12012                   p->ss7call = NULL;
12013                else
12014                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
12015                ast_mutex_unlock(&p->lock);
12016                }
12017                break;
12018          case ISUP_EVENT_FAA:
12019             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12020             if (chanpos < 0) {
12021                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12022                break;
12023             } else {
12024                p = linkset->pvts[chanpos];
12025                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12026                ast_mutex_lock(&p->lock);
12027                if (p->alreadyhungup){
12028                   p->ss7call = NULL;
12029                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
12030                }
12031                ast_mutex_unlock(&p->lock);
12032             }
12033             break;
12034          default:
12035             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12036             break;
12037          }
12038       }
12039       ast_mutex_unlock(&linkset->lock);
12040    }
12041 
12042    return 0;
12043 }
12044 #endif   /* defined(HAVE_SS7) */
12045 
12046 #if defined(HAVE_SS7)
12047 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12048 {
12049 #if 0
12050    int i;
12051 
12052    for (i = 0; i < NUM_SPANS; i++)
12053       if (linksets[i].ss7 == ss7)
12054          break;
12055 
12056    ast_verbose("[%d] %s", i+1, s);
12057 #else
12058    ast_verbose("%s", s);
12059 #endif
12060 }
12061 #endif   /* defined(HAVE_SS7) */
12062 
12063 #if defined(HAVE_SS7)
12064 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12065 {
12066 #if 0
12067    int i;
12068 
12069    for (i = 0; i < NUM_SPANS; i++)
12070       if (linksets[i].ss7 == ss7)
12071          break;
12072 
12073 #else
12074    ast_log(LOG_ERROR, "%s", s);
12075 #endif
12076 }
12077 #endif   /* defined(HAVE_SS7) */
12078 
12079 #if defined(HAVE_OPENR2)
12080 static void *mfcr2_monitor(void *data)
12081 {
12082    struct dahdi_mfcr2 *mfcr2 = data;
12083    /* we should be using pthread_key_create
12084       and allocate pollers dynamically.
12085       I think do_monitor() could be leaking, since it
12086       could be cancelled at any time and is not
12087       using thread keys, why?, */
12088    struct pollfd pollers[sizeof(mfcr2->pvts)];
12089    int res = 0;
12090    int i = 0;
12091    int oldstate = 0;
12092    int quit_loop = 0;
12093    int maxsleep = 20;
12094    int was_idle = 0;
12095    int pollsize = 0;
12096    /* now that we're ready to get calls, unblock our side and
12097       get current line state */
12098    for (i = 0; i < mfcr2->numchans; i++) {
12099       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12100       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12101    }
12102    while (1) {
12103       /* we trust here that the mfcr2 channel list will not ever change once
12104          the module is loaded */
12105       pollsize = 0;
12106       for (i = 0; i < mfcr2->numchans; i++) {
12107          pollers[i].revents = 0;
12108          pollers[i].events = 0;
12109          if (mfcr2->pvts[i]->owner) {
12110             continue;
12111          }
12112          if (!mfcr2->pvts[i]->r2chan) {
12113             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12114             quit_loop = 1;
12115             break;
12116          }
12117          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12118          pollers[i].events = POLLIN | POLLPRI;
12119          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12120          pollsize++;
12121       }
12122       if (quit_loop) {
12123          break;
12124       }
12125       if (pollsize == 0) {
12126          if (!was_idle) {
12127             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12128             was_idle = 1;
12129          }
12130          poll(NULL, 0, maxsleep);
12131          continue;
12132       }
12133       was_idle = 0;
12134       /* probably poll() is a valid cancel point, lets just be on the safe side
12135          by calling pthread_testcancel */
12136       pthread_testcancel();
12137       res = poll(pollers, mfcr2->numchans, maxsleep);
12138       pthread_testcancel();
12139       if ((res < 0) && (errno != EINTR)) {
12140          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12141          break;
12142       }
12143       /* do we want to allow to cancel while processing events? */
12144       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12145       for (i = 0; i < mfcr2->numchans; i++) {
12146          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12147             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12148          }
12149       }
12150       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12151    }
12152    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12153    return 0;
12154 }
12155 #endif /* HAVE_OPENR2 */
12156 
12157 #if defined(HAVE_PRI)
12158 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12159 {
12160    struct dahdi_pvt *p;
12161    p = pri->crvs;
12162    while (p) {
12163       if (p->channel == crv)
12164          return p;
12165       p = p->next;
12166    }
12167    return NULL;
12168 }
12169 #endif   /* defined(HAVE_PRI) */
12170 
12171 #if defined(HAVE_PRI)
12172 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12173 {
12174    int x;
12175    int span = PRI_SPAN(channel);
12176    int spanfd;
12177    struct dahdi_params param;
12178    int principle = -1;
12179    int explicit = PRI_EXPLICIT(channel);
12180    channel = PRI_CHANNEL(channel);
12181 
12182    if (!explicit) {
12183       spanfd = pri_active_dchan_fd(pri);
12184       memset(&param, 0, sizeof(param));
12185       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12186          return -1;
12187       span = pris[param.spanno - 1].prilogicalspan;
12188    }
12189 
12190    for (x = 0; x < pri->numchans; x++) {
12191       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12192          principle = x;
12193          break;
12194       }
12195    }
12196 
12197    return principle;
12198 }
12199 #endif   /* defined(HAVE_PRI) */
12200 
12201 #if defined(HAVE_PRI)
12202 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12203 {
12204    int x;
12205    struct dahdi_pvt *crv;
12206    if (!c) {
12207       if (principle < 0)
12208          return -1;
12209       return principle;
12210    }
12211    if ((principle > -1) &&
12212       (principle < pri->numchans) &&
12213       (pri->pvts[principle]) &&
12214       (pri->pvts[principle]->call == c))
12215       return principle;
12216    /* First, check for other bearers */
12217    for (x = 0; x < pri->numchans; x++) {
12218       if (!pri->pvts[x])
12219          continue;
12220       if (pri->pvts[x]->call == c) {
12221          /* Found our call */
12222          if (principle != x) {
12223             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12224 
12225             ast_verb(3, "Moving call from channel %d to channel %d\n",
12226                 old->channel, new->channel);
12227             if (new->owner) {
12228                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12229                   old->channel, new->channel, new->channel);
12230                return -1;
12231             }
12232             /* Fix it all up now */
12233             new->owner = old->owner;
12234             old->owner = NULL;
12235             if (new->owner) {
12236                ast_string_field_build(new->owner, name,
12237                   "DAHDI/%d:%d-%d", pri->trunkgroup,
12238                   new->channel, 1);
12239                new->owner->tech_pvt = new;
12240                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12241                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12242                old->subs[SUB_REAL].owner = NULL;
12243             } else
12244                ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
12245             new->call = old->call;
12246             old->call = NULL;
12247 
12248             /* Copy any DSP that may be present */
12249             new->dsp = old->dsp;
12250             new->dsp_features = old->dsp_features;
12251             old->dsp = NULL;
12252             old->dsp_features = 0;
12253          }
12254          return principle;
12255       }
12256    }
12257    /* Now check for a CRV with no bearer */
12258    crv = pri->crvs;
12259    while (crv) {
12260       if (crv->call == c) {
12261          /* This is our match...  Perform some basic checks */
12262          if (crv->bearer)
12263             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12264          else if (pri->pvts[principle]->owner)
12265             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12266          else {
12267             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
12268                wakeup the potential sleeper */
12269             dahdi_close_sub(crv, SUB_REAL);
12270             pri->pvts[principle]->call = crv->call;
12271             pri_assign_bearer(crv, pri, pri->pvts[principle]);
12272             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12273                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12274                pri->trunkgroup, crv->channel);
12275             wakeup_sub(crv, SUB_REAL, pri);
12276          }
12277          return principle;
12278       }
12279       crv = crv->next;
12280    }
12281    ast_log(LOG_WARNING, "Call specified, but not found?\n");
12282    return -1;
12283 }
12284 #endif   /* defined(HAVE_PRI) */
12285 
12286 #if defined(HAVE_PRI)
12287 static void *do_idle_thread(void *vchan)
12288 {
12289    struct ast_channel *chan = vchan;
12290    struct dahdi_pvt *pvt = chan->tech_pvt;
12291    struct ast_frame *f;
12292    char ex[80];
12293    /* Wait up to 30 seconds for an answer */
12294    int newms, ms = 30000;
12295    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12296    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12297    if (ast_call(chan, ex, 0)) {
12298       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12299       ast_hangup(chan);
12300       return NULL;
12301    }
12302    while ((newms = ast_waitfor(chan, ms)) > 0) {
12303       f = ast_read(chan);
12304       if (!f) {
12305          /* Got hangup */
12306          break;
12307       }
12308       if (f->frametype == AST_FRAME_CONTROL) {
12309          switch (f->subclass) {
12310          case AST_CONTROL_ANSWER:
12311             /* Launch the PBX */
12312             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12313             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12314             chan->priority = 1;
12315             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12316             ast_pbx_run(chan);
12317             /* It's already hungup, return immediately */
12318             return NULL;
12319          case AST_CONTROL_BUSY:
12320             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12321             break;
12322          case AST_CONTROL_CONGESTION:
12323             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12324             break;
12325          };
12326       }
12327       ast_frfree(f);
12328       ms = newms;
12329    }
12330    /* Hangup the channel since nothing happend */
12331    ast_hangup(chan);
12332    return NULL;
12333 }
12334 #endif   /* defined(HAVE_PRI) */
12335 
12336 #if defined(HAVE_PRI)
12337 #ifndef PRI_RESTART
12338 #error "Upgrade your libpri"
12339 #endif
12340 static void dahdi_pri_message(struct pri *pri, char *s)
12341 {
12342    int x, y;
12343    int dchan = -1, span = -1;
12344    int dchancount = 0;
12345 
12346    if (pri) {
12347       for (x = 0; x < NUM_SPANS; x++) {
12348          for (y = 0; y < NUM_DCHANS; y++) {
12349             if (pris[x].dchans[y])
12350                dchancount++;
12351 
12352             if (pris[x].dchans[y] == pri)
12353                dchan = y;
12354          }
12355          if (dchan >= 0) {
12356             span = x;
12357             break;
12358          }
12359          dchancount = 0;
12360       }
12361       if (dchancount > 1 && (span > -1))
12362          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12363       else
12364          ast_verbose("%s", s);
12365    } else
12366       ast_verbose("%s", s);
12367 
12368    ast_mutex_lock(&pridebugfdlock);
12369 
12370    if (pridebugfd >= 0) {
12371       if (write(pridebugfd, s, strlen(s)) < 0) {
12372          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12373       }
12374    }
12375 
12376    ast_mutex_unlock(&pridebugfdlock);
12377 }
12378 #endif   /* defined(HAVE_PRI) */
12379 
12380 #if defined(HAVE_PRI)
12381 static void dahdi_pri_error(struct pri *pri, char *s)
12382 {
12383    int x, y;
12384    int dchan = -1, span = -1;
12385    int dchancount = 0;
12386 
12387    if (pri) {
12388       for (x = 0; x < NUM_SPANS; x++) {
12389          for (y = 0; y < NUM_DCHANS; y++) {
12390             if (pris[x].dchans[y])
12391                dchancount++;
12392 
12393             if (pris[x].dchans[y] == pri)
12394                dchan = y;
12395          }
12396          if (dchan >= 0) {
12397             span = x;
12398             break;
12399          }
12400          dchancount = 0;
12401       }
12402       if ((dchancount > 1) && (span > -1))
12403          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12404       else
12405          ast_log(LOG_ERROR, "%s", s);
12406    } else
12407       ast_log(LOG_ERROR, "%s", s);
12408 
12409    ast_mutex_lock(&pridebugfdlock);
12410 
12411    if (pridebugfd >= 0) {
12412       if (write(pridebugfd, s, strlen(s)) < 0) {
12413          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12414       }
12415    }
12416 
12417    ast_mutex_unlock(&pridebugfdlock);
12418 }
12419 #endif   /* defined(HAVE_PRI) */
12420 
12421 #if defined(HAVE_PRI)
12422 static int pri_check_restart(struct dahdi_pri *pri)
12423 {
12424    do {
12425       pri->resetpos++;
12426    } while ((pri->resetpos < pri->numchans) &&
12427       (!pri->pvts[pri->resetpos] ||
12428       pri->pvts[pri->resetpos]->call ||
12429       pri->pvts[pri->resetpos]->resetting));
12430    if (pri->resetpos < pri->numchans) {
12431       /* Mark the channel as resetting and restart it */
12432       pri->pvts[pri->resetpos]->resetting = 1;
12433       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12434    } else {
12435       pri->resetting = 0;
12436       time(&pri->lastreset);
12437    }
12438    return 0;
12439 }
12440 #endif   /* defined(HAVE_PRI) */
12441 
12442 #if defined(HAVE_PRI)
12443 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12444 {
12445    int x;
12446    int redo;
12447    ast_mutex_unlock(&pri->lock);
12448    ast_mutex_lock(&p->lock);
12449    do {
12450       redo = 0;
12451       for (x = 0; x < 3; x++) {
12452          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12453             redo++;
12454             DEADLOCK_AVOIDANCE(&p->lock);
12455          }
12456          if (p->subs[x].owner) {
12457             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12458             ast_channel_unlock(p->subs[x].owner);
12459          }
12460       }
12461    } while (redo);
12462    ast_mutex_unlock(&p->lock);
12463    ast_mutex_lock(&pri->lock);
12464    return 0;
12465 }
12466 #endif   /* defined(HAVE_PRI) */
12467 
12468 #if defined(HAVE_PRI)
12469 static char * redirectingreason2str(int redirectingreason)
12470 {
12471    switch (redirectingreason) {
12472    case 0:
12473       return "UNKNOWN";
12474    case 1:
12475       return "BUSY";
12476    case 2:
12477       return "NO_REPLY";
12478    case 0xF:
12479       return "UNCONDITIONAL";
12480    default:
12481       return "NOREDIRECT";
12482    }
12483 }
12484 #endif   /* defined(HAVE_PRI) */
12485 
12486 #if defined(HAVE_PRI)
12487 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12488 {
12489    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
12490       snprintf(buf, size, "%s", number);
12491       return;
12492    }
12493    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12494       if (size) {
12495          *buf = '\0';
12496       }
12497       return;
12498    }
12499    switch (plan) {
12500    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
12501       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12502       break;
12503    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
12504       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12505       break;
12506    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
12507       snprintf(buf, size, "%s%s", pri->localprefix, number);
12508       break;
12509    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
12510       snprintf(buf, size, "%s%s", pri->privateprefix, number);
12511       break;
12512    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
12513       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12514       break;
12515    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
12516       snprintf(buf, size, "%s", number);
12517       break;
12518    }
12519 }
12520 #endif   /* defined(HAVE_PRI) */
12521 
12522 #if defined(HAVE_PRI)
12523 static void *pri_dchannel(void *vpri)
12524 {
12525    struct dahdi_pri *pri = vpri;
12526    pri_event *e;
12527    struct pollfd fds[NUM_DCHANS];
12528    int res;
12529    int chanpos = 0;
12530    int x;
12531    int haveidles;
12532    int activeidles;
12533    int nextidle = -1;
12534    struct ast_channel *c;
12535    struct timeval tv, lowest, *next;
12536    struct timeval lastidle = ast_tvnow();
12537    int doidling=0;
12538    char *cc;
12539    char idlen[80];
12540    struct ast_channel *idle;
12541    pthread_t p;
12542    time_t t;
12543    int i, which=-1;
12544    int numdchans;
12545    int cause=0;
12546    struct dahdi_pvt *crv;
12547    pthread_t threadid;
12548    char ani2str[6];
12549    char plancallingnum[256];
12550    char plancallingani[256];
12551    char calledtonstr[10];
12552 
12553    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12554 
12555    gettimeofday(&lastidle, NULL);
12556    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12557       /* Need to do idle dialing, check to be sure though */
12558       cc = strchr(pri->idleext, '@');
12559       if (cc) {
12560          *cc = '\0';
12561          cc++;
12562          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12563 #if 0
12564          /* Extensions may not be loaded yet */
12565          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12566             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12567          else
12568 #endif
12569             doidling = 1;
12570       } else
12571          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12572    }
12573    for (;;) {
12574       for (i = 0; i < NUM_DCHANS; i++) {
12575          if (!pri->dchannels[i])
12576             break;
12577          fds[i].fd = pri->fds[i];
12578          fds[i].events = POLLIN | POLLPRI;
12579          fds[i].revents = 0;
12580       }
12581       numdchans = i;
12582       time(&t);
12583       ast_mutex_lock(&pri->lock);
12584       if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12585          if (pri->resetting && pri_is_up(pri)) {
12586             if (pri->resetpos < 0)
12587                pri_check_restart(pri);
12588          } else {
12589             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
12590                pri->resetting = 1;
12591                pri->resetpos = -1;
12592             }
12593          }
12594       }
12595       /* Look for any idle channels if appropriate */
12596       if (doidling && pri_is_up(pri)) {
12597          nextidle = -1;
12598          haveidles = 0;
12599          activeidles = 0;
12600          for (x = pri->numchans; x >= 0; x--) {
12601             if (pri->pvts[x] && !pri->pvts[x]->owner &&
12602                !pri->pvts[x]->call) {
12603                if (haveidles < pri->minunused) {
12604                   haveidles++;
12605                } else if (!pri->pvts[x]->resetting) {
12606                   nextidle = x;
12607                   break;
12608                }
12609             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12610                activeidles++;
12611          }
12612          if (nextidle > -1) {
12613             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12614                /* Don't create a new idle call more than once per second */
12615                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12616                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12617                if (idle) {
12618                   pri->pvts[nextidle]->isidlecall = 1;
12619                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12620                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12621                      dahdi_hangup(idle);
12622                   }
12623                } else
12624                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12625                lastidle = ast_tvnow();
12626             }
12627          } else if ((haveidles < pri->minunused) &&
12628             (activeidles > pri->minidle)) {
12629             /* Mark something for hangup if there is something
12630                that can be hungup */
12631             for (x = pri->numchans; x >= 0; x--) {
12632                /* find a candidate channel */
12633                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12634                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12635                   haveidles++;
12636                   /* Stop if we have enough idle channels or
12637                     can't spare any more active idle ones */
12638                   if ((haveidles >= pri->minunused) ||
12639                      (activeidles <= pri->minidle))
12640                      break;
12641                }
12642             }
12643          }
12644       }
12645       /* Start with reasonable max */
12646       lowest = ast_tv(60, 0);
12647       for (i = 0; i < NUM_DCHANS; i++) {
12648          /* Find lowest available d-channel */
12649          if (!pri->dchannels[i])
12650             break;
12651          if ((next = pri_schedule_next(pri->dchans[i]))) {
12652             /* We need relative time here */
12653             tv = ast_tvsub(*next, ast_tvnow());
12654             if (tv.tv_sec < 0) {
12655                tv = ast_tv(0,0);
12656             }
12657             if (doidling || pri->resetting) {
12658                if (tv.tv_sec > 1) {
12659                   tv = ast_tv(1, 0);
12660                }
12661             } else {
12662                if (tv.tv_sec > 60) {
12663                   tv = ast_tv(60, 0);
12664                }
12665             }
12666          } else if (doidling || pri->resetting) {
12667             /* Make sure we stop at least once per second if we're
12668                monitoring idle channels */
12669             tv = ast_tv(1,0);
12670          } else {
12671             /* Don't poll for more than 60 seconds */
12672             tv = ast_tv(60, 0);
12673          }
12674          if (!i || ast_tvcmp(tv, lowest) < 0) {
12675             lowest = tv;
12676          }
12677       }
12678       ast_mutex_unlock(&pri->lock);
12679 
12680       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12681       pthread_testcancel();
12682       e = NULL;
12683       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12684       pthread_testcancel();
12685       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12686 
12687       ast_mutex_lock(&pri->lock);
12688       if (!res) {
12689          for (which = 0; which < NUM_DCHANS; which++) {
12690             if (!pri->dchans[which])
12691                break;
12692             /* Just a timeout, run the scheduler */
12693             e = pri_schedule_run(pri->dchans[which]);
12694             if (e)
12695                break;
12696          }
12697       } else if (res > -1) {
12698          for (which = 0; which < NUM_DCHANS; which++) {
12699             if (!pri->dchans[which])
12700                break;
12701             if (fds[which].revents & POLLPRI) {
12702                /* Check for an event */
12703                x = 0;
12704                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12705                if (x) {
12706                   ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
12707                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12708                      "PRIEvent: %s\r\n"
12709                      "PRIEventCode: %d\r\n"
12710                      "D-channel: %s\r\n"
12711                      "Span: %d\r\n",
12712                      event2str(x),
12713                      x,
12714                      pri_order(which),
12715                      pri->span
12716                      );
12717                }
12718                /* Keep track of alarm state */
12719                if (x == DAHDI_EVENT_ALARM) {
12720                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12721                   pri_find_dchan(pri);
12722                } else if (x == DAHDI_EVENT_NOALARM) {
12723                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
12724                   pri_restart(pri->dchans[which]);
12725                }
12726 
12727                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12728             } else if (fds[which].revents & POLLIN) {
12729                e = pri_check_event(pri->dchans[which]);
12730             }
12731             if (e)
12732                break;
12733          }
12734       } else if (errno != EINTR)
12735          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12736 
12737       if (e) {
12738          if (pri->debug)
12739             pri_dump_event(pri->dchans[which], e);
12740 
12741          if (e->e != PRI_EVENT_DCHAN_DOWN) {
12742             if (!(pri->dchanavail[which] & DCHAN_UP)) {
12743                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12744             }
12745             pri->dchanavail[which] |= DCHAN_UP;
12746          } else if (pri->sig != SIG_BRI_PTMP) {
12747             if (pri->dchanavail[which] & DCHAN_UP) {
12748                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12749             }
12750             pri->dchanavail[which] &= ~DCHAN_UP;
12751          }
12752 
12753          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12754             /* Must be an NFAS group that has the secondary dchan active */
12755             pri->pri = pri->dchans[which];
12756 
12757          switch (e->e) {
12758          case PRI_EVENT_DCHAN_UP:
12759             if (!pri->pri) pri_find_dchan(pri);
12760 
12761             /* Note presense of D-channel */
12762             time(&pri->lastreset);
12763 
12764             /* Restart in 5 seconds */
12765             if (pri->resetinterval > -1) {
12766                pri->lastreset -= pri->resetinterval;
12767                pri->lastreset += 5;
12768             }
12769             pri->resetting = 0;
12770             /* Take the channels from inalarm condition */
12771             for (i = 0; i < pri->numchans; i++)
12772                if (pri->pvts[i]) {
12773                   pri->pvts[i]->inalarm = 0;
12774                }
12775             break;
12776          case PRI_EVENT_DCHAN_DOWN:
12777             pri_find_dchan(pri);
12778             if (!pri_is_up(pri)) {
12779                pri->resetting = 0;
12780                /* Hangup active channels and put them in alarm mode */
12781                for (i = 0; i < pri->numchans; i++) {
12782                   struct dahdi_pvt *p = pri->pvts[i];
12783                   if (p) {
12784                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12785                         /* T309 is not enabled : hangup calls when alarm occurs */
12786                         if (p->call) {
12787                            if (p->pri && p->pri->pri) {
12788                               pri_hangup(p->pri->pri, p->call, -1);
12789                               pri_destroycall(p->pri->pri, p->call);
12790                               p->call = NULL;
12791                            } else
12792                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12793                         }
12794                         if (p->realcall) {
12795                            pri_hangup_all(p->realcall, pri);
12796                         } else if (p->owner)
12797                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12798                      }
12799                      /* For PTMP connections with non persistent layer 2 we want
12800                       * to *not* declare inalarm unless there actually is an alarm */
12801                      if (p->sig != SIG_BRI_PTMP) {
12802                         p->inalarm = 1;
12803                      }
12804                   }
12805                }
12806             }
12807             break;
12808          case PRI_EVENT_RESTART:
12809             if (e->restart.channel > -1) {
12810                chanpos = pri_find_principle(pri, e->restart.channel);
12811                if (chanpos < 0)
12812                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12813                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12814                else {
12815                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12816                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12817                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12818                   if (pri->pvts[chanpos]->call) {
12819                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12820                      pri->pvts[chanpos]->call = NULL;
12821                   }
12822                   /* Force soft hangup if appropriate */
12823                   if (pri->pvts[chanpos]->realcall)
12824                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12825                   else if (pri->pvts[chanpos]->owner)
12826                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12827                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12828                }
12829             } else {
12830                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12831                for (x = 0; x < pri->numchans; x++)
12832                   if (pri->pvts[x]) {
12833                      ast_mutex_lock(&pri->pvts[x]->lock);
12834                      if (pri->pvts[x]->call) {
12835                         pri_destroycall(pri->pri, pri->pvts[x]->call);
12836                         pri->pvts[x]->call = NULL;
12837                      }
12838                      if (pri->pvts[x]->realcall)
12839                         pri_hangup_all(pri->pvts[x]->realcall, pri);
12840                      else if (pri->pvts[x]->owner)
12841                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12842                      ast_mutex_unlock(&pri->pvts[x]->lock);
12843                   }
12844             }
12845             break;
12846          case PRI_EVENT_KEYPAD_DIGIT:
12847             chanpos = pri_find_principle(pri, e->digit.channel);
12848             if (chanpos < 0) {
12849                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12850                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12851             } else {
12852                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12853                if (chanpos > -1) {
12854                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12855                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
12856                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12857                      /* how to do that */
12858                      int digitlen = strlen(e->digit.digits);
12859                      char digit;
12860                      int i;
12861                      for (i = 0; i < digitlen; i++) {
12862                         digit = e->digit.digits[i];
12863                         {
12864                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12865                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12866                         }
12867                      }
12868                   }
12869                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12870                }
12871             }
12872             break;
12873 
12874          case PRI_EVENT_INFO_RECEIVED:
12875             chanpos = pri_find_principle(pri, e->ring.channel);
12876             if (chanpos < 0) {
12877                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12878                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12879             } else {
12880                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12881                if (chanpos > -1) {
12882                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12883                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
12884                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12885                      /* how to do that */
12886                      int digitlen = strlen(e->ring.callednum);
12887                      char digit;
12888                      int i;
12889                      for (i = 0; i < digitlen; i++) {
12890                         digit = e->ring.callednum[i];
12891                         {
12892                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12893                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12894                         }
12895                      }
12896                   }
12897                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12898                }
12899             }
12900             break;
12901          case PRI_EVENT_RING:
12902             crv = NULL;
12903             if (e->ring.channel == -1)
12904                chanpos = pri_find_empty_chan(pri, 1);
12905             else
12906                chanpos = pri_find_principle(pri, e->ring.channel);
12907             /* if no channel specified find one empty */
12908             if (chanpos < 0) {
12909                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12910                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12911             } else {
12912                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12913                if (pri->pvts[chanpos]->owner) {
12914                   if (pri->pvts[chanpos]->call == e->ring.call) {
12915                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12916                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12917                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12918                      break;
12919                   } else {
12920                      /* This is where we handle initial glare */
12921                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
12922                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12923                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12924                      chanpos = -1;
12925                   }
12926                }
12927                if (chanpos > -1)
12928                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12929             }
12930             if ((chanpos < 0) && (e->ring.flexible))
12931                chanpos = pri_find_empty_chan(pri, 1);
12932             if (chanpos > -1) {
12933                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12934                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12935                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
12936                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12937                   if (crv)
12938                      ast_mutex_lock(&crv->lock);
12939                   if (!crv || crv->owner) {
12940                      pri->pvts[chanpos]->call = NULL;
12941                      if (crv) {
12942                         if (crv->owner)
12943                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12944                         ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12945                      } else
12946                         ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12947                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12948                      if (crv)
12949                         ast_mutex_unlock(&crv->lock);
12950                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12951                      break;
12952                   }
12953                }
12954                pri->pvts[chanpos]->call = e->ring.call;
12955                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12956                if (pri->pvts[chanpos]->use_callerid) {
12957                   ast_shrink_phone_number(plancallingnum);
12958                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12959 #ifdef PRI_ANI
12960                   if (!ast_strlen_zero(e->ring.callingani)) {
12961                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12962                      ast_shrink_phone_number(plancallingani);
12963                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12964                   } else {
12965                      pri->pvts[chanpos]->cid_ani[0] = '\0';
12966                   }
12967 #endif
12968                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12969                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
12970                } else {
12971                   pri->pvts[chanpos]->cid_num[0] = '\0';
12972                   pri->pvts[chanpos]->cid_ani[0] = '\0';
12973                   pri->pvts[chanpos]->cid_name[0] = '\0';
12974                   pri->pvts[chanpos]->cid_ton = 0;
12975                }
12976                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12977                   e->ring.redirectingnum, e->ring.callingplanrdnis);
12978 
12979                /* Set DNID on all incoming calls -- even immediate */
12980                ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12981 
12982                /* If immediate=yes go to s|1 */
12983                if (pri->pvts[chanpos]->immediate) {
12984                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12985                   pri->pvts[chanpos]->exten[0] = 's';
12986                   pri->pvts[chanpos]->exten[1] = '\0';
12987                }
12988                /* Get called number */
12989                else if (!ast_strlen_zero(e->ring.callednum)) {
12990                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12991                } else if (pri->overlapdial)
12992                   pri->pvts[chanpos]->exten[0] = '\0';
12993                else {
12994                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
12995                   pri->pvts[chanpos]->exten[0] = 's';
12996                   pri->pvts[chanpos]->exten[1] = '\0';
12997                }
12998                /* No number yet, but received "sending complete"? */
12999                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13000                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
13001                   pri->pvts[chanpos]->exten[0] = 's';
13002                   pri->pvts[chanpos]->exten[1] = '\0';
13003                }
13004 
13005                /* Make sure extension exists (or in overlap dial mode, can exist) */
13006                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13007                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13008                   /* Setup law */
13009                   int law;
13010                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13011                      /* Set to audio mode at this point */
13012                      law = 1;
13013                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13014                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13015                   }
13016                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13017                      law = DAHDI_LAW_ALAW;
13018                   else
13019                      law = DAHDI_LAW_MULAW;
13020                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13021                   if (res < 0)
13022                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13023                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13024                   if (res < 0)
13025                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13026                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13027                      /* Just announce proceeding */
13028                      pri->pvts[chanpos]->proceeding = 1;
13029                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13030                   } else {
13031                      if (pri->switchtype != PRI_SWITCH_GR303_TMC)
13032                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13033                      else
13034                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13035                   }
13036                   /* Get the use_callingpres state */
13037                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13038 
13039                   /* Start PBX */
13040                   if (!e->ring.complete
13041                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13042                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13043                      /*
13044                       * Release the PRI lock while we create the channel
13045                       * so other threads can send D channel messages.
13046                       */
13047                      ast_mutex_unlock(&pri->lock);
13048                      if (crv) {
13049                         /* Set bearer and such */
13050                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13051                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13052                         pri->pvts[chanpos]->owner = &inuse;
13053                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13054                      } else {
13055                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13056                      }
13057                      ast_mutex_lock(&pri->lock);
13058                      if (c) {
13059                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13060                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13061                         }
13062                         if (e->ring.ani2 >= 0) {
13063                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13064                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13065                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13066                         }
13067 
13068 #ifdef SUPPORT_USERUSER
13069                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
13070                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13071                         }
13072 #endif
13073 
13074                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13075                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13076                         if (e->ring.redirectingreason >= 0)
13077                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13078                      }
13079                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13080                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13081                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13082                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13083                      } else {
13084                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13085                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13086                         if (c)
13087                            ast_hangup(c);
13088                         else {
13089                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13090                            pri->pvts[chanpos]->call = NULL;
13091                         }
13092                      }
13093                   } else {
13094                      /*
13095                       * Release the PRI lock while we create the channel
13096                       * so other threads can send D channel messages.
13097                       */
13098                      ast_mutex_unlock(&pri->lock);
13099                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13100                      ast_mutex_lock(&pri->lock);
13101                      if (c) {
13102                         /*
13103                          * It is reasonably safe to set the following
13104                          * channel variables while the PRI and DAHDI private
13105                          * structures are locked.  The PBX has not been
13106                          * started yet and it is unlikely that any other task
13107                          * will do anything with the channel we have just
13108                          * created.
13109                          */
13110                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13111                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13112                         }
13113                         if (e->ring.ani2 >= 0) {
13114                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13115                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13116                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13117                         }
13118 
13119 #ifdef SUPPORT_USERUSER
13120                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
13121                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13122                         }
13123 #endif
13124 
13125                         if (e->ring.redirectingreason >= 0)
13126                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13127 
13128                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13129                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13130                      }
13131                      if (c && !ast_pbx_start(c)) {
13132                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13133                            plancallingnum, pri->pvts[chanpos]->exten,
13134                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13135 
13136                         dahdi_enable_ec(pri->pvts[chanpos]);
13137                      } else {
13138                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13139                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13140                         if (c) {
13141                            ast_hangup(c);
13142                         } else {
13143                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13144                            pri->pvts[chanpos]->call = NULL;
13145                         }
13146                      }
13147                   }
13148                } else {
13149                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
13150                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13151                      pri->pvts[chanpos]->prioffset, pri->span);
13152                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13153                   pri->pvts[chanpos]->call = NULL;
13154                   pri->pvts[chanpos]->exten[0] = '\0';
13155                }
13156                if (crv)
13157                   ast_mutex_unlock(&crv->lock);
13158                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13159             } else {
13160                if (e->ring.flexible)
13161                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13162                else
13163                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13164             }
13165             break;
13166          case PRI_EVENT_RINGING:
13167             chanpos = pri_find_principle(pri, e->ringing.channel);
13168             if (chanpos < 0) {
13169                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13170                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13171             } else {
13172                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13173                if (chanpos < 0) {
13174                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13175                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13176                } else {
13177                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13178                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13179                      dahdi_enable_ec(pri->pvts[chanpos]);
13180                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13181                      pri->pvts[chanpos]->alerting = 1;
13182                   } else
13183                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13184 
13185                   if (
13186 #ifdef PRI_PROGRESS_MASK
13187                      e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13188 #else
13189                      e->ringing.progress == 8
13190 #endif
13191                      ) {
13192                      /* Now we can do call progress detection */
13193                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13194                         /* RINGING detection isn't required because we got ALERTING signal */
13195                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13196                         pri->pvts[chanpos]->dsp_features = 0;
13197                      }
13198                   }
13199 
13200 #ifdef SUPPORT_USERUSER
13201                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13202                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13203                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13204                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13205                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13206                   }
13207 #endif
13208 
13209                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13210                }
13211             }
13212             break;
13213          case PRI_EVENT_PROGRESS:
13214             /* Get chan value if e->e is not PRI_EVNT_RINGING */
13215             chanpos = pri_find_principle(pri, e->proceeding.channel);
13216             if (chanpos > -1) {
13217                if ((!pri->pvts[chanpos]->progress)
13218 #ifdef PRI_PROGRESS_MASK
13219                   || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13220 #else
13221                   || (e->proceeding.progress == 8)
13222 #endif
13223                   ) {
13224                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13225 
13226                   if (e->proceeding.cause > -1) {
13227                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13228 
13229                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
13230                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13231                         if (pri->pvts[chanpos]->owner) {
13232                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13233 
13234                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13235                            f.subclass = AST_CONTROL_BUSY;
13236                         }
13237                      }
13238                   }
13239 
13240                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13241                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13242                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13243                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13244                   if (
13245 #ifdef PRI_PROGRESS_MASK
13246                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13247 #else
13248                      e->proceeding.progress == 8
13249 #endif
13250                      ) {
13251                      /* Now we can do call progress detection */
13252                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13253                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13254                         pri->pvts[chanpos]->dsp_features = 0;
13255                      }
13256                      /* Bring voice path up */
13257                      f.subclass = AST_CONTROL_PROGRESS;
13258                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13259                   }
13260                   pri->pvts[chanpos]->progress = 1;
13261                   pri->pvts[chanpos]->dialing = 0;
13262                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13263                }
13264             }
13265             break;
13266          case PRI_EVENT_PROCEEDING:
13267             chanpos = pri_find_principle(pri, e->proceeding.channel);
13268             if (chanpos > -1) {
13269                if (!pri->pvts[chanpos]->proceeding) {
13270                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13271 
13272                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13273                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13274                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13275                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13276                   if (
13277 #ifdef PRI_PROGRESS_MASK
13278                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13279 #else
13280                      e->proceeding.progress == 8
13281 #endif
13282                      ) {
13283                      /* Now we can do call progress detection */
13284                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13285                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13286                         pri->pvts[chanpos]->dsp_features = 0;
13287                      }
13288                      /* Bring voice path up */
13289                      f.subclass = AST_CONTROL_PROGRESS;
13290                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13291                   }
13292                   pri->pvts[chanpos]->proceeding = 1;
13293                   pri->pvts[chanpos]->dialing = 0;
13294                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13295                }
13296             }
13297             break;
13298          case PRI_EVENT_FACNAME:
13299             chanpos = pri_find_principle(pri, e->facname.channel);
13300             if (chanpos < 0) {
13301                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13302                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13303             } else {
13304                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13305                if (chanpos < 0) {
13306                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13307                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13308                } else if (pri->pvts[chanpos]->use_callerid) {
13309                   /* Re-use *69 field for PRI */
13310                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13311                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13312                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13313                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
13314                   dahdi_enable_ec(pri->pvts[chanpos]);
13315                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13316                }
13317             }
13318             break;
13319          case PRI_EVENT_ANSWER:
13320             chanpos = pri_find_principle(pri, e->answer.channel);
13321             if (chanpos < 0) {
13322                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13323                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13324             } else {
13325                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13326                if (chanpos < 0) {
13327                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13328                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13329                } else {
13330                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13331                   /* Now we can do call progress detection */
13332 
13333                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
13334                    * By this time, we need DTMF detection and other features that were previously disabled
13335                    * -- Matt F */
13336                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13337                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13338                      pri->pvts[chanpos]->dsp_features = 0;
13339                   }
13340                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13341                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13342                      x = DAHDI_START;
13343                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13344                      if (res < 0) {
13345                         if (errno != EINPROGRESS) {
13346                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13347                         }
13348                      }
13349                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13350                      pri->pvts[chanpos]->dialing = 1;
13351                      /* Send any "w" waited stuff */
13352                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13353                      if (res < 0) {
13354                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13355                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13356                      } else
13357                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13358 
13359                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13360                   } else if (pri->pvts[chanpos]->confirmanswer) {
13361                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13362                   } else {
13363                      pri->pvts[chanpos]->dialing = 0;
13364                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13365                      /* Enable echo cancellation if it's not on already */
13366                      dahdi_enable_ec(pri->pvts[chanpos]);
13367                   }
13368 
13369 #ifdef SUPPORT_USERUSER
13370                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
13371                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13372                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13373                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13374                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13375                   }
13376 #endif
13377 
13378                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13379                }
13380             }
13381             break;
13382          case PRI_EVENT_HANGUP:
13383             chanpos = pri_find_principle(pri, e->hangup.channel);
13384             if (chanpos < 0) {
13385                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13386                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13387             } else {
13388                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13389                if (chanpos > -1) {
13390                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13391                   if (!pri->pvts[chanpos]->alreadyhungup) {
13392                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
13393                      pri->pvts[chanpos]->alreadyhungup = 1;
13394                      if (pri->pvts[chanpos]->realcall)
13395                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13396                      else if (pri->pvts[chanpos]->owner) {
13397                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
13398                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13399                         switch (pri->pvts[chanpos]->owner->_state) {
13400                         case AST_STATE_BUSY:
13401                         case AST_STATE_UP:
13402                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13403                            break;
13404                         default:
13405                            switch (e->hangup.cause) {
13406                            case PRI_CAUSE_USER_BUSY:
13407                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13408                               break;
13409                            case PRI_CAUSE_CALL_REJECTED:
13410                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13411                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13412                            case PRI_CAUSE_SWITCH_CONGESTION:
13413                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13414                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13415                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13416                               break;
13417                            default:
13418                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13419                            }
13420                            break;
13421                         }
13422                      }
13423                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13424                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13425                   } else {
13426                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13427                      pri->pvts[chanpos]->call = NULL;
13428                   }
13429                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13430                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13431                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13432                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13433                      pri->pvts[chanpos]->resetting = 1;
13434                   }
13435                   if (e->hangup.aoc_units > -1)
13436                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13437                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13438 
13439 #ifdef SUPPORT_USERUSER
13440                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13441                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13442                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13443                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13444                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13445                   }
13446 #endif
13447 
13448                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13449                } else {
13450                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13451                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13452                }
13453             }
13454             break;
13455 #ifndef PRI_EVENT_HANGUP_REQ
13456 #error please update libpri
13457 #endif
13458          case PRI_EVENT_HANGUP_REQ:
13459             chanpos = pri_find_principle(pri, e->hangup.channel);
13460             if (chanpos < 0) {
13461                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13462                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13463             } else {
13464                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13465                if (chanpos > -1) {
13466                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13467                   if (pri->pvts[chanpos]->realcall)
13468                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13469                   else if (pri->pvts[chanpos]->owner) {
13470                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13471                      switch (pri->pvts[chanpos]->owner->_state) {
13472                      case AST_STATE_BUSY:
13473                      case AST_STATE_UP:
13474                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13475                         break;
13476                      default:
13477                         switch (e->hangup.cause) {
13478                         case PRI_CAUSE_USER_BUSY:
13479                            pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13480                            break;
13481                         case PRI_CAUSE_CALL_REJECTED:
13482                         case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13483                         case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13484                         case PRI_CAUSE_SWITCH_CONGESTION:
13485                         case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13486                         case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13487                            pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13488                            break;
13489                         default:
13490                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13491                            break;
13492                         }
13493                         break;
13494                      }
13495                      ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
13496                      if (e->hangup.aoc_units > -1)
13497                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13498                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13499                   } else {
13500                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13501                      pri->pvts[chanpos]->call = NULL;
13502                   }
13503                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13504                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13505                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13506                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13507                      pri->pvts[chanpos]->resetting = 1;
13508                   }
13509 
13510 #ifdef SUPPORT_USERUSER
13511                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13512                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13513                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13514                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13515                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13516                   }
13517 #endif
13518 
13519                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13520                } else {
13521                   ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13522                }
13523             }
13524             break;
13525          case PRI_EVENT_HANGUP_ACK:
13526             chanpos = pri_find_principle(pri, e->hangup.channel);
13527             if (chanpos < 0) {
13528                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13529                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13530             } else {
13531                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13532                if (chanpos > -1) {
13533                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13534                   pri->pvts[chanpos]->call = NULL;
13535                   pri->pvts[chanpos]->resetting = 0;
13536                   if (pri->pvts[chanpos]->owner) {
13537                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13538                   }
13539 
13540 #ifdef SUPPORT_USERUSER
13541                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13542                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13543                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13544                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13545                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13546                   }
13547 #endif
13548 
13549                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13550                }
13551             }
13552             break;
13553          case PRI_EVENT_CONFIG_ERR:
13554             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
13555             break;
13556          case PRI_EVENT_RESTART_ACK:
13557             chanpos = pri_find_principle(pri, e->restartack.channel);
13558             if (chanpos < 0) {
13559                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
13560                   channel number, so we have to figure it out...  This must be why
13561                   everybody resets exactly a channel at a time. */
13562                for (x = 0; x < pri->numchans; x++) {
13563                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
13564                      chanpos = x;
13565                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13566                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13567                         pri->pvts[chanpos]->prioffset, pri->span);
13568                      if (pri->pvts[chanpos]->realcall)
13569                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13570                      else if (pri->pvts[chanpos]->owner) {
13571                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13572                            pri->pvts[chanpos]->prioffset, pri->span);
13573                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13574                      }
13575                      pri->pvts[chanpos]->resetting = 0;
13576                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13577                            pri->pvts[chanpos]->prioffset, pri->span);
13578                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13579                      if (pri->resetting)
13580                         pri_check_restart(pri);
13581                      break;
13582                   }
13583                }
13584                if (chanpos < 0) {
13585                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13586                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13587                }
13588             } else {
13589                if (pri->pvts[chanpos]) {
13590                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13591                   if (pri->pvts[chanpos]->realcall)
13592                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13593                   else if (pri->pvts[chanpos]->owner) {
13594                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13595                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13596                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13597                   }
13598                   pri->pvts[chanpos]->resetting = 0;
13599                   pri->pvts[chanpos]->inservice = 1;
13600                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13601                            pri->pvts[chanpos]->prioffset, pri->span);
13602                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13603                   if (pri->resetting)
13604                      pri_check_restart(pri);
13605                }
13606             }
13607             break;
13608          case PRI_EVENT_SETUP_ACK:
13609             chanpos = pri_find_principle(pri, e->setup_ack.channel);
13610             if (chanpos < 0) {
13611                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13612                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13613             } else {
13614                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13615                if (chanpos > -1) {
13616                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13617                   pri->pvts[chanpos]->setup_ack = 1;
13618                   /* Send any queued digits */
13619                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13620                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13621                      pri_information(pri->pri, pri->pvts[chanpos]->call,
13622                         pri->pvts[chanpos]->dialdest[x]);
13623                   }
13624                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13625                } else
13626                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13627             }
13628             break;
13629          case PRI_EVENT_NOTIFY:
13630             chanpos = pri_find_principle(pri, e->notify.channel);
13631             if (chanpos < 0) {
13632                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13633                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13634             } else if (!pri->discardremoteholdretrieval) {
13635                struct ast_frame f = { AST_FRAME_CONTROL, };
13636                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13637                switch (e->notify.info) {
13638                case PRI_NOTIFY_REMOTE_HOLD:
13639                   f.subclass = AST_CONTROL_HOLD;
13640                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13641                   break;
13642                case PRI_NOTIFY_REMOTE_RETRIEVAL:
13643                   f.subclass = AST_CONTROL_UNHOLD;
13644                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13645                   break;
13646                }
13647                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13648             }
13649             break;
13650          default:
13651             ast_debug(1, "Event: %d\n", e->e);
13652          }
13653       }
13654       ast_mutex_unlock(&pri->lock);
13655    }
13656    /* Never reached */
13657    return NULL;
13658 }
13659 #endif   /* defined(HAVE_PRI) */
13660 
13661 #if defined(HAVE_PRI)
13662 static int start_pri(struct dahdi_pri *pri)
13663 {
13664    int res, x;
13665    struct dahdi_params p;
13666    struct dahdi_bufferinfo bi;
13667    struct dahdi_spaninfo si;
13668    int i;
13669 
13670    for (i = 0; i < NUM_DCHANS; i++) {
13671       if (!pri->dchannels[i])
13672          break;
13673       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13674       x = pri->dchannels[i];
13675       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13676          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13677          return -1;
13678       }
13679       memset(&p, 0, sizeof(p));
13680       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13681       if (res) {
13682          dahdi_close_pri_fd(pri, i);
13683          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13684          return -1;
13685       }
13686       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13687          dahdi_close_pri_fd(pri, i);
13688          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13689          return -1;
13690       }
13691       memset(&si, 0, sizeof(si));
13692       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13693       if (res) {
13694          dahdi_close_pri_fd(pri, i);
13695          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13696       }
13697       if (!si.alarms)
13698          pri->dchanavail[i] |= DCHAN_NOTINALARM;
13699       else
13700          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13701       memset(&bi, 0, sizeof(bi));
13702       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13703       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13704       bi.numbufs = 32;
13705       bi.bufsize = 1024;
13706       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13707          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13708          dahdi_close_pri_fd(pri, i);
13709          return -1;
13710       }
13711       switch (pri->sig) {
13712       case SIG_BRI:
13713          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13714          break;
13715       case SIG_BRI_PTMP:
13716          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13717          break;
13718       default:
13719          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13720          break;
13721       }
13722       /* Force overlap dial if we're doing GR-303! */
13723       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13724          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13725       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13726 #ifdef HAVE_PRI_PROG_W_CAUSE
13727       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13728 #endif
13729 #ifdef HAVE_PRI_INBANDDISCONNECT
13730       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13731 #endif
13732       /* Enslave to master if appropriate */
13733       if (i)
13734          pri_enslave(pri->dchans[0], pri->dchans[i]);
13735       if (!pri->dchans[i]) {
13736          dahdi_close_pri_fd(pri, i);
13737          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13738          return -1;
13739       }
13740       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13741       pri_set_nsf(pri->dchans[i], pri->nsf);
13742 #ifdef PRI_GETSET_TIMERS
13743       for (x = 0; x < PRI_MAX_TIMERS; x++) {
13744          if (pritimers[x] != 0)
13745             pri_set_timer(pri->dchans[i], x, pritimers[x]);
13746       }
13747 #endif
13748    }
13749    /* Assume primary is the one we use */
13750    pri->pri = pri->dchans[0];
13751    pri->resetpos = -1;
13752    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13753       for (i = 0; i < NUM_DCHANS; i++) {
13754          if (!pri->dchannels[i])
13755             break;
13756          dahdi_close_pri_fd(pri, i);
13757       }
13758       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13759       return -1;
13760    }
13761    return 0;
13762 }
13763 #endif   /* defined(HAVE_PRI) */
13764 
13765 #if defined(HAVE_PRI)
13766 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13767 {
13768    int which, span;
13769    char *ret = NULL;
13770 
13771    if (pos != rpos)
13772       return ret;
13773 
13774    for (which = span = 0; span < NUM_SPANS; span++) {
13775       if (pris[span].pri && ++which > state) {
13776          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13777             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13778          }
13779          break;
13780       }
13781    }
13782    return ret;
13783 }
13784 #endif   /* defined(HAVE_PRI) */
13785 
13786 #if defined(HAVE_PRI)
13787 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13788 {
13789    return complete_span_helper(line,word,pos,state,3);
13790 }
13791 #endif   /* defined(HAVE_PRI) */
13792 
13793 #if defined(HAVE_PRI)
13794 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13795 {
13796    int myfd;
13797    switch (cmd) {
13798    case CLI_INIT:
13799       e->command = "pri set debug file";
13800       e->usage = "Usage: pri set debug file [output-file]\n"
13801          "       Sends PRI debug output to the specified output file\n";
13802       return NULL;
13803    case CLI_GENERATE:
13804       return NULL;
13805    }
13806    if (a->argc < 5)
13807       return CLI_SHOWUSAGE;
13808 
13809    if (ast_strlen_zero(a->argv[4]))
13810       return CLI_SHOWUSAGE;
13811 
13812    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13813    if (myfd < 0) {
13814       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13815       return CLI_SUCCESS;
13816    }
13817 
13818    ast_mutex_lock(&pridebugfdlock);
13819 
13820    if (pridebugfd >= 0)
13821       close(pridebugfd);
13822 
13823    pridebugfd = myfd;
13824    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13825    ast_mutex_unlock(&pridebugfdlock);
13826    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13827    return CLI_SUCCESS;
13828 }
13829 #endif   /* defined(HAVE_PRI) */
13830 
13831 #if defined(HAVE_PRI)
13832 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13833 {
13834    int span;
13835    int x;
13836    int level = 0;
13837    switch (cmd) {
13838    case CLI_INIT:
13839       e->command = "pri set debug {on|off|0|1|2} span";
13840       e->usage =
13841          "Usage: pri set debug {<level>|on|off} span <span>\n"
13842          "       Enables debugging on a given PRI span\n";
13843       return NULL;
13844    case CLI_GENERATE:
13845       return complete_span_4(a->line, a->word, a->pos, a->n);
13846    }
13847    if (a->argc < 6) {
13848       return CLI_SHOWUSAGE;
13849    }
13850 
13851    if (!strcasecmp(a->argv[3], "on")) {
13852       level = 1;
13853    } else if (!strcasecmp(a->argv[3], "off")) {
13854       level = 0;
13855    } else {
13856       level = atoi(a->argv[3]);
13857    }
13858    span = atoi(a->argv[5]);
13859    if ((span < 1) || (span > NUM_SPANS)) {
13860       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13861       return CLI_SUCCESS;
13862    }
13863    if (!pris[span-1].pri) {
13864       ast_cli(a->fd, "No PRI running on span %d\n", span);
13865       return CLI_SUCCESS;
13866    }
13867    for (x = 0; x < NUM_DCHANS; x++) {
13868       if (pris[span-1].dchans[x]) {
13869          if (level == 1) {
13870             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13871                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13872                PRI_DEBUG_Q921_STATE);
13873             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13874          } else if (level == 0) {
13875             pri_set_debug(pris[span-1].dchans[x], 0);
13876             //close the file if it's set
13877             ast_mutex_lock(&pridebugfdlock);
13878             close(pridebugfd);
13879             pridebugfd = -1;
13880             ast_cli(a->fd, "PRI debug output to file disabled\n");
13881             ast_mutex_unlock(&pridebugfdlock);
13882          } else {
13883             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13884                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13885                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13886             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13887          }
13888       }
13889    }
13890    return CLI_SUCCESS;
13891 }
13892 #endif   /* defined(HAVE_PRI) */
13893 
13894 #if defined(HAVE_PRI)
13895 static void build_status(char *s, size_t len, int status, int active)
13896 {
13897    if (!s || len < 1) {
13898       return;
13899    }
13900    s[0] = '\0';
13901    if (status & DCHAN_PROVISIONED)
13902       strncat(s, "Provisioned, ", len - strlen(s) - 1);
13903    if (!(status & DCHAN_NOTINALARM))
13904       strncat(s, "In Alarm, ", len - strlen(s) - 1);
13905    if (status & DCHAN_UP)
13906       strncat(s, "Up", len - strlen(s) - 1);
13907    else
13908       strncat(s, "Down", len - strlen(s) - 1);
13909    if (active)
13910       strncat(s, ", Active", len - strlen(s) - 1);
13911    else
13912       strncat(s, ", Standby", len - strlen(s) - 1);
13913    s[len - 1] = '\0';
13914 }
13915 #endif   /* defined(HAVE_PRI) */
13916 
13917 #if defined(HAVE_PRI)
13918 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13919 {
13920    int span;
13921    int x;
13922    char status[256];
13923 
13924    switch (cmd) {
13925    case CLI_INIT:
13926       e->command = "pri show spans";
13927       e->usage =
13928          "Usage: pri show spans\n"
13929          "       Displays PRI Information\n";
13930       return NULL;
13931    case CLI_GENERATE:
13932       return NULL;
13933    }
13934 
13935    if (a->argc != 3)
13936       return CLI_SHOWUSAGE;
13937 
13938    for (span = 0; span < NUM_SPANS; span++) {
13939       if (pris[span].pri) {
13940          for (x = 0; x < NUM_DCHANS; x++) {
13941             if (pris[span].dchannels[x]) {
13942                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13943                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13944             }
13945          }
13946       }
13947    }
13948    return CLI_SUCCESS;
13949 }
13950 #endif   /* defined(HAVE_PRI) */
13951 
13952 #if defined(HAVE_PRI)
13953 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13954 {
13955    int span;
13956    int x;
13957    char status[256];
13958    switch (cmd) {
13959    case CLI_INIT:
13960       e->command = "pri show span";
13961       e->usage =
13962          "Usage: pri show span <span>\n"
13963          "       Displays PRI Information on a given PRI span\n";
13964       return NULL;
13965    case CLI_GENERATE:
13966       return complete_span_4(a->line, a->word, a->pos, a->n);
13967    }
13968 
13969    if (a->argc < 4)
13970       return CLI_SHOWUSAGE;
13971    span = atoi(a->argv[3]);
13972    if ((span < 1) || (span > NUM_SPANS)) {
13973       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13974       return CLI_SUCCESS;
13975    }
13976    if (!pris[span-1].pri) {
13977       ast_cli(a->fd, "No PRI running on span %d\n", span);
13978       return CLI_SUCCESS;
13979    }
13980    for (x = 0; x < NUM_DCHANS; x++) {
13981       if (pris[span-1].dchannels[x]) {
13982 #ifdef PRI_DUMP_INFO_STR
13983          char *info_str = NULL;
13984 #endif
13985          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13986          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13987          ast_cli(a->fd, "Status: %s\n", status);
13988 #ifdef PRI_DUMP_INFO_STR
13989          info_str = pri_dump_info_str(pris[span-1].pri);
13990          if (info_str) {
13991             ast_cli(a->fd, "%s", info_str);
13992             ast_free(info_str);
13993          }
13994 #else
13995          pri_dump_info(pris[span-1].pri);
13996 #endif
13997          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13998       }
13999    }
14000    return CLI_SUCCESS;
14001 }
14002 #endif   /* defined(HAVE_PRI) */
14003 
14004 #if defined(HAVE_PRI)
14005 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14006 {
14007    int x;
14008    int span;
14009    int count=0;
14010    int debug=0;
14011 
14012    switch (cmd) {
14013    case CLI_INIT:
14014       e->command = "pri show debug";
14015       e->usage =
14016          "Usage: pri show debug\n"
14017          "  Show the debug state of pri spans\n";
14018       return NULL;
14019    case CLI_GENERATE:
14020       return NULL;
14021    }
14022 
14023    for (span = 0; span < NUM_SPANS; span++) {
14024       if (pris[span].pri) {
14025          for (x = 0; x < NUM_DCHANS; x++) {
14026             debug = 0;
14027             if (pris[span].dchans[x]) {
14028                debug = pri_get_debug(pris[span].dchans[x]);
14029                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
14030                count++;
14031             }
14032          }
14033       }
14034 
14035    }
14036    ast_mutex_lock(&pridebugfdlock);
14037    if (pridebugfd >= 0)
14038       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14039    ast_mutex_unlock(&pridebugfdlock);
14040 
14041    if (!count)
14042       ast_cli(a->fd, "No debug set or no PRI running\n");
14043    return CLI_SUCCESS;
14044 }
14045 #endif   /* defined(HAVE_PRI) */
14046 
14047 #if defined(HAVE_PRI)
14048 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14049 {
14050    switch (cmd) {
14051    case CLI_INIT:
14052       e->command = "pri show version";
14053       e->usage =
14054          "Usage: pri show version\n"
14055          "Show libpri version information\n";
14056       return NULL;
14057    case CLI_GENERATE:
14058       return NULL;
14059    }
14060 
14061    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14062 
14063    return CLI_SUCCESS;
14064 }
14065 #endif   /* defined(HAVE_PRI) */
14066 
14067 #if defined(HAVE_PRI)
14068 static struct ast_cli_entry dahdi_pri_cli[] = {
14069    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14070    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14071    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14072    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14073    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14074    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14075 };
14076 #endif   /* defined(HAVE_PRI) */
14077 
14078 #ifdef HAVE_OPENR2
14079 
14080 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14081 {
14082    switch (cmd) {
14083    case CLI_INIT:
14084       e->command = "mfcr2 show version";
14085       e->usage =
14086          "Usage: mfcr2 show version\n"
14087          "       Shows the version of the OpenR2 library being used.\n";
14088       return NULL;
14089    case CLI_GENERATE:
14090       return NULL;
14091    }
14092    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14093    return CLI_SUCCESS;
14094 }
14095 
14096 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14097 {
14098 #define FORMAT "%4s %40s\n"
14099    int i = 0;
14100    int numvariants = 0;
14101    const openr2_variant_entry_t *variants;
14102    switch (cmd) {
14103    case CLI_INIT:
14104       e->command = "mfcr2 show variants";
14105       e->usage =
14106          "Usage: mfcr2 show variants\n"
14107          "       Shows the list of MFC/R2 variants supported.\n";
14108       return NULL;
14109    case CLI_GENERATE:
14110       return NULL;
14111    }
14112    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14113       ast_cli(a->fd, "Failed to get list of variants.\n");
14114       return CLI_FAILURE;
14115    }
14116    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14117    for (i = 0; i < numvariants; i++) {
14118       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14119    }
14120    return CLI_SUCCESS;
14121 #undef FORMAT
14122 }
14123 
14124 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14125 {
14126 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14127    int filtertype = 0;
14128    int targetnum = 0;
14129    char channo[5];
14130    char anino[5];
14131    char dnisno[5];
14132    struct dahdi_pvt *p;
14133    openr2_context_t *r2context;
14134    openr2_variant_t r2variant;
14135    switch (cmd) {
14136    case CLI_INIT:
14137       e->command = "mfcr2 show channels [group|context]";
14138       e->usage =
14139          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14140          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14141       return NULL;
14142    case CLI_GENERATE:
14143       return NULL;
14144    }
14145    if (!((a->argc == 3) || (a->argc == 5))) {
14146       return CLI_SHOWUSAGE;
14147    }
14148    if (a->argc == 5) {
14149       if (!strcasecmp(a->argv[3], "group")) {
14150          targetnum = atoi(a->argv[4]);
14151          if ((targetnum < 0) || (targetnum > 63))
14152             return CLI_SHOWUSAGE;
14153          targetnum = 1 << targetnum;
14154          filtertype = 1;
14155       } else if (!strcasecmp(a->argv[3], "context")) {
14156          filtertype = 2;
14157       } else {
14158          return CLI_SHOWUSAGE;
14159       }
14160    }
14161    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14162    ast_mutex_lock(&iflock);
14163    p = iflist;
14164    for (p = iflist; p; p = p->next) {
14165       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14166          continue;
14167       }
14168       if (filtertype) {
14169          switch(filtertype) {
14170          case 1: /* mfcr2 show channels group <group> */
14171             if (p->group != targetnum) {
14172                continue;
14173             }
14174             break;
14175          case 2: /* mfcr2 show channels context <context> */
14176             if (strcasecmp(p->context, a->argv[4])) {
14177                continue;
14178             }
14179             break;
14180          default:
14181             ;
14182          }
14183       }
14184       r2context = openr2_chan_get_context(p->r2chan);
14185       r2variant = openr2_context_get_variant(r2context);
14186       snprintf(channo, sizeof(channo), "%d", p->channel);
14187       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14188       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14189       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14190             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14191             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14192             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14193    }
14194    ast_mutex_unlock(&iflock);
14195    return CLI_SUCCESS;
14196 #undef FORMAT
14197 }
14198 
14199 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14200 {
14201    struct dahdi_pvt *p = NULL;
14202    int channo = 0;
14203    char *toklevel = NULL;
14204    char *saveptr = NULL;
14205    char *logval = NULL;
14206    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14207    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14208    switch (cmd) {
14209    case CLI_INIT:
14210       e->command = "mfcr2 set debug";
14211       e->usage =
14212          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14213          "       Set a new logging level for the specified channel.\n"
14214          "       If no channel is specified the logging level will be applied to all channels.\n";
14215       return NULL;
14216    case CLI_GENERATE:
14217       return NULL;
14218    }
14219    if (a->argc < 4) {
14220       return CLI_SHOWUSAGE;
14221    }
14222    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14223    logval = ast_strdupa(a->argv[3]);
14224    toklevel = strtok_r(logval, ",", &saveptr);
14225    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14226       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14227       return CLI_FAILURE;
14228    } else if (OR2_LOG_NOTHING == tmplevel) {
14229       loglevel = tmplevel;
14230    } else {
14231       loglevel |= tmplevel;
14232       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14233          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14234             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14235             continue;
14236          }
14237          loglevel |= tmplevel;
14238       }
14239    }
14240    ast_mutex_lock(&iflock);
14241    for (p = iflist; p; p = p->next) {
14242       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14243          continue;
14244       }
14245       if ((channo != -1) && (p->channel != channo )) {
14246          continue;
14247       }
14248       openr2_chan_set_log_level(p->r2chan, loglevel);
14249       if (channo != -1) {
14250          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14251          break;
14252       }
14253    }
14254    if ((channo != -1) && !p) {
14255       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14256    }
14257    if (channo == -1) {
14258       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14259    }
14260    ast_mutex_unlock(&iflock);
14261    return CLI_SUCCESS;
14262 }
14263 
14264 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14265 {
14266    struct dahdi_pvt *p = NULL;
14267    int channo = 0;
14268    switch (cmd) {
14269    case CLI_INIT:
14270       e->command = "mfcr2 call files [on|off]";
14271       e->usage =
14272          "Usage: mfcr2 call files [on|off] <channel>\n"
14273          "       Enable call files creation on the specified channel.\n"
14274          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14275       return NULL;
14276    case CLI_GENERATE:
14277       return NULL;
14278    }
14279    if (a->argc < 4) {
14280       return CLI_SHOWUSAGE;
14281    }
14282    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14283    ast_mutex_lock(&iflock);
14284    for (p = iflist; p; p = p->next) {
14285       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14286          continue;
14287       }
14288       if ((channo != -1) && (p->channel != channo )) {
14289          continue;
14290       }
14291       if (ast_true(a->argv[3])) {
14292          openr2_chan_enable_call_files(p->r2chan);
14293       } else {
14294          openr2_chan_disable_call_files(p->r2chan);
14295       }
14296       if (channo != -1) {
14297          if (ast_true(a->argv[3])) {
14298             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14299          } else {
14300             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14301          }
14302          break;
14303       }
14304    }
14305    if ((channo != -1) && !p) {
14306       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14307    }
14308    if (channo == -1) {
14309       if (ast_true(a->argv[3])) {
14310          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14311       } else {
14312          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14313       }
14314    }
14315    ast_mutex_unlock(&iflock);
14316    return CLI_SUCCESS;
14317 }
14318 
14319 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14320 {
14321    struct dahdi_pvt *p = NULL;
14322    int channo = 0;
14323    switch (cmd) {
14324    case CLI_INIT:
14325       e->command = "mfcr2 set idle";
14326       e->usage =
14327          "Usage: mfcr2 set idle <channel>\n"
14328          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14329          "       Force the given channel into IDLE state.\n"
14330          "       If no channel is specified, all channels will be set to IDLE.\n";
14331       return NULL;
14332    case CLI_GENERATE:
14333       return NULL;
14334    }
14335    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14336    ast_mutex_lock(&iflock);
14337    for (p = iflist; p; p = p->next) {
14338       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14339          continue;
14340       }
14341       if ((channo != -1) && (p->channel != channo )) {
14342          continue;
14343       }
14344       openr2_chan_set_idle(p->r2chan);
14345       ast_mutex_lock(&p->lock);
14346       p->locallyblocked = 0;
14347       p->mfcr2call = 0;
14348       ast_mutex_unlock(&p->lock);
14349       if (channo != -1) {
14350          break;
14351       }
14352    }
14353    if ((channo != -1) && !p) {
14354       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14355    }
14356    ast_mutex_unlock(&iflock);
14357    return CLI_SUCCESS;
14358 }
14359 
14360 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14361 {
14362    struct dahdi_pvt *p = NULL;
14363    int channo = 0;
14364    switch (cmd) {
14365    case CLI_INIT:
14366       e->command = "mfcr2 set blocked";
14367       e->usage =
14368          "Usage: mfcr2 set blocked <channel>\n"
14369          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14370          "       Force the given channel into BLOCKED state.\n"
14371          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14372       return NULL;
14373    case CLI_GENERATE:
14374       return NULL;
14375    }
14376    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14377    ast_mutex_lock(&iflock);
14378    for (p = iflist; p; p = p->next) {
14379       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14380          continue;
14381       }
14382       if ((channo != -1) && (p->channel != channo )) {
14383          continue;
14384       }
14385       openr2_chan_set_blocked(p->r2chan);
14386       ast_mutex_lock(&p->lock);
14387       p->locallyblocked = 1;
14388       ast_mutex_unlock(&p->lock);
14389       if (channo != -1) {
14390          break;
14391       }
14392    }
14393    if ((channo != -1) && !p) {
14394       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14395    }
14396    ast_mutex_unlock(&iflock);
14397    return CLI_SUCCESS;
14398 }
14399 
14400 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14401    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14402    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14403    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14404    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14405    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14406    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14407    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14408 };
14409 
14410 #endif /* HAVE_OPENR2 */
14411 
14412 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14413 {
14414    int channel;
14415    int ret;
14416    switch (cmd) {
14417    case CLI_INIT:
14418       e->command = "dahdi destroy channel";
14419       e->usage =
14420          "Usage: dahdi destroy channel <chan num>\n"
14421          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14422       return NULL;
14423    case CLI_GENERATE:
14424       return NULL;
14425    }
14426    if (a->argc != 4)
14427       return CLI_SHOWUSAGE;
14428 
14429    channel = atoi(a->argv[3]);
14430    ret = dahdi_destroy_channel_bynum(channel);
14431    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14432 }
14433 
14434 static void dahdi_softhangup_all(void)
14435 {
14436    struct dahdi_pvt *p;
14437 retry:
14438    ast_mutex_lock(&iflock);
14439    for (p = iflist; p; p = p->next) {
14440       ast_mutex_lock(&p->lock);
14441       if (p->owner && !p->restartpending) {
14442          if (ast_channel_trylock(p->owner)) {
14443             if (option_debug > 2)
14444                ast_verbose("Avoiding deadlock\n");
14445             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14446             ast_mutex_unlock(&p->lock);
14447             ast_mutex_unlock(&iflock);
14448             goto retry;
14449          }
14450          if (option_debug > 2)
14451             ast_verbose("Softhanging up on %s\n", p->owner->name);
14452          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14453          p->restartpending = 1;
14454          num_restart_pending++;
14455          ast_channel_unlock(p->owner);
14456       }
14457       ast_mutex_unlock(&p->lock);
14458    }
14459    ast_mutex_unlock(&iflock);
14460 }
14461 
14462 static int setup_dahdi(int reload);
14463 static int dahdi_restart(void)
14464 {
14465 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14466    int i, j;
14467 #endif
14468    int cancel_code;
14469    struct dahdi_pvt *p;
14470 
14471    ast_mutex_lock(&restart_lock);
14472    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14473    dahdi_softhangup_all();
14474    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14475 #ifdef HAVE_OPENR2
14476    dahdi_r2_destroy_links();
14477 #endif
14478 
14479 #if defined(HAVE_PRI)
14480    for (i = 0; i < NUM_SPANS; i++) {
14481       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14482          cancel_code = pthread_cancel(pris[i].master);
14483          pthread_kill(pris[i].master, SIGURG);
14484          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14485          pthread_join(pris[i].master, NULL);
14486          ast_debug(4, "Joined thread of span %d\n", i);
14487       }
14488    }
14489 #endif
14490 
14491 #if defined(HAVE_SS7)
14492    for (i = 0; i < NUM_SPANS; i++) {
14493       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14494          cancel_code = pthread_cancel(linksets[i].master);
14495          pthread_kill(linksets[i].master, SIGURG);
14496          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14497          pthread_join(linksets[i].master, NULL);
14498          ast_debug(4, "Joined thread of span %d\n", i);
14499       }
14500    }
14501 #endif
14502 
14503    ast_mutex_lock(&monlock);
14504    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14505       cancel_code = pthread_cancel(monitor_thread);
14506       pthread_kill(monitor_thread, SIGURG);
14507       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14508       pthread_join(monitor_thread, NULL);
14509       ast_debug(4, "Joined monitor thread\n");
14510    }
14511    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14512 
14513    ast_mutex_lock(&ss_thread_lock);
14514    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14515       int x = DAHDI_FLASH;
14516       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14517 
14518       for (p = iflist; p; p = p->next) {
14519          if (p->owner)
14520             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
14521          }
14522          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14523       }
14524 
14525    /* ensure any created channels before monitor threads were stopped are hungup */
14526    dahdi_softhangup_all();
14527    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14528    destroy_all_channels();
14529    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14530 
14531    ast_mutex_unlock(&monlock);
14532 
14533 #ifdef HAVE_PRI
14534    for (i = 0; i < NUM_SPANS; i++) {
14535       for (j = 0; j < NUM_DCHANS; j++)
14536          dahdi_close_pri_fd(&(pris[i]), j);
14537    }
14538 
14539    memset(pris, 0, sizeof(pris));
14540    for (i = 0; i < NUM_SPANS; i++) {
14541       ast_mutex_init(&pris[i].lock);
14542       pris[i].offset = -1;
14543       pris[i].master = AST_PTHREADT_NULL;
14544       for (j = 0; j < NUM_DCHANS; j++)
14545          pris[i].fds[j] = -1;
14546       }
14547    pri_set_error(dahdi_pri_error);
14548    pri_set_message(dahdi_pri_message);
14549 #endif
14550 #ifdef HAVE_SS7
14551    for (i = 0; i < NUM_SPANS; i++) {
14552       for (j = 0; j < NUM_DCHANS; j++)
14553          dahdi_close_ss7_fd(&(linksets[i]), j);
14554    }
14555 
14556    memset(linksets, 0, sizeof(linksets));
14557    for (i = 0; i < NUM_SPANS; i++) {
14558       ast_mutex_init(&linksets[i].lock);
14559       linksets[i].master = AST_PTHREADT_NULL;
14560       for (j = 0; j < NUM_DCHANS; j++)
14561          linksets[i].fds[j] = -1;
14562    }
14563    ss7_set_error(dahdi_ss7_error);
14564    ss7_set_message(dahdi_ss7_message);
14565 #endif
14566 
14567    if (setup_dahdi(2) != 0) {
14568       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14569       ast_mutex_unlock(&ss_thread_lock);
14570       return 1;
14571    }
14572    ast_mutex_unlock(&ss_thread_lock);
14573    ast_mutex_unlock(&restart_lock);
14574    return 0;
14575 }
14576 
14577 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14578 {
14579    switch (cmd) {
14580    case CLI_INIT:
14581       e->command = "dahdi restart";
14582       e->usage =
14583          "Usage: dahdi restart\n"
14584          "  Restarts the DAHDI channels: destroys them all and then\n"
14585          "  re-reads them from chan_dahdi.conf.\n"
14586          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14587          "";
14588       return NULL;
14589    case CLI_GENERATE:
14590       return NULL;
14591    }
14592    if (a->argc != 2)
14593       return CLI_SHOWUSAGE;
14594 
14595    if (dahdi_restart() != 0)
14596       return CLI_FAILURE;
14597    return CLI_SUCCESS;
14598 }
14599 
14600 static int action_dahdirestart(struct mansession *s, const struct message *m)
14601 {
14602    if (dahdi_restart() != 0) {
14603       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14604       return 1;
14605    }
14606    astman_send_ack(s, m, "DAHDIRestart: Success");
14607    return 0;
14608 }
14609 
14610 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14611 {
14612 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14613 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14614    unsigned int targetnum = 0;
14615    int filtertype = 0;
14616    struct dahdi_pvt *tmp = NULL;
14617    char tmps[20] = "";
14618    char statestr[20] = "";
14619    char blockstr[20] = "";
14620    ast_mutex_t *lock;
14621    struct dahdi_pvt *start;
14622 #ifdef HAVE_PRI
14623    int trunkgroup;
14624    struct dahdi_pri *pri = NULL;
14625    int x;
14626 #endif
14627    switch (cmd) {
14628    case CLI_INIT:
14629       e->command = "dahdi show channels [trunkgroup|group|context]";
14630       e->usage =
14631          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14632          "  Shows a list of available channels with optional filtering\n"
14633          "  <group> must be a number between 0 and 63\n";
14634       return NULL;
14635    case CLI_GENERATE:
14636       return NULL;
14637    }
14638 
14639    lock = &iflock;
14640    start = iflist;
14641 
14642    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
14643 
14644    if (!((a->argc == 3) || (a->argc == 5)))
14645       return CLI_SHOWUSAGE;
14646 
14647    if (a->argc == 5) {
14648 #ifdef HAVE_PRI
14649       if (!strcasecmp(a->argv[3], "trunkgroup")) {
14650          /* this option requires no special handling, so leave filtertype to zero */
14651          if ((trunkgroup = atoi(a->argv[4])) < 1)
14652             return CLI_SHOWUSAGE;
14653          for (x = 0; x < NUM_SPANS; x++) {
14654             if (pris[x].trunkgroup == trunkgroup) {
14655                pri = pris + x;
14656                break;
14657             }
14658          }
14659          if (pri) {
14660             start = pri->crvs;
14661             lock = &pri->lock;
14662          } else {
14663             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14664             return CLI_FAILURE;
14665          }
14666       } else
14667 #endif
14668       if (!strcasecmp(a->argv[3], "group")) {
14669          targetnum = atoi(a->argv[4]);
14670          if ((targetnum < 0) || (targetnum > 63))
14671             return CLI_SHOWUSAGE;
14672          targetnum = 1 << targetnum;
14673          filtertype = 1;
14674       } else if (!strcasecmp(a->argv[3], "context")) {
14675          filtertype = 2;
14676       }
14677    }
14678 
14679    ast_mutex_lock(lock);
14680 #ifdef HAVE_PRI
14681    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14682 #else
14683    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14684 #endif
14685 
14686    tmp = start;
14687    while (tmp) {
14688       if (filtertype) {
14689          switch(filtertype) {
14690          case 1: /* dahdi show channels group <group> */
14691             if (!(tmp->group & targetnum)) {
14692                tmp = tmp->next;
14693                continue;
14694             }
14695             break;
14696          case 2: /* dahdi show channels context <context> */
14697             if (strcasecmp(tmp->context, a->argv[4])) {
14698                tmp = tmp->next;
14699                continue;
14700             }
14701             break;
14702          default:
14703             ;
14704          }
14705       }
14706       if (tmp->channel > 0) {
14707          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14708       } else
14709          ast_copy_string(tmps, "pseudo", sizeof(tmps));
14710 
14711       if (tmp->locallyblocked)
14712          blockstr[0] = 'L';
14713       else
14714          blockstr[0] = ' ';
14715 
14716       if (tmp->remotelyblocked)
14717          blockstr[1] = 'R';
14718       else
14719          blockstr[1] = ' ';
14720 
14721       blockstr[2] = '\0';
14722 
14723       snprintf(statestr, sizeof(statestr), "%s", "In Service");
14724 
14725       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14726       tmp = tmp->next;
14727    }
14728    ast_mutex_unlock(lock);
14729    return CLI_SUCCESS;
14730 #undef FORMAT
14731 #undef FORMAT2
14732 }
14733 
14734 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14735 {
14736    int channel;
14737    struct dahdi_pvt *tmp = NULL;
14738    struct dahdi_confinfo ci;
14739    struct dahdi_params ps;
14740    int x;
14741    ast_mutex_t *lock;
14742    struct dahdi_pvt *start;
14743 #ifdef HAVE_PRI
14744    char *c;
14745    int trunkgroup;
14746    struct dahdi_pri *pri=NULL;
14747 #endif
14748    switch (cmd) {
14749    case CLI_INIT:
14750       e->command = "dahdi show channel";
14751       e->usage =
14752          "Usage: dahdi show channel <chan num>\n"
14753          "  Detailed information about a given channel\n";
14754       return NULL;
14755    case CLI_GENERATE:
14756       return NULL;
14757    }
14758 
14759    lock = &iflock;
14760    start = iflist;
14761 
14762    if (a->argc != 4)
14763       return CLI_SHOWUSAGE;
14764 #ifdef HAVE_PRI
14765    if ((c = strchr(a->argv[3], ':'))) {
14766       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14767          return CLI_SHOWUSAGE;
14768       if ((trunkgroup < 1) || (channel < 1))
14769          return CLI_SHOWUSAGE;
14770       for (x = 0; x < NUM_SPANS; x++) {
14771          if (pris[x].trunkgroup == trunkgroup) {
14772             pri = pris + x;
14773             break;
14774          }
14775       }
14776       if (pri) {
14777          start = pri->crvs;
14778          lock = &pri->lock;
14779       } else {
14780          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14781          return CLI_FAILURE;
14782       }
14783    } else
14784 #endif
14785       channel = atoi(a->argv[3]);
14786 
14787    ast_mutex_lock(lock);
14788    tmp = start;
14789    while (tmp) {
14790       if (tmp->channel == channel) {
14791 #ifdef HAVE_PRI
14792          if (pri)
14793             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14794          else
14795 #endif
14796          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14797          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14798          ast_cli(a->fd, "Span: %d\n", tmp->span);
14799          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14800          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14801          ast_cli(a->fd, "Context: %s\n", tmp->context);
14802          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14803          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14804          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14805          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14806          if (tmp->vars) {
14807             struct ast_variable *v;
14808             ast_cli(a->fd, "Variables:\n");
14809             for (v = tmp->vars ; v ; v = v->next)
14810                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14811          }
14812          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14813          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14814          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14815          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14816          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14817          ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
14818          ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
14819          ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
14820          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14821          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14822          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14823          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14824          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14825          if (tmp->busydetect) {
14826 #if defined(BUSYDETECT_TONEONLY)
14827             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14828 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14829             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14830 #endif
14831 #ifdef BUSYDETECT_DEBUG
14832             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14833 #endif
14834             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14835             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14836          }
14837          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14838          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14839          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14840          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14841          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14842          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14843          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14844          ast_cli(a->fd, "Echo Cancellation:\n");
14845 
14846          if (tmp->echocancel.head.tap_length) {
14847             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14848             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14849                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14850             }
14851             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14852          } else {
14853             ast_cli(a->fd, "\tnone\n");
14854          }
14855          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14856          if (tmp->master)
14857             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14858          for (x = 0; x < MAX_SLAVES; x++) {
14859             if (tmp->slaves[x])
14860                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14861          }
14862 #ifdef HAVE_OPENR2
14863          if (tmp->mfcr2) {
14864             char calldir[OR2_MAX_PATH];
14865             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14866             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14867             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14868             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14869             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14870             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14871             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14872             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14873             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14874             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14875             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14876 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14877             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14878 #endif
14879             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14880             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14881             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14882             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14883             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14884             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14885             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14886             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14887             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14888             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14889             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14890             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14891          }
14892 #endif
14893 #ifdef HAVE_SS7
14894          if (tmp->ss7) {
14895             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14896          }
14897 #endif
14898 #ifdef HAVE_PRI
14899          if (tmp->pri) {
14900             ast_cli(a->fd, "PRI Flags: ");
14901             if (tmp->resetting)
14902                ast_cli(a->fd, "Resetting ");
14903             if (tmp->call)
14904                ast_cli(a->fd, "Call ");
14905             if (tmp->bearer)
14906                ast_cli(a->fd, "Bearer ");
14907             ast_cli(a->fd, "\n");
14908             if (tmp->logicalspan)
14909                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14910             else
14911                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14912          }
14913 #endif
14914          memset(&ci, 0, sizeof(ci));
14915          ps.channo = tmp->channel;
14916          if (tmp->subs[SUB_REAL].dfd > -1) {
14917             memset(&ci, 0, sizeof(ci));
14918             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14919                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14920             }
14921             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14922                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14923             }
14924             memset(&ps, 0, sizeof(ps));
14925             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14926                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14927             } else {
14928                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14929             }
14930          }
14931          ast_mutex_unlock(lock);
14932          return CLI_SUCCESS;
14933       }
14934       tmp = tmp->next;
14935    }
14936 
14937    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14938    ast_mutex_unlock(lock);
14939    return CLI_FAILURE;
14940 }
14941 
14942 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14943 {
14944    int i, j;
14945    switch (cmd) {
14946    case CLI_INIT:
14947       e->command = "dahdi show cadences";
14948       e->usage =
14949          "Usage: dahdi show cadences\n"
14950          "       Shows all cadences currently defined\n";
14951       return NULL;
14952    case CLI_GENERATE:
14953       return NULL;
14954    }
14955    for (i = 0; i < num_cadence; i++) {
14956       char output[1024];
14957       char tmp[16], tmp2[64];
14958       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14959       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14960 
14961       for (j = 0; j < 16; j++) {
14962          if (cadences[i].ringcadence[j] == 0)
14963             break;
14964          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14965          if (cidrings[i] * 2 - 1 == j)
14966             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14967          else
14968             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14969          if (j != 0)
14970             strncat(output, ",", sizeof(output) - strlen(output) - 1);
14971          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14972       }
14973       ast_cli(a->fd,"%s\n",output);
14974    }
14975    return CLI_SUCCESS;
14976 }
14977 
14978 /* Based on irqmiss.c */
14979 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14980 {
14981    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14982    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14983    int span;
14984    int res;
14985    char alarmstr[50];
14986 
14987    int ctl;
14988    struct dahdi_spaninfo s;
14989 
14990    switch (cmd) {
14991    case CLI_INIT:
14992       e->command = "dahdi show status";
14993       e->usage =
14994          "Usage: dahdi show status\n"
14995          "       Shows a list of DAHDI cards with status\n";
14996       return NULL;
14997    case CLI_GENERATE:
14998       return NULL;
14999    }
15000    ctl = open("/dev/dahdi/ctl", O_RDWR);
15001    if (ctl < 0) {
15002       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15003       return CLI_FAILURE;
15004    }
15005    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15006 
15007    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15008       s.spanno = span;
15009       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15010       if (res) {
15011          continue;
15012       }
15013       alarmstr[0] = '\0';
15014       if (s.alarms > 0) {
15015          if (s.alarms & DAHDI_ALARM_BLUE)
15016             strcat(alarmstr, "BLU/");
15017          if (s.alarms & DAHDI_ALARM_YELLOW)
15018             strcat(alarmstr, "YEL/");
15019          if (s.alarms & DAHDI_ALARM_RED)
15020             strcat(alarmstr, "RED/");
15021          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15022             strcat(alarmstr, "LB/");
15023          if (s.alarms & DAHDI_ALARM_RECOVER)
15024             strcat(alarmstr, "REC/");
15025          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15026             strcat(alarmstr, "NOP/");
15027          if (!strlen(alarmstr))
15028             strcat(alarmstr, "UUU/");
15029          if (strlen(alarmstr)) {
15030             /* Strip trailing / */
15031             alarmstr[strlen(alarmstr) - 1] = '\0';
15032          }
15033       } else {
15034          if (s.numchans)
15035             strcpy(alarmstr, "OK");
15036          else
15037             strcpy(alarmstr, "UNCONFIGURED");
15038       }
15039 
15040       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15041          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15042          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15043          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15044          "CAS",
15045          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15046          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15047          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15048          "Unk",
15049          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15050             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15051             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15052          lbostr[s.lbo]
15053          );
15054    }
15055    close(ctl);
15056 
15057    return CLI_SUCCESS;
15058 #undef FORMAT
15059 #undef FORMAT2
15060 }
15061 
15062 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15063 {
15064    int pseudo_fd = -1;
15065    struct dahdi_versioninfo vi;
15066 
15067    switch (cmd) {
15068    case CLI_INIT:
15069       e->command = "dahdi show version";
15070       e->usage =
15071          "Usage: dahdi show version\n"
15072          "       Shows the DAHDI version in use\n";
15073       return NULL;
15074    case CLI_GENERATE:
15075       return NULL;
15076    }
15077    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15078       ast_cli(a->fd, "Failed to open control file to get version.\n");
15079       return CLI_SUCCESS;
15080    }
15081 
15082    strcpy(vi.version, "Unknown");
15083    strcpy(vi.echo_canceller, "Unknown");
15084 
15085    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15086       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15087    else
15088       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15089 
15090    close(pseudo_fd);
15091 
15092    return CLI_SUCCESS;
15093 }
15094 
15095 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15096 {
15097    int channel;
15098    int gain;
15099    int tx;
15100    struct dahdi_hwgain hwgain;
15101    struct dahdi_pvt *tmp = NULL;
15102 
15103    switch (cmd) {
15104    case CLI_INIT:
15105       e->command = "dahdi set hwgain";
15106       e->usage =
15107          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15108          "  Sets the hardware gain on a a given channel, overriding the\n"
15109          "   value provided at module loadtime, whether the channel is in\n"
15110          "   use or not.  Changes take effect immediately.\n"
15111          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15112          "   <chan num> is the channel number relative to the device\n"
15113          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15114       return NULL;
15115    case CLI_GENERATE:
15116       return NULL;
15117    }
15118 
15119    if (a->argc != 6)
15120       return CLI_SHOWUSAGE;
15121 
15122    if (!strcasecmp("rx", a->argv[3]))
15123       tx = 0; /* rx */
15124    else if (!strcasecmp("tx", a->argv[3]))
15125       tx = 1; /* tx */
15126    else
15127       return CLI_SHOWUSAGE;
15128 
15129    channel = atoi(a->argv[4]);
15130    gain = atof(a->argv[5])*10.0;
15131 
15132    ast_mutex_lock(&iflock);
15133 
15134    for (tmp = iflist; tmp; tmp = tmp->next) {
15135 
15136       if (tmp->channel != channel)
15137          continue;
15138 
15139       if (tmp->subs[SUB_REAL].dfd == -1)
15140          break;
15141 
15142       hwgain.newgain = gain;
15143       hwgain.tx = tx;
15144       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15145          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15146          ast_mutex_unlock(&iflock);
15147          return CLI_FAILURE;
15148       }
15149       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15150          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15151       break;
15152    }
15153 
15154    ast_mutex_unlock(&iflock);
15155 
15156    if (tmp)
15157       return CLI_SUCCESS;
15158 
15159    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15160    return CLI_FAILURE;
15161 
15162 }
15163 
15164 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15165 {
15166    int channel;
15167    float gain;
15168    int tx;
15169    int res;
15170    ast_mutex_t *lock;
15171    struct dahdi_pvt *tmp = NULL;
15172 
15173    switch (cmd) {
15174    case CLI_INIT:
15175       e->command = "dahdi set swgain";
15176       e->usage =
15177          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15178          "  Sets the software gain on a a given channel, overriding the\n"
15179          "   value provided at module loadtime, whether the channel is in\n"
15180          "   use or not.  Changes take effect immediately.\n"
15181          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15182          "   <chan num> is the channel number relative to the device\n"
15183          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15184       return NULL;
15185    case CLI_GENERATE:
15186       return NULL;
15187    }
15188 
15189    lock = &iflock;
15190 
15191    if (a->argc != 6)
15192       return CLI_SHOWUSAGE;
15193 
15194    if (!strcasecmp("rx", a->argv[3]))
15195       tx = 0; /* rx */
15196    else if (!strcasecmp("tx", a->argv[3]))
15197       tx = 1; /* tx */
15198    else
15199       return CLI_SHOWUSAGE;
15200 
15201    channel = atoi(a->argv[4]);
15202    gain = atof(a->argv[5]);
15203 
15204    ast_mutex_lock(lock);
15205    for (tmp = iflist; tmp; tmp = tmp->next) {
15206 
15207       if (tmp->channel != channel)
15208          continue;
15209 
15210       if (tmp->subs[SUB_REAL].dfd == -1)
15211          break;
15212 
15213       if (tx)
15214          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15215       else
15216          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15217 
15218       if (res) {
15219          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15220          ast_mutex_unlock(lock);
15221          return CLI_FAILURE;
15222       }
15223 
15224       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15225          tx ? "tx" : "rx", gain, channel);
15226       break;
15227    }
15228    ast_mutex_unlock(lock);
15229 
15230    if (tmp)
15231       return CLI_SUCCESS;
15232 
15233    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15234    return CLI_FAILURE;
15235 
15236 }
15237 
15238 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15239 {
15240    int channel;
15241    int on;
15242    struct dahdi_pvt *dahdi_chan = NULL;
15243 
15244    switch (cmd) {
15245    case CLI_INIT:
15246       e->command = "dahdi set dnd";
15247       e->usage =
15248          "Usage: dahdi set dnd <chan#> <on|off>\n"
15249          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15250          "  Changes take effect immediately.\n"
15251          "  <chan num> is the channel number\n"
15252          "  <on|off> Enable or disable DND mode?\n"
15253          ;
15254       return NULL;
15255    case CLI_GENERATE:
15256       return NULL;
15257    }
15258 
15259    if (a->argc != 5)
15260       return CLI_SHOWUSAGE;
15261 
15262    if ((channel = atoi(a->argv[3])) <= 0) {
15263       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15264       return CLI_SHOWUSAGE;
15265    }
15266 
15267    if (ast_true(a->argv[4]))
15268       on = 1;
15269    else if (ast_false(a->argv[4]))
15270       on = 0;
15271    else {
15272       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15273       return CLI_SHOWUSAGE;
15274    }
15275 
15276    ast_mutex_lock(&iflock);
15277    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15278       if (dahdi_chan->channel != channel)
15279          continue;
15280 
15281       /* Found the channel. Actually set it */
15282       dahdi_dnd(dahdi_chan, on);
15283       break;
15284    }
15285    ast_mutex_unlock(&iflock);
15286 
15287    if (!dahdi_chan) {
15288       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15289       return CLI_FAILURE;
15290    }
15291 
15292    return CLI_SUCCESS;
15293 }
15294 
15295 static struct ast_cli_entry dahdi_cli[] = {
15296    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15297    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15298    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15299    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15300    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15301    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15302    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15303    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15304    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15305    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15306 };
15307 
15308 #define TRANSFER  0
15309 #define HANGUP    1
15310 
15311 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15312 {
15313    if (p) {
15314       switch (mode) {
15315          case TRANSFER:
15316             p->fake_event = DAHDI_EVENT_WINKFLASH;
15317             break;
15318          case HANGUP:
15319             p->fake_event = DAHDI_EVENT_ONHOOK;
15320             break;
15321          default:
15322             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15323       }
15324    }
15325    return 0;
15326 }
15327 static struct dahdi_pvt *find_channel(int channel)
15328 {
15329    struct dahdi_pvt *p = iflist;
15330    while (p) {
15331       if (p->channel == channel) {
15332          break;
15333       }
15334       p = p->next;
15335    }
15336    return p;
15337 }
15338 
15339 static int action_dahdidndon(struct mansession *s, const struct message *m)
15340 {
15341    struct dahdi_pvt *p = NULL;
15342    const char *channel = astman_get_header(m, "DAHDIChannel");
15343 
15344    if (ast_strlen_zero(channel)) {
15345       astman_send_error(s, m, "No channel specified");
15346       return 0;
15347    }
15348    p = find_channel(atoi(channel));
15349    if (!p) {
15350       astman_send_error(s, m, "No such channel");
15351       return 0;
15352    }
15353    p->dnd = 1;
15354    astman_send_ack(s, m, "DND Enabled");
15355    return 0;
15356 }
15357 
15358 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15359 {
15360    struct dahdi_pvt *p = NULL;
15361    const char *channel = astman_get_header(m, "DAHDIChannel");
15362 
15363    if (ast_strlen_zero(channel)) {
15364       astman_send_error(s, m, "No channel specified");
15365       return 0;
15366    }
15367    p = find_channel(atoi(channel));
15368    if (!p) {
15369       astman_send_error(s, m, "No such channel");
15370       return 0;
15371    }
15372    p->dnd = 0;
15373    astman_send_ack(s, m, "DND Disabled");
15374    return 0;
15375 }
15376 
15377 static int action_transfer(struct mansession *s, const struct message *m)
15378 {
15379    struct dahdi_pvt *p = NULL;
15380    const char *channel = astman_get_header(m, "DAHDIChannel");
15381 
15382    if (ast_strlen_zero(channel)) {
15383       astman_send_error(s, m, "No channel specified");
15384       return 0;
15385    }
15386    p = find_channel(atoi(channel));
15387    if (!p) {
15388       astman_send_error(s, m, "No such channel");
15389       return 0;
15390    }
15391    dahdi_fake_event(p,TRANSFER);
15392    astman_send_ack(s, m, "DAHDITransfer");
15393    return 0;
15394 }
15395 
15396 static int action_transferhangup(struct mansession *s, const struct message *m)
15397 {
15398    struct dahdi_pvt *p = NULL;
15399    const char *channel = astman_get_header(m, "DAHDIChannel");
15400 
15401    if (ast_strlen_zero(channel)) {
15402       astman_send_error(s, m, "No channel specified");
15403       return 0;
15404    }
15405    p = find_channel(atoi(channel));
15406    if (!p) {
15407       astman_send_error(s, m, "No such channel");
15408       return 0;
15409    }
15410    dahdi_fake_event(p,HANGUP);
15411    astman_send_ack(s, m, "DAHDIHangup");
15412    return 0;
15413 }
15414 
15415 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15416 {
15417    struct dahdi_pvt *p = NULL;
15418    const char *channel = astman_get_header(m, "DAHDIChannel");
15419    const char *number = astman_get_header(m, "Number");
15420    int i;
15421 
15422    if (ast_strlen_zero(channel)) {
15423       astman_send_error(s, m, "No channel specified");
15424       return 0;
15425    }
15426    if (ast_strlen_zero(number)) {
15427       astman_send_error(s, m, "No number specified");
15428       return 0;
15429    }
15430    p = find_channel(atoi(channel));
15431    if (!p) {
15432       astman_send_error(s, m, "No such channel");
15433       return 0;
15434    }
15435    if (!p->owner) {
15436       astman_send_error(s, m, "Channel does not have it's owner");
15437       return 0;
15438    }
15439    for (i = 0; i < strlen(number); i++) {
15440       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15441       dahdi_queue_frame(p, &f, NULL);
15442    }
15443    astman_send_ack(s, m, "DAHDIDialOffhook");
15444    return 0;
15445 }
15446 
15447 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15448 {
15449    struct dahdi_pvt *tmp = NULL;
15450    const char *id = astman_get_header(m, "ActionID");
15451    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15452    char idText[256] = "";
15453    int channels = 0;
15454    int dahdichanquery = -1;
15455    if (!ast_strlen_zero(dahdichannel)) {
15456       dahdichanquery = atoi(dahdichannel);
15457    }
15458 
15459    astman_send_ack(s, m, "DAHDI channel status will follow");
15460    if (!ast_strlen_zero(id))
15461       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15462 
15463    ast_mutex_lock(&iflock);
15464 
15465    tmp = iflist;
15466    while (tmp) {
15467       if (tmp->channel > 0) {
15468          int alm = get_alarms(tmp);
15469 
15470          /* If a specific channel is queried for, only deliver status for that channel */
15471          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15472             continue;
15473 
15474          channels++;
15475          if (tmp->owner) {
15476             /* Add data if we have a current call */
15477             astman_append(s,
15478                "Event: DAHDIShowChannels\r\n"
15479                "DAHDIChannel: %d\r\n"
15480                "Channel: %s\r\n"
15481                "Uniqueid: %s\r\n"
15482                "AccountCode: %s\r\n"
15483                "Signalling: %s\r\n"
15484                "SignallingCode: %d\r\n"
15485                "Context: %s\r\n"
15486                "DND: %s\r\n"
15487                "Alarm: %s\r\n"
15488                "%s"
15489                "\r\n",
15490                tmp->channel,
15491                tmp->owner->name,
15492                tmp->owner->uniqueid,
15493                tmp->owner->accountcode,
15494                sig2str(tmp->sig),
15495                tmp->sig,
15496                tmp->context,
15497                tmp->dnd ? "Enabled" : "Disabled",
15498                alarm2str(alm), idText);
15499          } else {
15500             astman_append(s,
15501                "Event: DAHDIShowChannels\r\n"
15502                "DAHDIChannel: %d\r\n"
15503                "Signalling: %s\r\n"
15504                "SignallingCode: %d\r\n"
15505                "Context: %s\r\n"
15506                "DND: %s\r\n"
15507                "Alarm: %s\r\n"
15508                "%s"
15509                "\r\n",
15510                tmp->channel, sig2str(tmp->sig), tmp->sig,
15511                tmp->context,
15512                tmp->dnd ? "Enabled" : "Disabled",
15513                alarm2str(alm), idText);
15514          }
15515       }
15516 
15517       tmp = tmp->next;
15518    }
15519 
15520    ast_mutex_unlock(&iflock);
15521 
15522    astman_append(s,
15523       "Event: DAHDIShowChannelsComplete\r\n"
15524       "%s"
15525       "Items: %d\r\n"
15526       "\r\n",
15527       idText,
15528       channels);
15529    return 0;
15530 }
15531 
15532 #if defined(HAVE_SS7)
15533 static int linkset_addsigchan(int sigchan)
15534 {
15535    struct dahdi_ss7 *link;
15536    int res;
15537    int curfd;
15538    struct dahdi_params p;
15539    struct dahdi_bufferinfo bi;
15540    struct dahdi_spaninfo si;
15541 
15542 
15543    link = ss7_resolve_linkset(cur_linkset);
15544    if (!link) {
15545       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15546       return -1;
15547    }
15548 
15549    if (cur_ss7type < 0) {
15550       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15551       return -1;
15552    }
15553 
15554    if (!link->ss7)
15555       link->ss7 = ss7_new(cur_ss7type);
15556 
15557    if (!link->ss7) {
15558       ast_log(LOG_ERROR, "Can't create new SS7!\n");
15559       return -1;
15560    }
15561 
15562    link->type = cur_ss7type;
15563 
15564    if (cur_pointcode < 0) {
15565       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15566       return -1;
15567    } else
15568       ss7_set_pc(link->ss7, cur_pointcode);
15569 
15570    if (sigchan < 0) {
15571       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15572       return -1;
15573    } else {
15574       if (link->numsigchans >= NUM_DCHANS) {
15575          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15576          return -1;
15577       }
15578       curfd = link->numsigchans;
15579 
15580       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15581       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15582          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15583          return -1;
15584       }
15585       memset(&p, 0, sizeof(p));
15586       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15587       if (res) {
15588          dahdi_close_ss7_fd(link, curfd);
15589          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15590          return -1;
15591       }
15592       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15593          dahdi_close_ss7_fd(link, curfd);
15594          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15595          return -1;
15596       }
15597 
15598       memset(&bi, 0, sizeof(bi));
15599       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15600       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15601       bi.numbufs = 32;
15602       bi.bufsize = 512;
15603 
15604       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15605          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15606          dahdi_close_ss7_fd(link, curfd);
15607          return -1;
15608       }
15609 
15610       if (p.sigtype == DAHDI_SIG_MTP2)
15611          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15612       else
15613          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15614 
15615       link->numsigchans++;
15616 
15617       memset(&si, 0, sizeof(si));
15618       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15619       if (res) {
15620          dahdi_close_ss7_fd(link, curfd);
15621          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15622       }
15623 
15624       if (!si.alarms) {
15625          link->linkstate[curfd] = LINKSTATE_DOWN;
15626          ss7_link_noalarm(link->ss7, link->fds[curfd]);
15627       } else {
15628          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15629          ss7_link_alarm(link->ss7, link->fds[curfd]);
15630       }
15631    }
15632 
15633    if (cur_adjpointcode < 0) {
15634       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15635       return -1;
15636    } else {
15637       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15638    }
15639 
15640    if (cur_defaultdpc < 0) {
15641       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15642       return -1;
15643    }
15644 
15645    if (cur_networkindicator < 0) {
15646       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15647       return -1;
15648    } else
15649       ss7_set_network_ind(link->ss7, cur_networkindicator);
15650 
15651    return 0;
15652 }
15653 #endif   /* defined(HAVE_SS7) */
15654 
15655 #if defined(HAVE_SS7)
15656 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15657 {
15658    int span;
15659    switch (cmd) {
15660    case CLI_INIT:
15661       e->command = "ss7 set debug {on|off} linkset";
15662       e->usage =
15663          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15664          "       Enables debugging on a given SS7 linkset\n";
15665       return NULL;
15666    case CLI_GENERATE:
15667       return NULL;
15668    }
15669    if (a->argc < 6)
15670       return CLI_SHOWUSAGE;
15671    span = atoi(a->argv[5]);
15672    if ((span < 1) || (span > NUM_SPANS)) {
15673       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15674       return CLI_SUCCESS;
15675    }
15676    if (!linksets[span-1].ss7) {
15677       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15678       return CLI_SUCCESS;
15679    }
15680    if (linksets[span-1].ss7) {
15681       if (!strcasecmp(a->argv[3], "on")) {
15682          ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15683          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15684       } else {
15685          ss7_set_debug(linksets[span-1].ss7, 0);
15686          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15687       }
15688    }
15689 
15690    return CLI_SUCCESS;
15691 }
15692 #endif   /* defined(HAVE_SS7) */
15693 
15694 #if defined(HAVE_SS7)
15695 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15696 {
15697    int linkset, cic;
15698    int blocked = -1, i;
15699    switch (cmd) {
15700    case CLI_INIT:
15701       e->command = "ss7 block cic";
15702       e->usage =
15703          "Usage: ss7 block cic <linkset> <CIC>\n"
15704          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15705       return NULL;
15706    case CLI_GENERATE:
15707       return NULL;
15708    }
15709    if (a->argc == 5)
15710       linkset = atoi(a->argv[3]);
15711    else
15712       return CLI_SHOWUSAGE;
15713 
15714    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15715       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15716       return CLI_SUCCESS;
15717    }
15718 
15719    if (!linksets[linkset-1].ss7) {
15720       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15721       return CLI_SUCCESS;
15722    }
15723 
15724    cic = atoi(a->argv[4]);
15725 
15726    if (cic < 1) {
15727       ast_cli(a->fd, "Invalid CIC specified!\n");
15728       return CLI_SUCCESS;
15729    }
15730 
15731    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15732       if (linksets[linkset-1].pvts[i]->cic == cic) {
15733          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15734          if (!blocked) {
15735             ast_mutex_lock(&linksets[linkset-1].lock);
15736             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15737             ast_mutex_unlock(&linksets[linkset-1].lock);
15738          }
15739       }
15740    }
15741 
15742    if (blocked < 0) {
15743       ast_cli(a->fd, "Invalid CIC specified!\n");
15744       return CLI_SUCCESS;
15745    }
15746 
15747    if (!blocked)
15748       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15749    else
15750       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15751 
15752    /* Break poll on the linkset so it sends our messages */
15753    pthread_kill(linksets[linkset-1].master, SIGURG);
15754 
15755    return CLI_SUCCESS;
15756 }
15757 #endif   /* defined(HAVE_SS7) */
15758 
15759 #if defined(HAVE_SS7)
15760 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15761 {
15762    int linkset;
15763    int i;
15764    switch (cmd) {
15765    case CLI_INIT:
15766       e->command = "ss7 block linkset";
15767       e->usage =
15768          "Usage: ss7 block linkset <linkset number>\n"
15769          "       Sends a remote blocking request for all CICs on the given linkset\n";
15770       return NULL;
15771    case CLI_GENERATE:
15772       return NULL;
15773    }
15774    if (a->argc == 4)
15775       linkset = atoi(a->argv[3]);
15776    else
15777       return CLI_SHOWUSAGE;
15778 
15779    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15780       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15781       return CLI_SUCCESS;
15782    }
15783 
15784    if (!linksets[linkset-1].ss7) {
15785       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15786       return CLI_SUCCESS;
15787    }
15788 
15789    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15790       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15791       ast_mutex_lock(&linksets[linkset-1].lock);
15792       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15793       ast_mutex_unlock(&linksets[linkset-1].lock);
15794    }
15795 
15796    /* Break poll on the linkset so it sends our messages */
15797    pthread_kill(linksets[linkset-1].master, SIGURG);
15798 
15799    return CLI_SUCCESS;
15800 }
15801 #endif   /* defined(HAVE_SS7) */
15802 
15803 #if defined(HAVE_SS7)
15804 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15805 {
15806    int linkset, cic;
15807    int i, blocked = -1;
15808    switch (cmd) {
15809    case CLI_INIT:
15810       e->command = "ss7 unblock cic";
15811       e->usage =
15812          "Usage: ss7 unblock cic <linkset> <CIC>\n"
15813          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15814       return NULL;
15815    case CLI_GENERATE:
15816       return NULL;
15817    }
15818 
15819    if (a->argc == 5)
15820       linkset = atoi(a->argv[3]);
15821    else
15822       return CLI_SHOWUSAGE;
15823 
15824    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15825       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15826       return CLI_SUCCESS;
15827    }
15828 
15829    if (!linksets[linkset-1].ss7) {
15830       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15831       return CLI_SUCCESS;
15832    }
15833 
15834    cic = atoi(a->argv[4]);
15835 
15836    if (cic < 1) {
15837       ast_cli(a->fd, "Invalid CIC specified!\n");
15838       return CLI_SUCCESS;
15839    }
15840 
15841    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15842       if (linksets[linkset-1].pvts[i]->cic == cic) {
15843          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15844          if (blocked) {
15845             ast_mutex_lock(&linksets[linkset-1].lock);
15846             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15847             ast_mutex_unlock(&linksets[linkset-1].lock);
15848          }
15849       }
15850    }
15851 
15852    if (blocked > 0)
15853       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15854 
15855    /* Break poll on the linkset so it sends our messages */
15856    pthread_kill(linksets[linkset-1].master, SIGURG);
15857 
15858    return CLI_SUCCESS;
15859 }
15860 #endif   /* defined(HAVE_SS7) */
15861 
15862 #if defined(HAVE_SS7)
15863 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15864 {
15865    int linkset;
15866    int i;
15867    switch (cmd) {
15868    case CLI_INIT:
15869       e->command = "ss7 unblock linkset";
15870       e->usage =
15871          "Usage: ss7 unblock linkset <linkset number>\n"
15872          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15873       return NULL;
15874    case CLI_GENERATE:
15875       return NULL;
15876    }
15877 
15878    if (a->argc == 4)
15879       linkset = atoi(a->argv[3]);
15880    else
15881       return CLI_SHOWUSAGE;
15882 
15883    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15884       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15885       return CLI_SUCCESS;
15886    }
15887 
15888    if (!linksets[linkset-1].ss7) {
15889       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15890       return CLI_SUCCESS;
15891    }
15892 
15893    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15894       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15895       ast_mutex_lock(&linksets[linkset-1].lock);
15896       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15897       ast_mutex_unlock(&linksets[linkset-1].lock);
15898    }
15899 
15900    /* Break poll on the linkset so it sends our messages */
15901    pthread_kill(linksets[linkset-1].master, SIGURG);
15902 
15903    return CLI_SUCCESS;
15904 }
15905 #endif   /* defined(HAVE_SS7) */
15906 
15907 #if defined(HAVE_SS7)
15908 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15909 {
15910    int linkset;
15911    struct dahdi_ss7 *ss7;
15912    switch (cmd) {
15913    case CLI_INIT:
15914       e->command = "ss7 show linkset";
15915       e->usage =
15916          "Usage: ss7 show linkset <span>\n"
15917          "       Shows the status of an SS7 linkset.\n";
15918       return NULL;
15919    case CLI_GENERATE:
15920       return NULL;
15921    }
15922 
15923    if (a->argc < 4)
15924       return CLI_SHOWUSAGE;
15925    linkset = atoi(a->argv[3]);
15926    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15927       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15928       return CLI_SUCCESS;
15929    }
15930    if (!linksets[linkset-1].ss7) {
15931       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15932       return CLI_SUCCESS;
15933    }
15934    if (linksets[linkset-1].ss7)
15935       ss7 = &linksets[linkset-1];
15936 
15937    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15938 
15939    return CLI_SUCCESS;
15940 }
15941 #endif   /* defined(HAVE_SS7) */
15942 
15943 #if defined(HAVE_SS7)
15944 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15945 {
15946    switch (cmd) {
15947    case CLI_INIT:
15948       e->command = "ss7 show version";
15949       e->usage =
15950          "Usage: ss7 show version\n"
15951          "  Show the libss7 version\n";
15952       return NULL;
15953    case CLI_GENERATE:
15954       return NULL;
15955    }
15956 
15957    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15958 
15959    return CLI_SUCCESS;
15960 }
15961 #endif   /* defined(HAVE_SS7) */
15962 
15963 #if defined(HAVE_SS7)
15964 static struct ast_cli_entry dahdi_ss7_cli[] = {
15965    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15966    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15967    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15968    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15969    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15970    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15971    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15972 };
15973 #endif   /* defined(HAVE_SS7) */
15974 
15975 static int __unload_module(void)
15976 {
15977    struct dahdi_pvt *p;
15978 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15979    int i, j;
15980 #endif
15981 
15982 #ifdef HAVE_PRI
15983    for (i = 0; i < NUM_SPANS; i++) {
15984       if (pris[i].master != AST_PTHREADT_NULL)
15985          pthread_cancel(pris[i].master);
15986    }
15987    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15988    ast_unregister_application(dahdi_send_keypad_facility_app);
15989 #ifdef HAVE_PRI_PROG_W_CAUSE
15990    ast_unregister_application(dahdi_send_callrerouting_facility_app);
15991 #endif
15992 #endif
15993 #if defined(HAVE_SS7)
15994    for (i = 0; i < NUM_SPANS; i++) {
15995       if (linksets[i].master != AST_PTHREADT_NULL)
15996          pthread_cancel(linksets[i].master);
15997       }
15998    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15999 #endif
16000 #if defined(HAVE_OPENR2)
16001    dahdi_r2_destroy_links();
16002    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16003    ast_unregister_application(dahdi_accept_r2_call_app);
16004 #endif
16005 
16006    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16007    ast_manager_unregister( "DAHDIDialOffhook" );
16008    ast_manager_unregister( "DAHDIHangup" );
16009    ast_manager_unregister( "DAHDITransfer" );
16010    ast_manager_unregister( "DAHDIDNDoff" );
16011    ast_manager_unregister( "DAHDIDNDon" );
16012    ast_manager_unregister("DAHDIShowChannels");
16013    ast_manager_unregister("DAHDIRestart");
16014    ast_channel_unregister(&dahdi_tech);
16015    ast_mutex_lock(&iflock);
16016    /* Hangup all interfaces if they have an owner */
16017    p = iflist;
16018    while (p) {
16019       if (p->owner)
16020          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16021       p = p->next;
16022    }
16023    ast_mutex_unlock(&iflock);
16024    ast_mutex_lock(&monlock);
16025    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16026       pthread_cancel(monitor_thread);
16027       pthread_kill(monitor_thread, SIGURG);
16028       pthread_join(monitor_thread, NULL);
16029    }
16030    monitor_thread = AST_PTHREADT_STOP;
16031    ast_mutex_unlock(&monlock);
16032 
16033    destroy_all_channels();
16034 
16035 #if defined(HAVE_PRI)
16036    for (i = 0; i < NUM_SPANS; i++) {
16037       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
16038          pthread_join(pris[i].master, NULL);
16039       for (j = 0; j < NUM_DCHANS; j++) {
16040          dahdi_close_pri_fd(&(pris[i]), j);
16041       }
16042    }
16043 #endif
16044 
16045 #if defined(HAVE_SS7)
16046    for (i = 0; i < NUM_SPANS; i++) {
16047       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
16048          pthread_join(linksets[i].master, NULL);
16049       for (j = 0; j < NUM_DCHANS; j++) {
16050          dahdi_close_ss7_fd(&(linksets[i]), j);
16051       }
16052    }
16053 #endif
16054    ast_cond_destroy(&ss_thread_complete);
16055    return 0;
16056 }
16057 
16058 static int unload_module(void)
16059 {
16060 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16061    int y;
16062 #endif
16063 #ifdef HAVE_PRI
16064    for (y = 0; y < NUM_SPANS; y++)
16065       ast_mutex_destroy(&pris[y].lock);
16066 #endif
16067 #ifdef HAVE_SS7
16068    for (y = 0; y < NUM_SPANS; y++)
16069       ast_mutex_destroy(&linksets[y].lock);
16070 #endif /* HAVE_SS7 */
16071    return __unload_module();
16072 }
16073 
16074 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
16075 {
16076    char *c, *chan;
16077    int x, start, finish;
16078    struct dahdi_pvt *tmp;
16079 #ifdef HAVE_PRI
16080    struct dahdi_pri *pri;
16081    int trunkgroup, y;
16082 #endif
16083 
16084    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16085       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16086       return -1;
16087    }
16088 
16089    c = ast_strdupa(value);
16090 
16091 #ifdef HAVE_PRI
16092    pri = NULL;
16093    if (iscrv) {
16094       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16095          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16096          return -1;
16097       }
16098       if (trunkgroup < 1) {
16099          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16100          return -1;
16101       }
16102       c += y;
16103       for (y = 0; y < NUM_SPANS; y++) {
16104          if (pris[y].trunkgroup == trunkgroup) {
16105             pri = pris + y;
16106             break;
16107          }
16108       }
16109       if (!pri) {
16110          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16111          return -1;
16112       }
16113    }
16114 #endif
16115 
16116    while ((chan = strsep(&c, ","))) {
16117       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16118          /* Range */
16119       } else if (sscanf(chan, "%30d", &start)) {
16120          /* Just one */
16121          finish = start;
16122       } else if (!strcasecmp(chan, "pseudo")) {
16123          finish = start = CHAN_PSEUDO;
16124          if (found_pseudo)
16125             *found_pseudo = 1;
16126       } else {
16127          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16128          return -1;
16129       }
16130       if (finish < start) {
16131          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16132          x = finish;
16133          finish = start;
16134          start = x;
16135       }
16136 
16137       for (x = start; x <= finish; x++) {
16138 #ifdef HAVE_PRI
16139          tmp = mkintf(x, conf, pri, reload);
16140 #else
16141          tmp = mkintf(x, conf, NULL, reload);
16142 #endif
16143 
16144          if (tmp) {
16145 #ifdef HAVE_PRI
16146             if (pri)
16147                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16148             else
16149 #endif
16150                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16151          } else {
16152             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16153                (reload == 1) ? "reconfigure" : "register", value);
16154             return -1;
16155          }
16156       }
16157    }
16158 
16159    return 0;
16160 }
16161 
16162 /** The length of the parameters list of 'dahdichan'.
16163  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16164 #define MAX_CHANLIST_LEN 80
16165 
16166 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16167 {
16168    char *parse = ast_strdupa(data);
16169    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16170    unsigned int param_count;
16171    unsigned int x;
16172 
16173    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16174       return;
16175 
16176    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16177 
16178    /* first parameter is tap length, process it here */
16179 
16180    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16181 
16182    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16183       confp->chan.echocancel.head.tap_length = x;
16184    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16185       confp->chan.echocancel.head.tap_length = 128;
16186 
16187    /* now process any remaining parameters */
16188 
16189    for (x = 1; x < param_count; x++) {
16190       struct {
16191          char *name;
16192          char *value;
16193       } param;
16194 
16195       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16196          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16197          continue;
16198       }
16199 
16200       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16201          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16202          continue;
16203       }
16204 
16205       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16206 
16207       if (param.value) {
16208          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16209             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16210             continue;
16211          }
16212       }
16213       confp->chan.echocancel.head.param_count++;
16214    }
16215 }
16216 
16217 /*! process_dahdi() - ignore keyword 'channel' and similar */
16218 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16219 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16220 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16221 
16222 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16223 {
16224    struct dahdi_pvt *tmp;
16225    int y;
16226    int found_pseudo = 0;
16227    char dahdichan[MAX_CHANLIST_LEN] = {};
16228 
16229    for (; v; v = v->next) {
16230       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16231          continue;
16232 
16233       /* must have parkinglot in confp before build_channels is called */
16234       if (!strcasecmp(v->name, "parkinglot")) {
16235          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16236       }
16237 
16238       /* Create the interface list */
16239       if (!strcasecmp(v->name, "channel")
16240 #ifdef HAVE_PRI
16241          || !strcasecmp(v->name, "crv")
16242 #endif
16243          ) {
16244          int iscrv;
16245          if (options & PROC_DAHDI_OPT_NOCHAN) {
16246             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16247             continue;
16248          }
16249          iscrv = !strcasecmp(v->name, "crv");
16250          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16251                return -1;
16252          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16253       } else if (!strcasecmp(v->name, "buffers")) {
16254          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16255             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16256             confp->chan.buf_no = numbufs;
16257             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16258          }
16259       } else if (!strcasecmp(v->name, "faxbuffers")) {
16260          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16261             confp->chan.usefaxbuffers = 1;
16262          }
16263       } else if (!strcasecmp(v->name, "dahdichan")) {
16264          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16265       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16266          usedistinctiveringdetection = ast_true(v->value);
16267       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16268          distinctiveringaftercid = ast_true(v->value);
16269       } else if (!strcasecmp(v->name, "dring1context")) {
16270          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16271       } else if (!strcasecmp(v->name, "dring2context")) {
16272          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16273       } else if (!strcasecmp(v->name, "dring3context")) {
16274          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16275       } else if (!strcasecmp(v->name, "dring1range")) {
16276          confp->chan.drings.ringnum[0].range = atoi(v->value);
16277       } else if (!strcasecmp(v->name, "dring2range")) {
16278          confp->chan.drings.ringnum[1].range = atoi(v->value);
16279       } else if (!strcasecmp(v->name, "dring3range")) {
16280          confp->chan.drings.ringnum[2].range = atoi(v->value);
16281       } else if (!strcasecmp(v->name, "dring1")) {
16282          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
16283       } else if (!strcasecmp(v->name, "dring2")) {
16284          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
16285       } else if (!strcasecmp(v->name, "dring3")) {
16286          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
16287       } else if (!strcasecmp(v->name, "usecallerid")) {
16288          confp->chan.use_callerid = ast_true(v->value);
16289       } else if (!strcasecmp(v->name, "cidsignalling")) {
16290          if (!strcasecmp(v->value, "bell"))
16291             confp->chan.cid_signalling = CID_SIG_BELL;
16292          else if (!strcasecmp(v->value, "v23"))
16293             confp->chan.cid_signalling = CID_SIG_V23;
16294          else if (!strcasecmp(v->value, "dtmf"))
16295             confp->chan.cid_signalling = CID_SIG_DTMF;
16296          else if (!strcasecmp(v->value, "smdi"))
16297             confp->chan.cid_signalling = CID_SIG_SMDI;
16298          else if (!strcasecmp(v->value, "v23_jp"))
16299             confp->chan.cid_signalling = CID_SIG_V23_JP;
16300          else if (ast_true(v->value))
16301             confp->chan.cid_signalling = CID_SIG_BELL;
16302       } else if (!strcasecmp(v->name, "cidstart")) {
16303          if (!strcasecmp(v->value, "ring"))
16304             confp->chan.cid_start = CID_START_RING;
16305          else if (!strcasecmp(v->value, "polarity_in"))
16306             confp->chan.cid_start = CID_START_POLARITY_IN;
16307          else if (!strcasecmp(v->value, "polarity"))
16308             confp->chan.cid_start = CID_START_POLARITY;
16309          else if (ast_true(v->value))
16310             confp->chan.cid_start = CID_START_RING;
16311       } else if (!strcasecmp(v->name, "threewaycalling")) {
16312          confp->chan.threewaycalling = ast_true(v->value);
16313       } else if (!strcasecmp(v->name, "cancallforward")) {
16314          confp->chan.cancallforward = ast_true(v->value);
16315       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16316          if (ast_true(v->value))
16317             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16318          else
16319             confp->chan.dtmfrelax = 0;
16320       } else if (!strcasecmp(v->name, "mailbox")) {
16321          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16322       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16323          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16324             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16325          }
16326       } else if (!strcasecmp(v->name, "adsi")) {
16327          confp->chan.adsi = ast_true(v->value);
16328       } else if (!strcasecmp(v->name, "usesmdi")) {
16329          confp->chan.use_smdi = ast_true(v->value);
16330       } else if (!strcasecmp(v->name, "smdiport")) {
16331          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16332       } else if (!strcasecmp(v->name, "transfer")) {
16333          confp->chan.transfer = ast_true(v->value);
16334       } else if (!strcasecmp(v->name, "canpark")) {
16335          confp->chan.canpark = ast_true(v->value);
16336       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16337          confp->chan.echocanbridged = ast_true(v->value);
16338       } else if (!strcasecmp(v->name, "busydetect")) {
16339          confp->chan.busydetect = ast_true(v->value);
16340       } else if (!strcasecmp(v->name, "busycount")) {
16341          confp->chan.busycount = atoi(v->value);
16342       } else if (!strcasecmp(v->name, "busypattern")) {
16343          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16344             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16345          }
16346       } else if (!strcasecmp(v->name, "callprogress")) {
16347          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16348          if (ast_true(v->value))
16349             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16350       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16351          confp->chan.waitfordialtone = atoi(v->value);
16352       } else if (!strcasecmp(v->name, "faxdetect")) {
16353          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16354          if (!strcasecmp(v->value, "incoming")) {
16355             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16356          } else if (!strcasecmp(v->value, "outgoing")) {
16357             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16358          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16359             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16360       } else if (!strcasecmp(v->name, "echocancel")) {
16361          process_echocancel(confp, v->value, v->lineno);
16362       } else if (!strcasecmp(v->name, "echotraining")) {
16363          if (sscanf(v->value, "%30d", &y) == 1) {
16364             if ((y < 10) || (y > 4000)) {
16365                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16366             } else {
16367                confp->chan.echotraining = y;
16368             }
16369          } else if (ast_true(v->value)) {
16370             confp->chan.echotraining = 400;
16371          } else
16372             confp->chan.echotraining = 0;
16373       } else if (!strcasecmp(v->name, "hidecallerid")) {
16374          confp->chan.hidecallerid = ast_true(v->value);
16375       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16376          confp->chan.hidecalleridname = ast_true(v->value);
16377       } else if (!strcasecmp(v->name, "pulsedial")) {
16378          confp->chan.pulse = ast_true(v->value);
16379       } else if (!strcasecmp(v->name, "callreturn")) {
16380          confp->chan.callreturn = ast_true(v->value);
16381       } else if (!strcasecmp(v->name, "callwaiting")) {
16382          confp->chan.callwaiting = ast_true(v->value);
16383       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16384          confp->chan.callwaitingcallerid = ast_true(v->value);
16385       } else if (!strcasecmp(v->name, "context")) {
16386          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16387       } else if (!strcasecmp(v->name, "language")) {
16388          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16389       } else if (!strcasecmp(v->name, "progzone")) {
16390          ast_copy_string(progzone, v->value, sizeof(progzone));
16391       } else if (!strcasecmp(v->name, "mohinterpret")
16392          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16393          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16394       } else if (!strcasecmp(v->name, "mohsuggest")) {
16395          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16396       } else if (!strcasecmp(v->name, "parkinglot")) {
16397          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16398       } else if (!strcasecmp(v->name, "stripmsd")) {
16399          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16400          confp->chan.stripmsd = atoi(v->value);
16401       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16402          numbufs = atoi(v->value);
16403       } else if (!strcasecmp(v->name, "group")) {
16404          confp->chan.group = ast_get_group(v->value);
16405       } else if (!strcasecmp(v->name, "callgroup")) {
16406          if (!strcasecmp(v->value, "none"))
16407             confp->chan.callgroup = 0;
16408          else
16409             confp->chan.callgroup = ast_get_group(v->value);
16410       } else if (!strcasecmp(v->name, "pickupgroup")) {
16411          if (!strcasecmp(v->value, "none"))
16412             confp->chan.pickupgroup = 0;
16413          else
16414             confp->chan.pickupgroup = ast_get_group(v->value);
16415       } else if (!strcasecmp(v->name, "setvar")) {
16416          char *varname = ast_strdupa(v->value), *varval = NULL;
16417          struct ast_variable *tmpvar;
16418          if (varname && (varval = strchr(varname, '='))) {
16419             *varval++ = '\0';
16420             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16421                tmpvar->next = confp->chan.vars;
16422                confp->chan.vars = tmpvar;
16423             }
16424          }
16425       } else if (!strcasecmp(v->name, "immediate")) {
16426          confp->chan.immediate = ast_true(v->value);
16427       } else if (!strcasecmp(v->name, "transfertobusy")) {
16428          confp->chan.transfertobusy = ast_true(v->value);
16429       } else if (!strcasecmp(v->name, "mwimonitor")) {
16430          confp->chan.mwimonitor_neon = 0;
16431          confp->chan.mwimonitor_fsk = 0;
16432          confp->chan.mwimonitor_rpas = 0;
16433          if (strcasestr(v->value, "fsk")) {
16434             confp->chan.mwimonitor_fsk = 1;
16435          }
16436          if (strcasestr(v->value, "rpas")) {
16437             confp->chan.mwimonitor_rpas = 1;
16438          }
16439          if (strcasestr(v->value, "neon")) {
16440             confp->chan.mwimonitor_neon = 1;
16441          }
16442          /* If set to true or yes, assume that simple fsk is desired */
16443          if (ast_true(v->value)) {
16444             confp->chan.mwimonitor_fsk = 1;
16445          }
16446       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16447          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16448             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16449          }
16450       } else if (!strcasecmp(v->name, "rxgain")) {
16451          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16452             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16453          }
16454       } else if (!strcasecmp(v->name, "txgain")) {
16455          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16456             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16457          }
16458       } else if (!strcasecmp(v->name, "tonezone")) {
16459          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16460             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16461          }
16462       } else if (!strcasecmp(v->name, "callerid")) {
16463          if (!strcasecmp(v->value, "asreceived")) {
16464             confp->chan.cid_num[0] = '\0';
16465             confp->chan.cid_name[0] = '\0';
16466          } else {
16467             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16468          }
16469       } else if (!strcasecmp(v->name, "fullname")) {
16470          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16471       } else if (!strcasecmp(v->name, "cid_number")) {
16472          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16473       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16474          confp->chan.dahditrcallerid = ast_true(v->value);
16475       } else if (!strcasecmp(v->name, "restrictcid")) {
16476          confp->chan.restrictcid = ast_true(v->value);
16477       } else if (!strcasecmp(v->name, "usecallingpres")) {
16478          confp->chan.use_callingpres = ast_true(v->value);
16479       } else if (!strcasecmp(v->name, "accountcode")) {
16480          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16481       } else if (!strcasecmp(v->name, "amaflags")) {
16482          y = ast_cdr_amaflags2int(v->value);
16483          if (y < 0)
16484             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16485          else
16486             confp->chan.amaflags = y;
16487       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16488          confp->chan.polarityonanswerdelay = atoi(v->value);
16489       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16490          confp->chan.answeronpolarityswitch = ast_true(v->value);
16491       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16492          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16493       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16494          confp->chan.sendcalleridafter = atoi(v->value);
16495       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16496          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16497       } else if (!strcasecmp(v->name, "mwisendtype")) {
16498 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16499          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16500             mwisend_rpas = 1;
16501          } else {
16502             mwisend_rpas = 0;
16503          }
16504 #else
16505          /* Default is fsk, to turn it off you must specify nofsk */
16506          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16507          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16508             confp->chan.mwisend_fsk = 0;
16509          } else {             /* Default FSK */
16510             confp->chan.mwisend_fsk = 1;
16511          }
16512          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16513             confp->chan.mwisend_rpas = 1;
16514          } else {
16515             confp->chan.mwisend_rpas = 0;
16516          }
16517          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16518             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16519          }
16520          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16521             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16522          }
16523          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16524             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16525          }
16526 #endif
16527       } else if (reload != 1) {
16528           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16529             int orig_radio = confp->chan.radio;
16530             int orig_outsigmod = confp->chan.outsigmod;
16531             int orig_auto = confp->is_sig_auto;
16532 
16533             confp->chan.radio = 0;
16534             confp->chan.outsigmod = -1;
16535             confp->is_sig_auto = 0;
16536             if (!strcasecmp(v->value, "em")) {
16537                confp->chan.sig = SIG_EM;
16538             } else if (!strcasecmp(v->value, "em_e1")) {
16539                confp->chan.sig = SIG_EM_E1;
16540             } else if (!strcasecmp(v->value, "em_w")) {
16541                confp->chan.sig = SIG_EMWINK;
16542             } else if (!strcasecmp(v->value, "fxs_ls")) {
16543                confp->chan.sig = SIG_FXSLS;
16544             } else if (!strcasecmp(v->value, "fxs_gs")) {
16545                confp->chan.sig = SIG_FXSGS;
16546             } else if (!strcasecmp(v->value, "fxs_ks")) {
16547                confp->chan.sig = SIG_FXSKS;
16548             } else if (!strcasecmp(v->value, "fxo_ls")) {
16549                confp->chan.sig = SIG_FXOLS;
16550             } else if (!strcasecmp(v->value, "fxo_gs")) {
16551                confp->chan.sig = SIG_FXOGS;
16552             } else if (!strcasecmp(v->value, "fxo_ks")) {
16553                confp->chan.sig = SIG_FXOKS;
16554             } else if (!strcasecmp(v->value, "fxs_rx")) {
16555                confp->chan.sig = SIG_FXSKS;
16556                confp->chan.radio = 1;
16557             } else if (!strcasecmp(v->value, "fxo_rx")) {
16558                confp->chan.sig = SIG_FXOLS;
16559                confp->chan.radio = 1;
16560             } else if (!strcasecmp(v->value, "fxs_tx")) {
16561                confp->chan.sig = SIG_FXSLS;
16562                confp->chan.radio = 1;
16563             } else if (!strcasecmp(v->value, "fxo_tx")) {
16564                confp->chan.sig = SIG_FXOGS;
16565                confp->chan.radio = 1;
16566             } else if (!strcasecmp(v->value, "em_rx")) {
16567                confp->chan.sig = SIG_EM;
16568                confp->chan.radio = 1;
16569             } else if (!strcasecmp(v->value, "em_tx")) {
16570                confp->chan.sig = SIG_EM;
16571                confp->chan.radio = 1;
16572             } else if (!strcasecmp(v->value, "em_rxtx")) {
16573                confp->chan.sig = SIG_EM;
16574                confp->chan.radio = 2;
16575             } else if (!strcasecmp(v->value, "em_txrx")) {
16576                confp->chan.sig = SIG_EM;
16577                confp->chan.radio = 2;
16578             } else if (!strcasecmp(v->value, "sf")) {
16579                confp->chan.sig = SIG_SF;
16580             } else if (!strcasecmp(v->value, "sf_w")) {
16581                confp->chan.sig = SIG_SFWINK;
16582             } else if (!strcasecmp(v->value, "sf_featd")) {
16583                confp->chan.sig = SIG_FEATD;
16584             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16585                confp->chan.sig = SIG_FEATDMF;
16586             } else if (!strcasecmp(v->value, "sf_featb")) {
16587                confp->chan.sig = SIG_SF_FEATB;
16588             } else if (!strcasecmp(v->value, "sf")) {
16589                confp->chan.sig = SIG_SF;
16590             } else if (!strcasecmp(v->value, "sf_rx")) {
16591                confp->chan.sig = SIG_SF;
16592                confp->chan.radio = 1;
16593             } else if (!strcasecmp(v->value, "sf_tx")) {
16594                confp->chan.sig = SIG_SF;
16595                confp->chan.radio = 1;
16596             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16597                confp->chan.sig = SIG_SF;
16598                confp->chan.radio = 2;
16599             } else if (!strcasecmp(v->value, "sf_txrx")) {
16600                confp->chan.sig = SIG_SF;
16601                confp->chan.radio = 2;
16602             } else if (!strcasecmp(v->value, "featd")) {
16603                confp->chan.sig = SIG_FEATD;
16604             } else if (!strcasecmp(v->value, "featdmf")) {
16605                confp->chan.sig = SIG_FEATDMF;
16606             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16607                confp->chan.sig = SIG_FEATDMF_TA;
16608             } else if (!strcasecmp(v->value, "e911")) {
16609                confp->chan.sig = SIG_E911;
16610             } else if (!strcasecmp(v->value, "fgccama")) {
16611                confp->chan.sig = SIG_FGC_CAMA;
16612             } else if (!strcasecmp(v->value, "fgccamamf")) {
16613                confp->chan.sig = SIG_FGC_CAMAMF;
16614             } else if (!strcasecmp(v->value, "featb")) {
16615                confp->chan.sig = SIG_FEATB;
16616 #ifdef HAVE_PRI
16617             } else if (!strcasecmp(v->value, "pri_net")) {
16618                confp->chan.sig = SIG_PRI;
16619                confp->pri.nodetype = PRI_NETWORK;
16620             } else if (!strcasecmp(v->value, "pri_cpe")) {
16621                confp->chan.sig = SIG_PRI;
16622                confp->pri.nodetype = PRI_CPE;
16623             } else if (!strcasecmp(v->value, "bri_cpe")) {
16624                confp->chan.sig = SIG_BRI;
16625                confp->pri.nodetype = PRI_CPE;
16626             } else if (!strcasecmp(v->value, "bri_net")) {
16627                confp->chan.sig = SIG_BRI;
16628                confp->pri.nodetype = PRI_NETWORK;
16629             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16630                confp->chan.sig = SIG_BRI_PTMP;
16631                confp->pri.nodetype = PRI_CPE;
16632             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16633                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16634             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16635                confp->chan.sig = SIG_GR303FXOKS;
16636                confp->pri.nodetype = PRI_NETWORK;
16637             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16638                confp->chan.sig = SIG_GR303FXSKS;
16639                confp->pri.nodetype = PRI_CPE;
16640 #endif
16641 #ifdef HAVE_SS7
16642             } else if (!strcasecmp(v->value, "ss7")) {
16643                confp->chan.sig = SIG_SS7;
16644 #endif
16645 #ifdef HAVE_OPENR2
16646             } else if (!strcasecmp(v->value, "mfcr2")) {
16647                confp->chan.sig = SIG_MFCR2;
16648 #endif
16649             } else if (!strcasecmp(v->value, "auto")) {
16650                confp->is_sig_auto = 1;
16651             } else {
16652                confp->chan.outsigmod = orig_outsigmod;
16653                confp->chan.radio = orig_radio;
16654                confp->is_sig_auto = orig_auto;
16655                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16656             }
16657           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16658             if (!strcasecmp(v->value, "em")) {
16659                confp->chan.outsigmod = SIG_EM;
16660             } else if (!strcasecmp(v->value, "em_e1")) {
16661                confp->chan.outsigmod = SIG_EM_E1;
16662             } else if (!strcasecmp(v->value, "em_w")) {
16663                confp->chan.outsigmod = SIG_EMWINK;
16664             } else if (!strcasecmp(v->value, "sf")) {
16665                confp->chan.outsigmod = SIG_SF;
16666             } else if (!strcasecmp(v->value, "sf_w")) {
16667                confp->chan.outsigmod = SIG_SFWINK;
16668             } else if (!strcasecmp(v->value, "sf_featd")) {
16669                confp->chan.outsigmod = SIG_FEATD;
16670             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16671                confp->chan.outsigmod = SIG_FEATDMF;
16672             } else if (!strcasecmp(v->value, "sf_featb")) {
16673                confp->chan.outsigmod = SIG_SF_FEATB;
16674             } else if (!strcasecmp(v->value, "sf")) {
16675                confp->chan.outsigmod = SIG_SF;
16676             } else if (!strcasecmp(v->value, "featd")) {
16677                confp->chan.outsigmod = SIG_FEATD;
16678             } else if (!strcasecmp(v->value, "featdmf")) {
16679                confp->chan.outsigmod = SIG_FEATDMF;
16680             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16681                confp->chan.outsigmod = SIG_FEATDMF_TA;
16682             } else if (!strcasecmp(v->value, "e911")) {
16683                confp->chan.outsigmod = SIG_E911;
16684             } else if (!strcasecmp(v->value, "fgccama")) {
16685                confp->chan.outsigmod = SIG_FGC_CAMA;
16686             } else if (!strcasecmp(v->value, "fgccamamf")) {
16687                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16688             } else if (!strcasecmp(v->value, "featb")) {
16689                confp->chan.outsigmod = SIG_FEATB;
16690             } else {
16691                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16692             }
16693 #ifdef HAVE_PRI
16694          } else if (!strcasecmp(v->name, "pridialplan")) {
16695             if (!strcasecmp(v->value, "national")) {
16696                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16697             } else if (!strcasecmp(v->value, "unknown")) {
16698                confp->pri.dialplan = PRI_UNKNOWN + 1;
16699             } else if (!strcasecmp(v->value, "private")) {
16700                confp->pri.dialplan = PRI_PRIVATE + 1;
16701             } else if (!strcasecmp(v->value, "international")) {
16702                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16703             } else if (!strcasecmp(v->value, "local")) {
16704                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16705             } else if (!strcasecmp(v->value, "dynamic")) {
16706                confp->pri.dialplan = -1;
16707             } else if (!strcasecmp(v->value, "redundant")) {
16708                confp->pri.dialplan = -2;
16709             } else {
16710                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16711             }
16712          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16713             if (!strcasecmp(v->value, "national")) {
16714                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16715             } else if (!strcasecmp(v->value, "unknown")) {
16716                confp->pri.localdialplan = PRI_UNKNOWN + 1;
16717             } else if (!strcasecmp(v->value, "private")) {
16718                confp->pri.localdialplan = PRI_PRIVATE + 1;
16719             } else if (!strcasecmp(v->value, "international")) {
16720                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16721             } else if (!strcasecmp(v->value, "local")) {
16722                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16723             } else if (!strcasecmp(v->value, "dynamic")) {
16724                confp->pri.localdialplan = -1;
16725             } else if (!strcasecmp(v->value, "redundant")) {
16726                confp->pri.localdialplan = -2;
16727             } else {
16728                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16729             }
16730          } else if (!strcasecmp(v->name, "switchtype")) {
16731             if (!strcasecmp(v->value, "national"))
16732                confp->pri.switchtype = PRI_SWITCH_NI2;
16733             else if (!strcasecmp(v->value, "ni1"))
16734                confp->pri.switchtype = PRI_SWITCH_NI1;
16735             else if (!strcasecmp(v->value, "dms100"))
16736                confp->pri.switchtype = PRI_SWITCH_DMS100;
16737             else if (!strcasecmp(v->value, "4ess"))
16738                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16739             else if (!strcasecmp(v->value, "5ess"))
16740                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16741             else if (!strcasecmp(v->value, "euroisdn"))
16742                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16743             else if (!strcasecmp(v->value, "qsig"))
16744                confp->pri.switchtype = PRI_SWITCH_QSIG;
16745             else {
16746                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16747                return -1;
16748             }
16749          } else if (!strcasecmp(v->name, "nsf")) {
16750             if (!strcasecmp(v->value, "sdn"))
16751                confp->pri.nsf = PRI_NSF_SDN;
16752             else if (!strcasecmp(v->value, "megacom"))
16753                confp->pri.nsf = PRI_NSF_MEGACOM;
16754             else if (!strcasecmp(v->value, "tollfreemegacom"))
16755                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16756             else if (!strcasecmp(v->value, "accunet"))
16757                confp->pri.nsf = PRI_NSF_ACCUNET;
16758             else if (!strcasecmp(v->value, "none"))
16759                confp->pri.nsf = PRI_NSF_NONE;
16760             else {
16761                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16762                confp->pri.nsf = PRI_NSF_NONE;
16763             }
16764          } else if (!strcasecmp(v->name, "priindication")) {
16765             if (!strcasecmp(v->value, "outofband"))
16766                confp->chan.priindication_oob = 1;
16767             else if (!strcasecmp(v->value, "inband"))
16768                confp->chan.priindication_oob = 0;
16769             else
16770                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16771                   v->value, v->lineno);
16772          } else if (!strcasecmp(v->name, "priexclusive")) {
16773             confp->chan.priexclusive = ast_true(v->value);
16774          } else if (!strcasecmp(v->name, "internationalprefix")) {
16775             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16776          } else if (!strcasecmp(v->name, "nationalprefix")) {
16777             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16778          } else if (!strcasecmp(v->name, "localprefix")) {
16779             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16780          } else if (!strcasecmp(v->name, "privateprefix")) {
16781             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16782          } else if (!strcasecmp(v->name, "unknownprefix")) {
16783             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16784          } else if (!strcasecmp(v->name, "resetinterval")) {
16785             if (!strcasecmp(v->value, "never"))
16786                confp->pri.resetinterval = -1;
16787             else if (atoi(v->value) >= 60)
16788                confp->pri.resetinterval = atoi(v->value);
16789             else
16790                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16791                   v->value, v->lineno);
16792          } else if (!strcasecmp(v->name, "minunused")) {
16793             confp->pri.minunused = atoi(v->value);
16794          } else if (!strcasecmp(v->name, "minidle")) {
16795             confp->pri.minidle = atoi(v->value);
16796          } else if (!strcasecmp(v->name, "idleext")) {
16797             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16798          } else if (!strcasecmp(v->name, "idledial")) {
16799             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16800          } else if (!strcasecmp(v->name, "overlapdial")) {
16801             if (ast_true(v->value)) {
16802                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16803             } else if (!strcasecmp(v->value, "incoming")) {
16804                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16805             } else if (!strcasecmp(v->value, "outgoing")) {
16806                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16807             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16808                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16809             } else {
16810                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16811             }
16812 #ifdef HAVE_PRI_PROG_W_CAUSE
16813          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16814             if (!strcasecmp(v->value, "logical")) {
16815                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16816             } else if (!strcasecmp(v->value, "physical")) {
16817                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16818             } else {
16819                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16820             }
16821 #endif
16822          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16823             confp->pri.discardremoteholdretrieval = ast_true(v->value);
16824 #ifdef HAVE_PRI_INBANDDISCONNECT
16825          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16826             confp->pri.inbanddisconnect = ast_true(v->value);
16827 #endif
16828          } else if (!strcasecmp(v->name, "pritimer")) {
16829 #ifdef PRI_GETSET_TIMERS
16830             char tmp[20];
16831             char *timerc;
16832             char *c;
16833             int timer;
16834             int timeridx;
16835 
16836             ast_copy_string(tmp, v->value, sizeof(tmp));
16837             c = tmp;
16838             timerc = strsep(&c, ",");
16839             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16840                timeridx = pri_timer2idx(timerc);
16841                timer = atoi(c);
16842                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16843                   ast_log(LOG_WARNING,
16844                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16845                      v->lineno);
16846                } else if (!timer) {
16847                   ast_log(LOG_WARNING,
16848                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16849                      c, timerc, v->lineno);
16850                } else {
16851                   pritimers[timeridx] = timer;
16852                }
16853             } else {
16854                ast_log(LOG_WARNING,
16855                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16856                   v->value, v->lineno);
16857             }
16858 
16859          } else if (!strcasecmp(v->name, "facilityenable")) {
16860             confp->pri.facilityenable = ast_true(v->value);
16861 #endif /* PRI_GETSET_TIMERS */
16862 #endif /* HAVE_PRI */
16863 #ifdef HAVE_SS7
16864          } else if (!strcasecmp(v->name, "ss7type")) {
16865             if (!strcasecmp(v->value, "itu")) {
16866                cur_ss7type = SS7_ITU;
16867             } else if (!strcasecmp(v->value, "ansi")) {
16868                cur_ss7type = SS7_ANSI;
16869             } else
16870                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16871          } else if (!strcasecmp(v->name, "linkset")) {
16872             cur_linkset = atoi(v->value);
16873          } else if (!strcasecmp(v->name, "pointcode")) {
16874             cur_pointcode = parse_pointcode(v->value);
16875          } else if (!strcasecmp(v->name, "adjpointcode")) {
16876             cur_adjpointcode = parse_pointcode(v->value);
16877          } else if (!strcasecmp(v->name, "defaultdpc")) {
16878             cur_defaultdpc = parse_pointcode(v->value);
16879          } else if (!strcasecmp(v->name, "cicbeginswith")) {
16880             cur_cicbeginswith = atoi(v->value);
16881          } else if (!strcasecmp(v->name, "networkindicator")) {
16882             if (!strcasecmp(v->value, "national"))
16883                cur_networkindicator = SS7_NI_NAT;
16884             else if (!strcasecmp(v->value, "national_spare"))
16885                cur_networkindicator = SS7_NI_NAT_SPARE;
16886             else if (!strcasecmp(v->value, "international"))
16887                cur_networkindicator = SS7_NI_INT;
16888             else if (!strcasecmp(v->value, "international_spare"))
16889                cur_networkindicator = SS7_NI_INT_SPARE;
16890             else
16891                cur_networkindicator = -1;
16892          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16893             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16894          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16895             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16896          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16897             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16898          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16899             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16900          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16901             if (!strcasecmp(v->value, "national")) {
16902                confp->ss7.called_nai = SS7_NAI_NATIONAL;
16903             } else if (!strcasecmp(v->value, "international")) {
16904                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16905             } else if (!strcasecmp(v->value, "subscriber")) {
16906                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16907             } else if (!strcasecmp(v->value, "unknown")) {
16908                confp->ss7.called_nai = SS7_NAI_UNKNOWN;
16909             } else if (!strcasecmp(v->value, "dynamic")) {
16910                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16911             } else {
16912                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16913             }
16914          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16915             if (!strcasecmp(v->value, "national")) {
16916                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16917             } else if (!strcasecmp(v->value, "international")) {
16918                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16919             } else if (!strcasecmp(v->value, "subscriber")) {
16920                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16921             } else if (!strcasecmp(v->value, "unknown")) {
16922                confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
16923             } else if (!strcasecmp(v->value, "dynamic")) {
16924                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16925             } else {
16926                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16927             }
16928          } else if (!strcasecmp(v->name, "sigchan")) {
16929             int sigchan, res;
16930             sigchan = atoi(v->value);
16931             res = linkset_addsigchan(sigchan);
16932             if (res < 0)
16933                return -1;
16934 
16935          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16936             struct dahdi_ss7 *link;
16937             link = ss7_resolve_linkset(cur_linkset);
16938             if (!link) {
16939                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16940                return -1;
16941             }
16942             if (ast_true(v->value))
16943                link->flags |= LINKSET_FLAG_EXPLICITACM;
16944 #endif /* HAVE_SS7 */
16945 #ifdef HAVE_OPENR2
16946          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16947             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16948             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
16949          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16950             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16951          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16952             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16953             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16954                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16955                confp->mfcr2.variant = OR2_VAR_ITU;
16956             }
16957          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16958             confp->mfcr2.mfback_timeout = atoi(v->value);
16959             if (!confp->mfcr2.mfback_timeout) {
16960                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16961                confp->mfcr2.mfback_timeout = -1;
16962             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16963                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16964             }
16965          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16966             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16967             if (confp->mfcr2.metering_pulse_timeout > 500) {
16968                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16969             }
16970          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16971             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16972          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16973             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16974          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16975             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16976          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16977             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16978          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16979             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16980          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16981             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16982          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16983             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16984 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16985          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
16986             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
16987 #endif
16988          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16989             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16990          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16991             confp->mfcr2.max_ani = atoi(v->value);
16992             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16993                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16994             }
16995          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16996             confp->mfcr2.max_dnis = atoi(v->value);
16997             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16998                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16999             }
17000          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17001             confp->mfcr2.category = openr2_proto_get_category(v->value);
17002             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17003                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17004                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17005                      v->value, v->lineno);
17006             }
17007          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17008             openr2_log_level_t tmplevel;
17009             char *clevel;
17010             char *logval = ast_strdupa(v->value);
17011             while (logval) {
17012                clevel = strsep(&logval,",");
17013                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17014                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17015                   continue;
17016                }
17017                confp->mfcr2.loglevel |= tmplevel;
17018             }
17019 #endif /* HAVE_OPENR2 */
17020          } else if (!strcasecmp(v->name, "cadence")) {
17021             /* setup to scan our argument */
17022             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17023             int i;
17024             struct dahdi_ring_cadence new_cadence;
17025             int cid_location = -1;
17026             int firstcadencepos = 0;
17027             char original_args[80];
17028             int cadence_is_ok = 1;
17029 
17030             ast_copy_string(original_args, v->value, sizeof(original_args));
17031             /* 16 cadences allowed (8 pairs) */
17032             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
17033 
17034             /* Cadence must be even (on/off) */
17035             if (element_count % 2 == 1) {
17036                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17037                cadence_is_ok = 0;
17038             }
17039 
17040             /* Ring cadences cannot be negative */
17041             for (i = 0; i < element_count; i++) {
17042                if (c[i] == 0) {
17043                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17044                   cadence_is_ok = 0;
17045                   break;
17046                } else if (c[i] < 0) {
17047                   if (i % 2 == 1) {
17048                      /* Silence duration, negative possibly okay */
17049                      if (cid_location == -1) {
17050                         cid_location = i;
17051                         c[i] *= -1;
17052                      } else {
17053                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17054                         cadence_is_ok = 0;
17055                         break;
17056                      }
17057                   } else {
17058                      if (firstcadencepos == 0) {
17059                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17060                                  /* duration will be passed negative to the DAHDI driver */
17061                      } else {
17062                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17063                         cadence_is_ok = 0;
17064                         break;
17065                      }
17066                   }
17067                }
17068             }
17069 
17070             /* Substitute our scanned cadence */
17071             for (i = 0; i < 16; i++) {
17072                new_cadence.ringcadence[i] = c[i];
17073             }
17074 
17075             if (cadence_is_ok) {
17076                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17077                if (element_count < 2) {
17078                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17079                } else {
17080                   if (cid_location == -1) {
17081                      /* user didn't say; default to first pause */
17082                      cid_location = 1;
17083                   } else {
17084                      /* convert element_index to cidrings value */
17085                      cid_location = (cid_location + 1) / 2;
17086                   }
17087                   /* ---we like their cadence; try to install it--- */
17088                   if (!user_has_defined_cadences++)
17089                      /* this is the first user-defined cadence; clear the default user cadences */
17090                      num_cadence = 0;
17091                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17092                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17093                   else {
17094                      cadences[num_cadence] = new_cadence;
17095                      cidrings[num_cadence++] = cid_location;
17096                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17097                   }
17098                }
17099             }
17100          } else if (!strcasecmp(v->name, "ringtimeout")) {
17101             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17102          } else if (!strcasecmp(v->name, "prewink")) {
17103             confp->timing.prewinktime = atoi(v->value);
17104          } else if (!strcasecmp(v->name, "preflash")) {
17105             confp->timing.preflashtime = atoi(v->value);
17106          } else if (!strcasecmp(v->name, "wink")) {
17107             confp->timing.winktime = atoi(v->value);
17108          } else if (!strcasecmp(v->name, "flash")) {
17109             confp->timing.flashtime = atoi(v->value);
17110          } else if (!strcasecmp(v->name, "start")) {
17111             confp->timing.starttime = atoi(v->value);
17112          } else if (!strcasecmp(v->name, "rxwink")) {
17113             confp->timing.rxwinktime = atoi(v->value);
17114          } else if (!strcasecmp(v->name, "rxflash")) {
17115             confp->timing.rxflashtime = atoi(v->value);
17116          } else if (!strcasecmp(v->name, "debounce")) {
17117             confp->timing.debouncetime = atoi(v->value);
17118          } else if (!strcasecmp(v->name, "toneduration")) {
17119             int toneduration;
17120             int ctlfd;
17121             int res;
17122             struct dahdi_dialparams dps;
17123 
17124             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17125             if (ctlfd == -1) {
17126                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17127                return -1;
17128             }
17129 
17130             toneduration = atoi(v->value);
17131             if (toneduration > -1) {
17132                memset(&dps, 0, sizeof(dps));
17133 
17134                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17135                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17136                if (res < 0) {
17137                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17138                   close(ctlfd);
17139                   return -1;
17140                }
17141             }
17142             close(ctlfd);
17143          } else if (!strcasecmp(v->name, "defaultcic")) {
17144             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17145          } else if (!strcasecmp(v->name, "defaultozz")) {
17146             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17147          } else if (!strcasecmp(v->name, "mwilevel")) {
17148             mwilevel = atoi(v->value);
17149          }
17150       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17151          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17152    }
17153    if (dahdichan[0]) {
17154       /* The user has set 'dahdichan' */
17155       /*< \todo pass proper line number instead of 0 */
17156       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17157          return -1;
17158       }
17159    }
17160    /*< \todo why check for the pseudo in the per-channel section.
17161     * Any actual use for manual setup of the pseudo channel? */
17162    if (!found_pseudo && reload != 1) {
17163       /* use the default configuration for a channel, so
17164          that any settings from real configured channels
17165          don't "leak" into the pseudo channel config
17166       */
17167       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17168 
17169       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17170 
17171       if (tmp) {
17172          ast_verb(3, "Automatically generated pseudo channel\n");
17173       } else {
17174          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17175       }
17176    }
17177    return 0;
17178 }
17179 
17180 static int setup_dahdi(int reload)
17181 {
17182    struct ast_config *cfg, *ucfg;
17183    struct ast_variable *v;
17184    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17185    struct dahdi_chan_conf conf;
17186    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17187    const char *cat;
17188    int res;
17189 
17190 #ifdef HAVE_PRI
17191    char *c;
17192    int spanno;
17193    int i;
17194    int logicalspan;
17195    int trunkgroup;
17196    int dchannels[NUM_DCHANS];
17197 #endif
17198 
17199    cfg = ast_config_load(config, config_flags);
17200 
17201    /* Error if we have no config file */
17202    if (!cfg) {
17203       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17204       return 0;
17205    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17206       ucfg = ast_config_load("users.conf", config_flags);
17207       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17208          return 0;
17209       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17210          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17211          return 0;
17212       }
17213       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17214       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17215          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17216          ast_config_destroy(ucfg);
17217          return 0;
17218       }
17219    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17220       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17221       return 0;
17222    } else {
17223       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17224       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17225          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17226          ast_config_destroy(cfg);
17227          return 0;
17228       }
17229    }
17230 
17231    /* It's a little silly to lock it, but we mind as well just to be sure */
17232    ast_mutex_lock(&iflock);
17233 #ifdef HAVE_PRI
17234    if (reload != 1) {
17235       /* Process trunkgroups first */
17236       v = ast_variable_browse(cfg, "trunkgroups");
17237       while (v) {
17238          if (!strcasecmp(v->name, "trunkgroup")) {
17239             trunkgroup = atoi(v->value);
17240             if (trunkgroup > 0) {
17241                if ((c = strchr(v->value, ','))) {
17242                   i = 0;
17243                   memset(dchannels, 0, sizeof(dchannels));
17244                   while (c && (i < NUM_DCHANS)) {
17245                      dchannels[i] = atoi(c + 1);
17246                      if (dchannels[i] < 0) {
17247                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17248                      } else
17249                         i++;
17250                      c = strchr(c + 1, ',');
17251                   }
17252                   if (i) {
17253                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17254                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
17255                   } else
17256                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
17257                   } else
17258                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17259                } else
17260                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17261             } else
17262                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17263          } else if (!strcasecmp(v->name, "spanmap")) {
17264             spanno = atoi(v->value);
17265             if (spanno > 0) {
17266                if ((c = strchr(v->value, ','))) {
17267                   trunkgroup = atoi(c + 1);
17268                   if (trunkgroup > 0) {
17269                      if ((c = strchr(c + 1, ',')))
17270                         logicalspan = atoi(c + 1);
17271                      else
17272                         logicalspan = 0;
17273                      if (logicalspan >= 0) {
17274                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17275                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17276                      } else
17277                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17278                      } else
17279                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
17280                   } else
17281                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17282                } else
17283                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17284             } else
17285                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17286          } else {
17287             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17288          }
17289          v = v->next;
17290       }
17291    }
17292 #endif
17293 
17294    /* Copy the default jb config over global_jbconf */
17295    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17296 
17297    mwimonitornotify[0] = '\0';
17298 
17299    v = ast_variable_browse(cfg, "channels");
17300    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17301       ast_mutex_unlock(&iflock);
17302       ast_config_destroy(cfg);
17303       if (ucfg) {
17304          ast_config_destroy(ucfg);
17305       }
17306       return res;
17307    }
17308 
17309    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17310    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17311       /* [channels] and [trunkgroups] are used. Let's also reserve
17312        * [globals] and [general] for future use
17313        */
17314       if (!strcasecmp(cat, "general") ||
17315          !strcasecmp(cat, "trunkgroups") ||
17316          !strcasecmp(cat, "globals") ||
17317          !strcasecmp(cat, "channels")) {
17318          continue;
17319       }
17320 
17321       memcpy(&conf, &base_conf, sizeof(conf));
17322 
17323       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17324          ast_mutex_unlock(&iflock);
17325          ast_config_destroy(cfg);
17326          if (ucfg) {
17327             ast_config_destroy(ucfg);
17328          }
17329          return res;
17330       }
17331    }
17332 
17333    ast_config_destroy(cfg);
17334 
17335    if (ucfg) {
17336       const char *chans;
17337 
17338       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17339 
17340       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17341          if (!strcasecmp(cat, "general")) {
17342             continue;
17343          }
17344 
17345          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17346 
17347          if (ast_strlen_zero(chans)) {
17348             continue;
17349          }
17350 
17351          memcpy(&conf, &base_conf, sizeof(conf));
17352 
17353          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17354             ast_config_destroy(ucfg);
17355             ast_mutex_unlock(&iflock);
17356             return res;
17357          }
17358       }
17359       ast_config_destroy(ucfg);
17360    }
17361    ast_mutex_unlock(&iflock);
17362 
17363 #ifdef HAVE_PRI
17364    if (reload != 1) {
17365       int x;
17366       for (x = 0; x < NUM_SPANS; x++) {
17367          if (pris[x].pvts[0]) {
17368             if (start_pri(pris + x)) {
17369                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17370                return -1;
17371             } else
17372                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17373          }
17374       }
17375    }
17376 #endif
17377 #ifdef HAVE_SS7
17378    if (reload != 1) {
17379       int x;
17380       for (x = 0; x < NUM_SPANS; x++) {
17381          if (linksets[x].ss7) {
17382             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17383                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17384                return -1;
17385             } else
17386                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17387          }
17388       }
17389    }
17390 #endif
17391 #ifdef HAVE_OPENR2
17392    if (reload != 1) {
17393       int x;
17394       for (x = 0; x < r2links_count; x++) {
17395          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17396             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17397             return -1;
17398          } else {
17399             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17400          }
17401       }
17402    }
17403 #endif
17404    /* And start the monitor for the first time */
17405    restart_monitor();
17406    return 0;
17407 }
17408 
17409 static int load_module(void)
17410 {
17411    int res;
17412 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17413    int y, i;
17414 #endif
17415 
17416 #ifdef HAVE_PRI
17417    memset(pris, 0, sizeof(pris));
17418    for (y = 0; y < NUM_SPANS; y++) {
17419       ast_mutex_init(&pris[y].lock);
17420       pris[y].offset = -1;
17421       pris[y].master = AST_PTHREADT_NULL;
17422       for (i = 0; i < NUM_DCHANS; i++)
17423          pris[y].fds[i] = -1;
17424    }
17425    pri_set_error(dahdi_pri_error);
17426    pri_set_message(dahdi_pri_message);
17427    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17428 #ifdef HAVE_PRI_PROG_W_CAUSE
17429    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17430 #endif
17431 #endif
17432 #ifdef HAVE_SS7
17433    memset(linksets, 0, sizeof(linksets));
17434    for (y = 0; y < NUM_SPANS; y++) {
17435       ast_mutex_init(&linksets[y].lock);
17436       linksets[y].master = AST_PTHREADT_NULL;
17437       for (i = 0; i < NUM_DCHANS; i++)
17438          linksets[y].fds[i] = -1;
17439    }
17440    ss7_set_error(dahdi_ss7_error);
17441    ss7_set_message(dahdi_ss7_message);
17442 #endif /* HAVE_SS7 */
17443    res = setup_dahdi(0);
17444    /* Make sure we can register our DAHDI channel type */
17445    if (res)
17446       return AST_MODULE_LOAD_DECLINE;
17447    if (ast_channel_register(&dahdi_tech)) {
17448       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17449       __unload_module();
17450       return AST_MODULE_LOAD_FAILURE;
17451    }
17452 #ifdef HAVE_PRI
17453    ast_string_field_init(&inuse, 16);
17454    ast_string_field_set(&inuse, name, "GR-303InUse");
17455    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17456 #endif
17457 #ifdef HAVE_SS7
17458    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17459 #endif
17460 #ifdef HAVE_OPENR2
17461    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17462    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17463 #endif
17464 
17465    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17466 
17467    memset(round_robin, 0, sizeof(round_robin));
17468    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17469    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17470    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17471    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17472    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17473    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17474    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17475 
17476    ast_cond_init(&ss_thread_complete, NULL);
17477 
17478    return res;
17479 }
17480 
17481 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17482 {
17483 #define  END_SILENCE_LEN 400
17484 #define  HEADER_MS 50
17485 #define  TRAILER_MS 5
17486 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17487 #define  ASCII_BYTES_PER_CHAR 80
17488 
17489    unsigned char *buf,*mybuf;
17490    struct dahdi_pvt *p = c->tech_pvt;
17491    struct pollfd fds[1];
17492    int size,res,fd,len,x;
17493    int bytes=0;
17494    /* Initial carrier (imaginary) */
17495    float cr = 1.0;
17496    float ci = 0.0;
17497    float scont = 0.0;
17498    int idx;
17499 
17500    idx = dahdi_get_index(c, p, 0);
17501    if (idx < 0) {
17502       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
17503       return -1;
17504    }
17505    if (!text[0]) return(0); /* if nothing to send, dont */
17506    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
17507    if (p->mate)
17508       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17509    else
17510       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17511    if (!buf)
17512       return -1;
17513    mybuf = buf;
17514    if (p->mate) {
17515       int codec = AST_LAW(p);
17516       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
17517          PUT_CLID_MARKMS;
17518       }
17519       /* Put actual message */
17520       for (x = 0; text[x]; x++) {
17521          PUT_CLID(text[x]);
17522       }
17523       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
17524          PUT_CLID_MARKMS;
17525       }
17526       len = bytes;
17527       buf = mybuf;
17528    } else {
17529       len = tdd_generate(p->tdd, buf, text);
17530       if (len < 1) {
17531          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17532          ast_free(mybuf);
17533          return -1;
17534       }
17535    }
17536    memset(buf + len, 0x7f, END_SILENCE_LEN);
17537    len += END_SILENCE_LEN;
17538    fd = p->subs[idx].dfd;
17539    while (len) {
17540       if (ast_check_hangup(c)) {
17541          ast_free(mybuf);
17542          return -1;
17543       }
17544       size = len;
17545       if (size > READ_SIZE)
17546          size = READ_SIZE;
17547       fds[0].fd = fd;
17548       fds[0].events = POLLOUT | POLLPRI;
17549       fds[0].revents = 0;
17550       res = poll(fds, 1, -1);
17551       if (!res) {
17552          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17553          continue;
17554       }
17555       /* if got exception */
17556       if (fds[0].revents & POLLPRI) {
17557          ast_free(mybuf);
17558          return -1;
17559       }
17560       if (!(fds[0].revents & POLLOUT)) {
17561          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17562          continue;
17563       }
17564       res = write(fd, buf, size);
17565       if (res != size) {
17566          if (res == -1) {
17567             ast_free(mybuf);
17568             return -1;
17569          }
17570          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17571          break;
17572       }
17573       len -= size;
17574       buf += size;
17575    }
17576    ast_free(mybuf);
17577    return(0);
17578 }
17579 
17580 
17581 static int reload(void)
17582 {
17583    int res = 0;
17584 
17585    res = setup_dahdi(1);
17586    if (res) {
17587       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17588       return -1;
17589    }
17590    return 0;
17591 }
17592 
17593 /* This is a workaround so that menuselect displays a proper description
17594  * AST_MODULE_INFO(, , "DAHDI Telephony"
17595  */
17596 
17597 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17598    .load = load_module,
17599    .unload = unload_module,
17600    .reload = reload,
17601    );