Mon Sep 20 2010 00:20:29

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: 261453 $")
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 faxbuffersinuse: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 struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01400 
01401 static const struct ast_channel_tech dahdi_tech = {
01402    .type = "DAHDI",
01403    .description = tdesc,
01404    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01405    .requester = dahdi_request,
01406    .send_digit_begin = dahdi_digit_begin,
01407    .send_digit_end = dahdi_digit_end,
01408    .send_text = dahdi_sendtext,
01409    .call = dahdi_call,
01410    .hangup = dahdi_hangup,
01411    .answer = dahdi_answer,
01412    .read = dahdi_read,
01413    .write = dahdi_write,
01414    .bridge = dahdi_bridge,
01415    .exception = dahdi_exception,
01416    .indicate = dahdi_indicate,
01417    .fixup = dahdi_fixup,
01418    .setoption = dahdi_setoption,
01419    .func_channel_read = dahdi_func_read,
01420 };
01421 
01422 #ifdef HAVE_PRI
01423 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01424 #else
01425 #define GET_CHANNEL(p) ((p)->channel)
01426 #endif
01427 
01428 struct dahdi_pvt *round_robin[32];
01429 
01430 #if defined(HAVE_PRI)
01431 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01432 {
01433    int res;
01434    /* Grab the lock first */
01435    do {
01436       res = ast_mutex_trylock(&pri->lock);
01437       if (res) {
01438          DEADLOCK_AVOIDANCE(&pvt->lock);
01439       }
01440    } while (res);
01441    /* Then break the poll */
01442    if (pri->master != AST_PTHREADT_NULL)
01443       pthread_kill(pri->master, SIGURG);
01444    return 0;
01445 }
01446 #endif   /* defined(HAVE_PRI) */
01447 
01448 #if defined(HAVE_SS7)
01449 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01450 {
01451    ast_mutex_unlock(&ss7->lock);
01452 }
01453 #endif   /* defined(HAVE_SS7) */
01454 
01455 #if defined(HAVE_SS7)
01456 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01457 {
01458    int res;
01459    /* Grab the lock first */
01460    do {
01461       res = ast_mutex_trylock(&pri->lock);
01462       if (res) {
01463          DEADLOCK_AVOIDANCE(&pvt->lock);
01464       }
01465    } while (res);
01466    /* Then break the poll */
01467    if (pri->master != AST_PTHREADT_NULL)
01468       pthread_kill(pri->master, SIGURG);
01469    return 0;
01470 }
01471 #endif   /* defined(HAVE_SS7) */
01472 #define NUM_CADENCE_MAX 25
01473 static int num_cadence = 4;
01474 static int user_has_defined_cadences = 0;
01475 
01476 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01477    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01478    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01479    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01480    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01481 };
01482 
01483 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01484  * is 1, the second pause is 2 and so on.
01485  */
01486 
01487 static int cidrings[NUM_CADENCE_MAX] = {
01488    2,                            /*!< Right after first long ring */
01489    4,                            /*!< Right after long part */
01490    3,                            /*!< After third chirp */
01491    2,                            /*!< Second spell */
01492 };
01493 
01494 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01495 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01496 
01497 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01498          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01499 
01500 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01501 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01502 
01503 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01504 {
01505    int res;
01506    if (p->subs[SUB_REAL].owner == ast)
01507       res = 0;
01508    else if (p->subs[SUB_CALLWAIT].owner == ast)
01509       res = 1;
01510    else if (p->subs[SUB_THREEWAY].owner == ast)
01511       res = 2;
01512    else {
01513       res = -1;
01514       if (!nullok)
01515          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01516    }
01517    return res;
01518 }
01519 
01520 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01521 {
01522 #ifdef HAVE_PRI
01523    if (pri)
01524       ast_mutex_unlock(&pri->lock);
01525 #endif
01526    for (;;) {
01527       if (p->subs[a].owner) {
01528          if (ast_channel_trylock(p->subs[a].owner)) {
01529             DEADLOCK_AVOIDANCE(&p->lock);
01530          } else {
01531             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01532             ast_channel_unlock(p->subs[a].owner);
01533             break;
01534          }
01535       } else
01536          break;
01537    }
01538 #ifdef HAVE_PRI
01539    if (pri)
01540       ast_mutex_lock(&pri->lock);
01541 #endif
01542 }
01543 
01544 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01545 {
01546 #ifdef HAVE_PRI
01547    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01548 #endif
01549 #ifdef HAVE_SS7
01550    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01551 #endif
01552    /* We must unlock the PRI to avoid the possibility of a deadlock */
01553 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01554    if (data) {
01555       switch (p->sig) {
01556 #ifdef HAVE_PRI
01557       case SIG_BRI:
01558       case SIG_BRI_PTMP:
01559       case SIG_PRI:
01560          ast_mutex_unlock(&pri->lock);
01561          break;
01562 #endif
01563 #ifdef HAVE_SS7
01564       case SIG_SS7:
01565          ast_mutex_unlock(&ss7->lock);
01566          break;
01567 #endif
01568       default:
01569          break;
01570       }
01571    }
01572 #endif
01573    for (;;) {
01574       if (p->owner) {
01575          if (ast_channel_trylock(p->owner)) {
01576             DEADLOCK_AVOIDANCE(&p->lock);
01577          } else {
01578             ast_queue_frame(p->owner, f);
01579             ast_channel_unlock(p->owner);
01580             break;
01581          }
01582       } else
01583          break;
01584    }
01585 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01586    if (data) {
01587       switch (p->sig) {
01588 #ifdef HAVE_PRI
01589       case SIG_BRI:
01590       case SIG_BRI_PTMP:
01591       case SIG_PRI:
01592          ast_mutex_lock(&pri->lock);
01593          break;
01594 #endif
01595 #ifdef HAVE_SS7
01596       case SIG_SS7:
01597          ast_mutex_lock(&ss7->lock);
01598          break;
01599 #endif
01600       default:
01601          break;
01602       }
01603    }
01604 #endif
01605 }
01606 
01607 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01608 #ifdef HAVE_OPENR2
01609 
01610 static int dahdi_r2_answer(struct dahdi_pvt *p)
01611 {
01612    int res = 0;
01613    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01614    * and does not has support for openr2_chan_answer_call_with_mode
01615    *  */
01616 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01617    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01618    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01619    if (!double_answer) {
01620       /* this still can result in double answer if the channel context
01621       * was configured that way */
01622       res = openr2_chan_answer_call(p->r2chan);
01623    } else if (wants_double_answer) {
01624       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01625    } else {
01626       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01627    }
01628 #else
01629    res = openr2_chan_answer_call(p->r2chan);
01630 #endif
01631    return res;
01632 }
01633 
01634 
01635 
01636 /* should be called with the ast_channel locked */
01637 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01638 {
01639    openr2_calling_party_category_t cat;
01640    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01641    struct dahdi_pvt *p = c->tech_pvt;
01642    if (ast_strlen_zero(catstr)) {
01643       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01644             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01645       return p->mfcr2_category;
01646    }
01647    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01648       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01649             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01650       return p->mfcr2_category;
01651    }
01652    ast_debug(1, "Using category %s\n", catstr);
01653    return cat;
01654 }
01655 
01656 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01657 {
01658    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01659    ast_mutex_lock(&p->lock);
01660    if (p->mfcr2call) {
01661       ast_mutex_unlock(&p->lock);
01662       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
01663          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
01664          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
01665          the other end will see our seize as a forced release and drop the call, we will see an invalid
01666          pattern that will be seen and treated as protocol error. */
01667       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01668       return;
01669    }
01670    p->mfcr2call = 1;
01671    /* better safe than sorry ... */
01672    p->cid_name[0] = '\0';
01673    p->cid_num[0] = '\0';
01674    p->rdnis[0] = '\0';
01675    p->exten[0] = '\0';
01676    p->mfcr2_ani_index = '\0';
01677    p->mfcr2_dnis_index = '\0';
01678    p->mfcr2_dnis_matched = 0;
01679    p->mfcr2_answer_pending = 0;
01680    p->mfcr2_call_accepted = 0;
01681    ast_mutex_unlock(&p->lock);
01682    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01683 }
01684 
01685 static int get_alarms(struct dahdi_pvt *p);
01686 static void handle_alarms(struct dahdi_pvt *p, int alms);
01687 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01688 {
01689    int res;
01690    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01691    ast_mutex_lock(&p->lock);
01692    p->inalarm = alarm ? 1 : 0;
01693    if (p->inalarm) {
01694       res = get_alarms(p);
01695       handle_alarms(p, res);
01696    } else {
01697       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01698       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01699    }
01700    ast_mutex_unlock(&p->lock);
01701 }
01702 
01703 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01704 {
01705    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01706 }
01707 
01708 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01709 {
01710    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01711    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01712    if (p->owner) {
01713       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01714       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01715    }
01716    ast_mutex_lock(&p->lock);
01717    p->mfcr2call = 0;
01718    ast_mutex_unlock(&p->lock);
01719 }
01720 
01721 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01722 {
01723    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01724       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01725          p->channel, openr2_proto_get_disconnect_string(cause));
01726       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01727       openr2_chan_set_idle(p->r2chan);
01728       ast_mutex_lock(&p->lock);
01729       p->mfcr2call = 0;
01730       ast_mutex_unlock(&p->lock);
01731    }
01732 }
01733 
01734 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01735 {
01736    struct dahdi_pvt *p;
01737    struct ast_channel *c;
01738    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01739          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01740          openr2_proto_get_category_string(category));
01741    p = openr2_chan_get_client_data(r2chan);
01742    /* if collect calls are not allowed and this is a collect call, reject it! */
01743    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01744       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01745       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01746       return;
01747    }
01748    ast_mutex_lock(&p->lock);
01749    p->mfcr2_recvd_category = category;
01750    /* if we're not supposed to use CID, clear whatever we have */
01751    if (!p->use_callerid) {
01752       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01753       p->cid_num[0] = 0;
01754       p->cid_name[0] = 0;
01755    }
01756    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01757    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01758       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01759       p->exten[0] = 's';
01760       p->exten[1] = 0;
01761    }
01762    ast_mutex_unlock(&p->lock);
01763    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01764       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01765             p->channel, p->exten, p->context);
01766       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01767       return;
01768    }
01769    if (!p->mfcr2_accept_on_offer) {
01770       /* The user wants us to start the PBX thread right away without accepting the call first */
01771       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01772       if (c) {
01773          /* Done here, don't disable reading now since we still need to generate MF tones to accept
01774             the call or reject it and detect the tone off condition of the other end, all of this
01775             will be done in the PBX thread now */
01776          return;
01777       }
01778       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01779       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01780    } else if (p->mfcr2_charge_calls) {
01781       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01782       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01783    } else {
01784       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01785       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01786    }
01787 }
01788 
01789 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01790 {
01791    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01792    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01793    ast_mutex_lock(&p->lock);
01794    p->mfcr2call = 0;
01795    ast_mutex_unlock(&p->lock);
01796 }
01797 
01798 static void dahdi_enable_ec(struct dahdi_pvt *p);
01799 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01800 {
01801    struct dahdi_pvt *p = NULL;
01802    struct ast_channel *c = NULL;
01803    p = openr2_chan_get_client_data(r2chan);
01804    dahdi_enable_ec(p);
01805    p->mfcr2_call_accepted = 1;
01806    /* if it's an incoming call ... */
01807    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01808       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01809       /* If accept on offer is not set, it means at this point the PBX thread is already
01810          launched (was launched in the 'on call offered' handler) and therefore this callback
01811          is being executed already in the PBX thread rather than the monitor thread, don't launch
01812          any other thread, just disable the openr2 reading and answer the call if needed */
01813       if (!p->mfcr2_accept_on_offer) {
01814          openr2_chan_disable_read(r2chan);
01815          if (p->mfcr2_answer_pending) {
01816             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01817             dahdi_r2_answer(p);
01818          }
01819          return;
01820       }
01821       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01822       if (c) {
01823          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
01824             library to forget about it */
01825          openr2_chan_disable_read(r2chan);
01826          return;
01827       }
01828       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01829       /* failed to create the channel, bail out and report it as an out of order line */
01830       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01831       return;
01832    }
01833    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
01834    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01835    p->subs[SUB_REAL].needringing = 1;
01836    p->dialing = 0;
01837    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
01838    openr2_chan_disable_read(r2chan);
01839 }
01840 
01841 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01842 {
01843    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01844    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01845    p->subs[SUB_REAL].needanswer = 1;
01846 }
01847 
01848 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01849 {
01850    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01851 }
01852 
01853 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01854 {
01855    switch (cause) {
01856    case OR2_CAUSE_BUSY_NUMBER:
01857       return AST_CAUSE_BUSY;
01858    case OR2_CAUSE_NETWORK_CONGESTION:
01859       return AST_CAUSE_CONGESTION;
01860    case OR2_CAUSE_OUT_OF_ORDER:
01861       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01862    case OR2_CAUSE_UNALLOCATED_NUMBER:
01863       return AST_CAUSE_UNREGISTERED;
01864    case OR2_CAUSE_NO_ANSWER:
01865       return AST_CAUSE_NO_ANSWER;
01866    case OR2_CAUSE_NORMAL_CLEARING:
01867       return AST_CAUSE_NORMAL_CLEARING;
01868    case OR2_CAUSE_UNSPECIFIED:
01869    default:
01870       return AST_CAUSE_NOTDEFINED;
01871    }
01872 }
01873 
01874 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01875 {
01876    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01877    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01878    ast_mutex_lock(&p->lock);
01879    if (!p->owner) {
01880       ast_mutex_unlock(&p->lock);
01881       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
01882       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01883       return;
01884    }
01885    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
01886       be done in dahdi_hangup */
01887    if (p->owner->_state == AST_STATE_UP) {
01888       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01889       ast_mutex_unlock(&p->lock);
01890    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01891       /* being the forward side we must report what happened to the call to whoever requested it */
01892       switch (cause) {
01893       case OR2_CAUSE_BUSY_NUMBER:
01894          p->subs[SUB_REAL].needbusy = 1;
01895          break;
01896       case OR2_CAUSE_NETWORK_CONGESTION:
01897       case OR2_CAUSE_OUT_OF_ORDER:
01898       case OR2_CAUSE_UNALLOCATED_NUMBER:
01899       case OR2_CAUSE_NO_ANSWER:
01900       case OR2_CAUSE_UNSPECIFIED:
01901       case OR2_CAUSE_NORMAL_CLEARING:
01902          p->subs[SUB_REAL].needcongestion = 1;
01903          break;
01904       default:
01905          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01906       }
01907       ast_mutex_unlock(&p->lock);
01908    } else {
01909       ast_mutex_unlock(&p->lock);
01910       /* being the backward side and not UP yet, we only need to request hangup */
01911       /* TODO: what about doing this same thing when were AST_STATE_UP? */
01912       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01913    }
01914 }
01915 
01916 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01917 {
01918    switch (level) {
01919    case OR2_LOG_NOTICE:
01920       ast_verbose("%s", logmessage);
01921       break;
01922    case OR2_LOG_WARNING:
01923       ast_log(LOG_WARNING, "%s", logmessage);
01924       break;
01925    case OR2_LOG_ERROR:
01926       ast_log(LOG_ERROR, "%s", logmessage);
01927       break;
01928    case OR2_LOG_STACK_TRACE:
01929    case OR2_LOG_MF_TRACE:
01930    case OR2_LOG_CAS_TRACE:
01931    case OR2_LOG_DEBUG:
01932    case OR2_LOG_EX_DEBUG:
01933       ast_log(LOG_DEBUG, "%s", logmessage);
01934       break;
01935    default:
01936       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01937       ast_log(LOG_DEBUG, "%s", logmessage);
01938       break;
01939    }
01940 }
01941 
01942 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01943 {
01944    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01945    ast_mutex_lock(&p->lock);
01946    p->remotelyblocked = 1;
01947    ast_mutex_unlock(&p->lock);
01948    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01949 }
01950 
01951 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01952 {
01953    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01954    ast_mutex_lock(&p->lock);
01955    p->remotelyblocked = 0;
01956    ast_mutex_unlock(&p->lock);
01957    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01958 }
01959 
01960 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01961    __attribute__((format (printf, 3, 0)));
01962 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01963 {
01964 #define CONTEXT_TAG "Context - "
01965    char logmsg[256];
01966    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
01967    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01968    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
01969    dahdi_r2_write_log(level, completemsg);
01970 #undef CONTEXT_TAG
01971 }
01972 
01973 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01974    __attribute__((format (printf, 3, 0)));
01975 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01976 {
01977 #define CHAN_TAG "Chan "
01978    char logmsg[256];
01979    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
01980    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01981    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
01982    dahdi_r2_write_log(level, completemsg);
01983 }
01984 
01985 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01986 {
01987    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01988    /* if 'immediate' is set, let's stop requesting DNIS */
01989    if (p->immediate) {
01990       return 0;
01991    }
01992    p->exten[p->mfcr2_dnis_index] = digit;
01993    p->rdnis[p->mfcr2_dnis_index] = digit;
01994    p->mfcr2_dnis_index++;
01995    p->exten[p->mfcr2_dnis_index] = 0;
01996    p->rdnis[p->mfcr2_dnis_index] = 0;
01997    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
01998    if ((p->mfcr2_dnis_matched ||
01999        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02000        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02001       return 0;
02002    }
02003    /* otherwise keep going */
02004    return 1;
02005 }
02006 
02007 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02008 {
02009    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02010    p->cid_num[p->mfcr2_ani_index] = digit;
02011    p->cid_name[p->mfcr2_ani_index] = digit;
02012    p->mfcr2_ani_index++;
02013    p->cid_num[p->mfcr2_ani_index] = 0;
02014    p->cid_name[p->mfcr2_ani_index] = 0;
02015 }
02016 
02017 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02018 {
02019    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02020 }
02021 
02022 static openr2_event_interface_t dahdi_r2_event_iface = {
02023    .on_call_init = dahdi_r2_on_call_init,
02024    .on_call_offered = dahdi_r2_on_call_offered,
02025    .on_call_accepted = dahdi_r2_on_call_accepted,
02026    .on_call_answered = dahdi_r2_on_call_answered,
02027    .on_call_disconnect = dahdi_r2_on_call_disconnect,
02028    .on_call_end = dahdi_r2_on_call_end,
02029    .on_call_read = dahdi_r2_on_call_read,
02030    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02031    .on_os_error = dahdi_r2_on_os_error,
02032    .on_protocol_error = dahdi_r2_on_protocol_error,
02033    .on_line_blocked = dahdi_r2_on_line_blocked,
02034    .on_line_idle = dahdi_r2_on_line_idle,
02035    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
02036    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02037    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02038    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02039    /* so far we do nothing with billing pulses */
02040    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02041 };
02042 
02043 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02044 {
02045    return AST_ALAW(sample);
02046 }
02047 
02048 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02049 {
02050    return AST_LIN2A(sample);
02051 }
02052 
02053 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02054    dahdi_r2_alaw_to_linear,
02055    dahdi_r2_linear_to_alaw
02056 };
02057 
02058 #endif /* HAVE_OPENR2 */
02059 
02060 static int restore_gains(struct dahdi_pvt *p);
02061 
02062 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02063 {
02064    int tchan;
02065    int tinthreeway;
02066    struct ast_channel *towner;
02067 
02068    ast_debug(1, "Swapping %d and %d\n", a, b);
02069 
02070    tchan = p->subs[a].chan;
02071    towner = p->subs[a].owner;
02072    tinthreeway = p->subs[a].inthreeway;
02073 
02074    p->subs[a].chan = p->subs[b].chan;
02075    p->subs[a].owner = p->subs[b].owner;
02076    p->subs[a].inthreeway = p->subs[b].inthreeway;
02077 
02078    p->subs[b].chan = tchan;
02079    p->subs[b].owner = towner;
02080    p->subs[b].inthreeway = tinthreeway;
02081 
02082    if (p->subs[a].owner)
02083       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02084    if (p->subs[b].owner)
02085       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02086    wakeup_sub(p, a, NULL);
02087    wakeup_sub(p, b, NULL);
02088 }
02089 
02090 static int dahdi_open(char *fn)
02091 {
02092    int fd;
02093    int isnum;
02094    int chan = 0;
02095    int bs;
02096    int x;
02097    isnum = 1;
02098    for (x = 0; x < strlen(fn); x++) {
02099       if (!isdigit(fn[x])) {
02100          isnum = 0;
02101          break;
02102       }
02103    }
02104    if (isnum) {
02105       chan = atoi(fn);
02106       if (chan < 1) {
02107          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02108          return -1;
02109       }
02110       fn = "/dev/dahdi/channel";
02111    }
02112    fd = open(fn, O_RDWR | O_NONBLOCK);
02113    if (fd < 0) {
02114       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02115       return -1;
02116    }
02117    if (chan) {
02118       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02119          x = errno;
02120          close(fd);
02121          errno = x;
02122          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02123          return -1;
02124       }
02125    }
02126    bs = READ_SIZE;
02127    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02128       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
02129       x = errno;
02130       close(fd);
02131       errno = x;
02132       return -1;
02133    }
02134    return fd;
02135 }
02136 
02137 static void dahdi_close(int fd)
02138 {
02139    if (fd > 0)
02140       close(fd);
02141 }
02142 
02143 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02144 {
02145    dahdi_close(chan_pvt->subs[sub_num].dfd);
02146    chan_pvt->subs[sub_num].dfd = -1;
02147 }
02148 
02149 #if defined(HAVE_PRI)
02150 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02151 {
02152    dahdi_close(pri->fds[fd_num]);
02153    pri->fds[fd_num] = -1;
02154 }
02155 #endif   /* defined(HAVE_PRI) */
02156 
02157 #if defined(HAVE_SS7)
02158 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02159 {
02160    dahdi_close(ss7->fds[fd_num]);
02161    ss7->fds[fd_num] = -1;
02162 }
02163 #endif   /* defined(HAVE_SS7) */
02164 
02165 static int dahdi_setlinear(int dfd, int linear)
02166 {
02167    int res;
02168    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02169    if (res)
02170       return res;
02171    return 0;
02172 }
02173 
02174 
02175 static int alloc_sub(struct dahdi_pvt *p, int x)
02176 {
02177    struct dahdi_bufferinfo bi;
02178    int res;
02179    if (p->subs[x].dfd >= 0) {
02180       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02181       return -1;
02182    }
02183 
02184    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02185    if (p->subs[x].dfd <= -1) {
02186       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02187       return -1;
02188    }
02189 
02190    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02191    if (!res) {
02192       bi.txbufpolicy = p->buf_policy;
02193       bi.rxbufpolicy = p->buf_policy;
02194       bi.numbufs = p->buf_no;
02195       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02196       if (res < 0) {
02197          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02198       }
02199    } else
02200       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02201 
02202    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02203       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02204       dahdi_close_sub(p, x);
02205       p->subs[x].dfd = -1;
02206       return -1;
02207    }
02208    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02209    return 0;
02210 }
02211 
02212 static int unalloc_sub(struct dahdi_pvt *p, int x)
02213 {
02214    if (!x) {
02215       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02216       return -1;
02217    }
02218    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02219    dahdi_close_sub(p, x);
02220    p->subs[x].linear = 0;
02221    p->subs[x].chan = 0;
02222    p->subs[x].owner = NULL;
02223    p->subs[x].inthreeway = 0;
02224    p->polarity = POLARITY_IDLE;
02225    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02226    return 0;
02227 }
02228 
02229 static int digit_to_dtmfindex(char digit)
02230 {
02231    if (isdigit(digit))
02232       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02233    else if (digit >= 'A' && digit <= 'D')
02234       return DAHDI_TONE_DTMF_A + (digit - 'A');
02235    else if (digit >= 'a' && digit <= 'd')
02236       return DAHDI_TONE_DTMF_A + (digit - 'a');
02237    else if (digit == '*')
02238       return DAHDI_TONE_DTMF_s;
02239    else if (digit == '#')
02240       return DAHDI_TONE_DTMF_p;
02241    else
02242       return -1;
02243 }
02244 
02245 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02246 {
02247    struct dahdi_pvt *pvt;
02248    int idx;
02249    int dtmf = -1;
02250 
02251    pvt = chan->tech_pvt;
02252 
02253    ast_mutex_lock(&pvt->lock);
02254 
02255    idx = dahdi_get_index(chan, pvt, 0);
02256 
02257    if ((idx != SUB_REAL) || !pvt->owner)
02258       goto out;
02259 
02260 #ifdef HAVE_PRI
02261    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02262          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
02263       if (pvt->setup_ack) {
02264          if (!pri_grab(pvt, pvt->pri)) {
02265             pri_information(pvt->pri->pri, pvt->call, digit);
02266             pri_rel(pvt->pri);
02267          } else
02268             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02269       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
02270          int res;
02271          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
02272          res = strlen(pvt->dialdest);
02273          pvt->dialdest[res++] = digit;
02274          pvt->dialdest[res] = '\0';
02275       }
02276       goto out;
02277    }
02278 #endif
02279    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02280       goto out;
02281 
02282    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02283       int res;
02284       struct dahdi_dialoperation zo = {
02285          .op = DAHDI_DIAL_OP_APPEND,
02286       };
02287 
02288       zo.dialstr[0] = 'T';
02289       zo.dialstr[1] = digit;
02290       zo.dialstr[2] = '\0';
02291       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02292          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02293       else
02294          pvt->dialing = 1;
02295    } else {
02296       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02297       pvt->dialing = 1;
02298       pvt->begindigit = digit;
02299    }
02300 
02301 out:
02302    ast_mutex_unlock(&pvt->lock);
02303 
02304    return 0;
02305 }
02306 
02307 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02308 {
02309    struct dahdi_pvt *pvt;
02310    int res = 0;
02311    int idx;
02312    int x;
02313 
02314    pvt = chan->tech_pvt;
02315 
02316    ast_mutex_lock(&pvt->lock);
02317 
02318    idx = dahdi_get_index(chan, pvt, 0);
02319 
02320    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02321       goto out;
02322 
02323 #ifdef HAVE_PRI
02324    /* This means that the digit was already sent via PRI signalling */
02325    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02326          && !pvt->begindigit)
02327       goto out;
02328 #endif
02329 
02330    if (pvt->begindigit) {
02331       x = -1;
02332       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02333       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02334       pvt->dialing = 0;
02335       pvt->begindigit = 0;
02336    }
02337 
02338 out:
02339    ast_mutex_unlock(&pvt->lock);
02340 
02341    return res;
02342 }
02343 
02344 static char *events[] = {
02345    "No event",
02346    "On hook",
02347    "Ring/Answered",
02348    "Wink/Flash",
02349    "Alarm",
02350    "No more alarm",
02351    "HDLC Abort",
02352    "HDLC Overrun",
02353    "HDLC Bad FCS",
02354    "Dial Complete",
02355    "Ringer On",
02356    "Ringer Off",
02357    "Hook Transition Complete",
02358    "Bits Changed",
02359    "Pulse Start",
02360    "Timer Expired",
02361    "Timer Ping",
02362    "Polarity Reversal",
02363    "Ring Begin",
02364 };
02365 
02366 static struct {
02367    int alarm;
02368    char *name;
02369 } alarms[] = {
02370    { DAHDI_ALARM_RED, "Red Alarm" },
02371    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02372    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02373    { DAHDI_ALARM_RECOVER, "Recovering" },
02374    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02375    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02376    { DAHDI_ALARM_NONE, "None" },
02377 };
02378 
02379 static char *alarm2str(int alm)
02380 {
02381    int x;
02382    for (x = 0; x < ARRAY_LEN(alarms); x++) {
02383       if (alarms[x].alarm & alm)
02384          return alarms[x].name;
02385    }
02386    return alm ? "Unknown Alarm" : "No Alarm";
02387 }
02388 
02389 static char *event2str(int event)
02390 {
02391    static char buf[256];
02392    if ((event < (ARRAY_LEN(events))) && (event > -1))
02393       return events[event];
02394    sprintf(buf, "Event %d", event); /* safe */
02395    return buf;
02396 }
02397 
02398 #ifdef HAVE_PRI
02399 static char *dialplan2str(int dialplan)
02400 {
02401    if (dialplan == -1 || dialplan == -2) {
02402       return("Dynamically set dialplan in ISDN");
02403    }
02404    return (pri_plan2str(dialplan));
02405 }
02406 #endif
02407 
02408 static char *dahdi_sig2str(int sig)
02409 {
02410    static char buf[256];
02411    switch (sig) {
02412    case SIG_EM:
02413       return "E & M Immediate";
02414    case SIG_EMWINK:
02415       return "E & M Wink";
02416    case SIG_EM_E1:
02417       return "E & M E1";
02418    case SIG_FEATD:
02419       return "Feature Group D (DTMF)";
02420    case SIG_FEATDMF:
02421       return "Feature Group D (MF)";
02422    case SIG_FEATDMF_TA:
02423       return "Feature Groud D (MF) Tandem Access";
02424    case SIG_FEATB:
02425       return "Feature Group B (MF)";
02426    case SIG_E911:
02427       return "E911 (MF)";
02428    case SIG_FGC_CAMA:
02429       return "FGC/CAMA (Dialpulse)";
02430    case SIG_FGC_CAMAMF:
02431       return "FGC/CAMA (MF)";
02432    case SIG_FXSLS:
02433       return "FXS Loopstart";
02434    case SIG_FXSGS:
02435       return "FXS Groundstart";
02436    case SIG_FXSKS:
02437       return "FXS Kewlstart";
02438    case SIG_FXOLS:
02439       return "FXO Loopstart";
02440    case SIG_FXOGS:
02441       return "FXO Groundstart";
02442    case SIG_FXOKS:
02443       return "FXO Kewlstart";
02444    case SIG_PRI:
02445       return "ISDN PRI";
02446    case SIG_BRI:
02447       return "ISDN BRI Point to Point";
02448    case SIG_BRI_PTMP:
02449       return "ISDN BRI Point to MultiPoint";
02450    case SIG_SS7:
02451       return "SS7";
02452    case SIG_MFCR2:
02453       return "MFC/R2";
02454    case SIG_SF:
02455       return "SF (Tone) Immediate";
02456    case SIG_SFWINK:
02457       return "SF (Tone) Wink";
02458    case SIG_SF_FEATD:
02459       return "SF (Tone) with Feature Group D (DTMF)";
02460    case SIG_SF_FEATDMF:
02461       return "SF (Tone) with Feature Group D (MF)";
02462    case SIG_SF_FEATB:
02463       return "SF (Tone) with Feature Group B (MF)";
02464    case SIG_GR303FXOKS:
02465       return "GR-303 with FXOKS";
02466    case SIG_GR303FXSKS:
02467       return "GR-303 with FXSKS";
02468    case 0:
02469       return "Pseudo";
02470    default:
02471       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02472       return buf;
02473    }
02474 }
02475 
02476 #define sig2str dahdi_sig2str
02477 
02478 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02479 {
02480    /* If the conference already exists, and we're already in it
02481       don't bother doing anything */
02482    struct dahdi_confinfo zi;
02483 
02484    memset(&zi, 0, sizeof(zi));
02485    zi.chan = 0;
02486 
02487    if (slavechannel > 0) {
02488       /* If we have only one slave, do a digital mon */
02489       zi.confmode = DAHDI_CONF_DIGITALMON;
02490       zi.confno = slavechannel;
02491    } else {
02492       if (!idx) {
02493          /* Real-side and pseudo-side both participate in conference */
02494          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02495             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02496       } else
02497          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02498       zi.confno = p->confno;
02499    }
02500    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02501       return 0;
02502    if (c->dfd < 0)
02503       return 0;
02504    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02505       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02506       return -1;
02507    }
02508    if (slavechannel < 1) {
02509       p->confno = zi.confno;
02510    }
02511    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02512    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02513    return 0;
02514 }
02515 
02516 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02517 {
02518    /* If they're listening to our channel, they're ours */
02519    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02520       return 1;
02521    /* If they're a talker on our (allocated) conference, they're ours */
02522    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02523       return 1;
02524    return 0;
02525 }
02526 
02527 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02528 {
02529    struct dahdi_confinfo zi;
02530    if (/* Can't delete if there's no dfd */
02531       (c->dfd < 0) ||
02532       /* Don't delete from the conference if it's not our conference */
02533       !isourconf(p, c)
02534       /* Don't delete if we don't think it's conferenced at all (implied) */
02535       ) return 0;
02536    memset(&zi, 0, sizeof(zi));
02537    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02538       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02539       return -1;
02540    }
02541    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02542    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02543    return 0;
02544 }
02545 
02546 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02547 {
02548    int x;
02549    int useslavenative;
02550    struct dahdi_pvt *slave = NULL;
02551    /* Start out optimistic */
02552    useslavenative = 1;
02553    /* Update conference state in a stateless fashion */
02554    for (x = 0; x < 3; x++) {
02555       /* Any three-way calling makes slave native mode *definitely* out
02556          of the question */
02557       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02558          useslavenative = 0;
02559    }
02560    /* If we don't have any 3-way calls, check to see if we have
02561       precisely one slave */
02562    if (useslavenative) {
02563       for (x = 0; x < MAX_SLAVES; x++) {
02564          if (p->slaves[x]) {
02565             if (slave) {
02566                /* Whoops already have a slave!  No
02567                   slave native and stop right away */
02568                slave = NULL;
02569                useslavenative = 0;
02570                break;
02571             } else {
02572                /* We have one slave so far */
02573                slave = p->slaves[x];
02574             }
02575          }
02576       }
02577    }
02578    /* If no slave, slave native definitely out */
02579    if (!slave)
02580       useslavenative = 0;
02581    else if (slave->law != p->law) {
02582       useslavenative = 0;
02583       slave = NULL;
02584    }
02585    if (out)
02586       *out = slave;
02587    return useslavenative;
02588 }
02589 
02590 static int reset_conf(struct dahdi_pvt *p)
02591 {
02592    p->confno = -1;
02593    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02594    if (p->subs[SUB_REAL].dfd > -1) {
02595       struct dahdi_confinfo zi;
02596 
02597       memset(&zi, 0, sizeof(zi));
02598       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02599          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02600    }
02601    return 0;
02602 }
02603 
02604 static int update_conf(struct dahdi_pvt *p)
02605 {
02606    int needconf = 0;
02607    int x;
02608    int useslavenative;
02609    struct dahdi_pvt *slave = NULL;
02610 
02611    useslavenative = isslavenative(p, &slave);
02612    /* Start with the obvious, general stuff */
02613    for (x = 0; x < 3; x++) {
02614       /* Look for three way calls */
02615       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02616          conf_add(p, &p->subs[x], x, 0);
02617          needconf++;
02618       } else {
02619          conf_del(p, &p->subs[x], x);
02620       }
02621    }
02622    /* If we have a slave, add him to our conference now. or DAX
02623       if this is slave native */
02624    for (x = 0; x < MAX_SLAVES; x++) {
02625       if (p->slaves[x]) {
02626          if (useslavenative)
02627             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02628          else {
02629             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02630             needconf++;
02631          }
02632       }
02633    }
02634    /* If we're supposed to be in there, do so now */
02635    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02636       if (useslavenative)
02637          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02638       else {
02639          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02640          needconf++;
02641       }
02642    }
02643    /* If we have a master, add ourselves to his conference */
02644    if (p->master) {
02645       if (isslavenative(p->master, NULL)) {
02646          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02647       } else {
02648          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02649       }
02650    }
02651    if (!needconf) {
02652       /* Nobody is left (or should be left) in our conference.
02653          Kill it. */
02654       p->confno = -1;
02655    }
02656    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02657    return 0;
02658 }
02659 
02660 static void dahdi_enable_ec(struct dahdi_pvt *p)
02661 {
02662    int x;
02663    int res;
02664    if (!p)
02665       return;
02666    if (p->echocanon) {
02667       ast_debug(1, "Echo cancellation already on\n");
02668       return;
02669    }
02670    if (p->digital) {
02671       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02672       return;
02673    }
02674    if (p->echocancel.head.tap_length) {
02675       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02676          x = 1;
02677          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02678          if (res)
02679             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02680       }
02681       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02682       if (res) {
02683          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02684       } else {
02685          p->echocanon = 1;
02686          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02687       }
02688    } else
02689       ast_debug(1, "No echo cancellation requested\n");
02690 }
02691 
02692 static void dahdi_train_ec(struct dahdi_pvt *p)
02693 {
02694    int x;
02695    int res;
02696 
02697    if (p && p->echocanon && p->echotraining) {
02698       x = p->echotraining;
02699       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02700       if (res)
02701          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02702       else
02703          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02704    } else {
02705       ast_debug(1, "No echo training requested\n");
02706    }
02707 }
02708 
02709 static void dahdi_disable_ec(struct dahdi_pvt *p)
02710 {
02711    int res;
02712 
02713    if (p->echocanon) {
02714       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02715 
02716       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02717 
02718       if (res)
02719          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02720       else
02721          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02722    }
02723 
02724    p->echocanon = 0;
02725 }
02726 
02727 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02728 {
02729    int j;
02730    int k;
02731    float linear_gain = pow(10.0, gain / 20.0);
02732 
02733    switch (law) {
02734    case DAHDI_LAW_ALAW:
02735       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02736          if (gain) {
02737             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02738             if (k > 32767) k = 32767;
02739             if (k < -32767) k = -32767;
02740             g->txgain[j] = AST_LIN2A(k);
02741          } else {
02742             g->txgain[j] = j;
02743          }
02744       }
02745       break;
02746    case DAHDI_LAW_MULAW:
02747       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02748          if (gain) {
02749             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02750             if (k > 32767) k = 32767;
02751             if (k < -32767) k = -32767;
02752             g->txgain[j] = AST_LIN2MU(k);
02753          } else {
02754             g->txgain[j] = j;
02755          }
02756       }
02757       break;
02758    }
02759 }
02760 
02761 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02762 {
02763    int j;
02764    int k;
02765    float linear_gain = pow(10.0, gain / 20.0);
02766 
02767    switch (law) {
02768    case DAHDI_LAW_ALAW:
02769       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02770          if (gain) {
02771             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02772             if (k > 32767) k = 32767;
02773             if (k < -32767) k = -32767;
02774             g->rxgain[j] = AST_LIN2A(k);
02775          } else {
02776             g->rxgain[j] = j;
02777          }
02778       }
02779       break;
02780    case DAHDI_LAW_MULAW:
02781       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02782          if (gain) {
02783             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02784             if (k > 32767) k = 32767;
02785             if (k < -32767) k = -32767;
02786             g->rxgain[j] = AST_LIN2MU(k);
02787          } else {
02788             g->rxgain[j] = j;
02789          }
02790       }
02791       break;
02792    }
02793 }
02794 
02795 static int set_actual_txgain(int fd, int chan, float gain, int law)
02796 {
02797    struct dahdi_gains g;
02798    int res;
02799 
02800    memset(&g, 0, sizeof(g));
02801    g.chan = chan;
02802    res = ioctl(fd, DAHDI_GETGAINS, &g);
02803    if (res) {
02804       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02805       return res;
02806    }
02807 
02808    fill_txgain(&g, gain, law);
02809 
02810    return ioctl(fd, DAHDI_SETGAINS, &g);
02811 }
02812 
02813 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02814 {
02815    struct dahdi_gains g;
02816    int res;
02817 
02818    memset(&g, 0, sizeof(g));
02819    g.chan = chan;
02820    res = ioctl(fd, DAHDI_GETGAINS, &g);
02821    if (res) {
02822       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02823       return res;
02824    }
02825 
02826    fill_rxgain(&g, gain, law);
02827 
02828    return ioctl(fd, DAHDI_SETGAINS, &g);
02829 }
02830 
02831 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02832 {
02833    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02834 }
02835 
02836 static int bump_gains(struct dahdi_pvt *p)
02837 {
02838    int res;
02839 
02840    /* Bump receive gain by value stored in cid_rxgain */
02841    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02842    if (res) {
02843       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02844       return -1;
02845    }
02846 
02847    return 0;
02848 }
02849 
02850 static int restore_gains(struct dahdi_pvt *p)
02851 {
02852    int res;
02853 
02854    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02855    if (res) {
02856       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02857       return -1;
02858    }
02859 
02860    return 0;
02861 }
02862 
02863 static inline int dahdi_set_hook(int fd, int hs)
02864 {
02865    int x, res;
02866 
02867    x = hs;
02868    res = ioctl(fd, DAHDI_HOOK, &x);
02869 
02870    if (res < 0) {
02871       if (errno == EINPROGRESS)
02872          return 0;
02873       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02874       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02875    }
02876 
02877    return res;
02878 }
02879 
02880 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02881 {
02882    int x, y, res;
02883    x = muted;
02884    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02885       y = 1;
02886       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02887       if (res)
02888          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02889    }
02890    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02891    if (res < 0)
02892       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02893    return res;
02894 }
02895 
02896 static int save_conference(struct dahdi_pvt *p)
02897 {
02898    struct dahdi_confinfo c;
02899    int res;
02900    if (p->saveconf.confmode) {
02901       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02902       return -1;
02903    }
02904    p->saveconf.chan = 0;
02905    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02906    if (res) {
02907       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02908       p->saveconf.confmode = 0;
02909       return -1;
02910    }
02911    memset(&c, 0, sizeof(c));
02912    c.confmode = DAHDI_CONF_NORMAL;
02913    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02914    if (res) {
02915       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02916       return -1;
02917    }
02918    ast_debug(1, "Disabled conferencing\n");
02919    return 0;
02920 }
02921 
02922 /*!
02923  * \brief Send MWI state change
02924  *
02925  * \arg mailbox_full This is the mailbox associated with the FXO line that the
02926  *      MWI state has changed on.
02927  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
02928  *      whether there are messages waiting or not.
02929  *
02930  *  \return nothing
02931  *
02932  * This function does two things:
02933  *
02934  * 1) It generates an internal Asterisk event notifying any other module that
02935  *    cares about MWI that the state of a mailbox has changed.
02936  *
02937  * 2) It runs the script specified by the mwimonitornotify option to allow
02938  *    some custom handling of the state change.
02939  */
02940 static void notify_message(char *mailbox_full, int thereornot)
02941 {
02942    char s[sizeof(mwimonitornotify) + 80];
02943    struct ast_event *event;
02944    char *mailbox, *context;
02945 
02946    /* Strip off @default */
02947    context = mailbox = ast_strdupa(mailbox_full);
02948    strsep(&context, "@");
02949    if (ast_strlen_zero(context))
02950       context = "default";
02951 
02952    if (!(event = ast_event_new(AST_EVENT_MWI,
02953          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02954          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02955          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02956          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02957          AST_EVENT_IE_END))) {
02958       return;
02959    }
02960 
02961    ast_event_queue_and_cache(event);
02962 
02963    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02964       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02965       ast_safe_system(s);
02966    }
02967 }
02968 
02969 static int restore_conference(struct dahdi_pvt *p)
02970 {
02971    int res;
02972    if (p->saveconf.confmode) {
02973       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02974       p->saveconf.confmode = 0;
02975       if (res) {
02976          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02977          return -1;
02978       }
02979    }
02980    ast_debug(1, "Restored conferencing\n");
02981    return 0;
02982 }
02983 
02984 static int send_callerid(struct dahdi_pvt *p);
02985 
02986 static int send_cwcidspill(struct dahdi_pvt *p)
02987 {
02988    p->callwaitcas = 0;
02989    p->cidcwexpire = 0;
02990    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02991       return -1;
02992    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02993    /* Make sure we account for the end */
02994    p->cidlen += READ_SIZE * 4;
02995    p->cidpos = 0;
02996    send_callerid(p);
02997    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02998    return 0;
02999 }
03000 
03001 static int has_voicemail(struct dahdi_pvt *p)
03002 {
03003    int new_msgs;
03004    struct ast_event *event;
03005    char *mailbox, *context;
03006 
03007    mailbox = context = ast_strdupa(p->mailbox);
03008    strsep(&context, "@");
03009    if (ast_strlen_zero(context))
03010       context = "default";
03011 
03012    event = ast_event_get_cached(AST_EVENT_MWI,
03013       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03014       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03015       AST_EVENT_IE_END);
03016 
03017    if (event) {
03018       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03019       ast_event_destroy(event);
03020    } else
03021       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03022 
03023    return new_msgs;
03024 }
03025 
03026 static int send_callerid(struct dahdi_pvt *p)
03027 {
03028    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
03029    int res;
03030    /* Take out of linear mode if necessary */
03031    if (p->subs[SUB_REAL].linear) {
03032       p->subs[SUB_REAL].linear = 0;
03033       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03034    }
03035    while (p->cidpos < p->cidlen) {
03036       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03037       if (res < 0) {
03038          if (errno == EAGAIN)
03039             return 0;
03040          else {
03041             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03042             return -1;
03043          }
03044       }
03045       if (!res)
03046          return 0;
03047       p->cidpos += res;
03048    }
03049    ast_free(p->cidspill);
03050    p->cidspill = NULL;
03051    if (p->callwaitcas) {
03052       /* Wait for CID/CW to expire */
03053       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03054    } else
03055       restore_conference(p);
03056    return 0;
03057 }
03058 
03059 static int dahdi_callwait(struct ast_channel *ast)
03060 {
03061    struct dahdi_pvt *p = ast->tech_pvt;
03062    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03063    if (p->cidspill) {
03064       ast_log(LOG_WARNING, "Spill already exists?!?\n");
03065       ast_free(p->cidspill);
03066    }
03067    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
03068       return -1;
03069    save_conference(p);
03070    /* Silence */
03071    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03072    if (!p->callwaitrings && p->callwaitingcallerid) {
03073       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03074       p->callwaitcas = 1;
03075       p->cidlen = 2400 + 680 + READ_SIZE * 4;
03076    } else {
03077       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03078       p->callwaitcas = 0;
03079       p->cidlen = 2400 + READ_SIZE * 4;
03080    }
03081    p->cidpos = 0;
03082    send_callerid(p);
03083 
03084    return 0;
03085 }
03086 
03087 #if defined(HAVE_SS7)
03088 static unsigned char cid_pres2ss7pres(int cid_pres)
03089 {
03090     return (cid_pres >> 5) & 0x03;
03091 }
03092 #endif   /* defined(HAVE_SS7) */
03093 
03094 #if defined(HAVE_SS7)
03095 static unsigned char cid_pres2ss7screen(int cid_pres)
03096 {
03097    return cid_pres & 0x03;
03098 }
03099 #endif   /* defined(HAVE_SS7) */
03100 
03101 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03102 {
03103    struct dahdi_pvt *p = ast->tech_pvt;
03104    int x, res, idx,mysig;
03105    char *c, *n, *l;
03106 #ifdef HAVE_PRI
03107    char *s = NULL;
03108 #endif
03109    char dest[256]; /* must be same length as p->dialdest */
03110    ast_mutex_lock(&p->lock);
03111    ast_copy_string(dest, rdest, sizeof(dest));
03112    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03113    if ((ast->_state == AST_STATE_BUSY)) {
03114       p->subs[SUB_REAL].needbusy = 1;
03115       ast_mutex_unlock(&p->lock);
03116       return 0;
03117    }
03118    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03119       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03120       ast_mutex_unlock(&p->lock);
03121       return -1;
03122    }
03123    p->waitingfordt.tv_sec = 0;
03124    p->dialednone = 0;
03125    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
03126    {
03127       /* Special pseudo -- automatically up */
03128       ast_setstate(ast, AST_STATE_UP);
03129       ast_mutex_unlock(&p->lock);
03130       return 0;
03131    }
03132    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03133    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03134    if (res)
03135       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03136    p->outgoing = 1;
03137 
03138    if (IS_DIGITAL(ast->transfercapability)){
03139       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03140    } else {
03141       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03142    }  
03143 
03144    mysig = p->sig;
03145    if (p->outsigmod > -1)
03146       mysig = p->outsigmod;
03147 
03148    switch (mysig) {
03149    case SIG_FXOLS:
03150    case SIG_FXOGS:
03151    case SIG_FXOKS:
03152       if (p->owner == ast) {
03153          /* Normal ring, on hook */
03154 
03155          /* Don't send audio while on hook, until the call is answered */
03156          p->dialing = 1;
03157          if (p->use_callerid) {
03158             /* Generate the Caller-ID spill if desired */
03159             if (p->cidspill) {
03160                ast_log(LOG_WARNING, "cidspill already exists??\n");
03161                ast_free(p->cidspill);
03162             }
03163             p->callwaitcas = 0;
03164             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03165                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03166                p->cidpos = 0;
03167                send_callerid(p);
03168             }
03169          }
03170          /* Choose proper cadence */
03171          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03172             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03173                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03174             p->cidrings = cidrings[p->distinctivering - 1];
03175          } else {
03176             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03177                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03178             p->cidrings = p->sendcalleridafter;
03179          }
03180 
03181          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
03182          c = strchr(dest, '/');
03183          if (c)
03184             c++;
03185          if (c && (strlen(c) < p->stripmsd)) {
03186             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03187             c = NULL;
03188          }
03189          if (c) {
03190             p->dop.op = DAHDI_DIAL_OP_REPLACE;
03191             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03192             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03193          } else {
03194             p->dop.dialstr[0] = '\0';
03195          }
03196          x = DAHDI_RING;
03197          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03198             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03199             ast_mutex_unlock(&p->lock);
03200             return -1;
03201          }
03202          p->dialing = 1;
03203       } else {
03204          /* Call waiting call */
03205          p->callwaitrings = 0;
03206          if (ast->cid.cid_num)
03207             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03208          else
03209             p->callwait_num[0] = '\0';
03210          if (ast->cid.cid_name)
03211             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03212          else
03213             p->callwait_name[0] = '\0';
03214          /* Call waiting tone instead */
03215          if (dahdi_callwait(ast)) {
03216             ast_mutex_unlock(&p->lock);
03217             return -1;
03218          }
03219          /* Make ring-back */
03220          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03221             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03222       }
03223       n = ast->cid.cid_name;
03224       l = ast->cid.cid_num;
03225       if (l)
03226          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03227       else
03228          p->lastcid_num[0] = '\0';
03229       if (n)
03230          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03231       else
03232          p->lastcid_name[0] = '\0';
03233       ast_setstate(ast, AST_STATE_RINGING);
03234       idx = dahdi_get_index(ast, p, 0);
03235       if (idx > -1) {
03236          p->subs[idx].needringing = 1;
03237       }
03238       break;
03239    case SIG_FXSLS:
03240    case SIG_FXSGS:
03241    case SIG_FXSKS:
03242       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03243          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03244          p->polaritydelaytv = ast_tvnow();
03245       }
03246       /* fall through */
03247    case SIG_EMWINK:
03248    case SIG_EM:
03249    case SIG_EM_E1:
03250    case SIG_FEATD:
03251    case SIG_FEATDMF:
03252    case SIG_E911:
03253    case SIG_FGC_CAMA:
03254    case SIG_FGC_CAMAMF:
03255    case SIG_FEATB:
03256    case SIG_SFWINK:
03257    case SIG_SF:
03258    case SIG_SF_FEATD:
03259    case SIG_SF_FEATDMF:
03260    case SIG_FEATDMF_TA:
03261    case SIG_SF_FEATB:
03262       c = strchr(dest, '/');
03263       if (c)
03264          c++;
03265       else
03266          c = "";
03267       if (strlen(c) < p->stripmsd) {
03268          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03269          ast_mutex_unlock(&p->lock);
03270          return -1;
03271       }
03272 #ifdef HAVE_PRI
03273       /* Start the trunk, if not GR-303 */
03274       if (!p->pri) {
03275 #endif
03276          x = DAHDI_START;
03277          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03278          if (res < 0) {
03279             if (errno != EINPROGRESS) {
03280                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03281                ast_mutex_unlock(&p->lock);
03282                return -1;
03283             }
03284          }
03285 #ifdef HAVE_PRI
03286       }
03287 #endif
03288       ast_debug(1, "Dialing '%s'\n", c);
03289       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03290 
03291       c += p->stripmsd;
03292 
03293       switch (mysig) {
03294       case SIG_FEATD:
03295          l = ast->cid.cid_num;
03296          if (l)
03297             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03298          else
03299             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03300          break;
03301       case SIG_FEATDMF:
03302          l = ast->cid.cid_num;
03303          if (l)
03304             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03305          else
03306             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03307          break;
03308       case SIG_FEATDMF_TA:
03309       {
03310          const char *cic, *ozz;
03311 
03312          /* If you have to go through a Tandem Access point you need to use this */
03313          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03314          if (!ozz)
03315             ozz = defaultozz;
03316          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03317          if (!cic)
03318             cic = defaultcic;
03319          if (!ozz || !cic) {
03320             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03321             ast_mutex_unlock(&p->lock);
03322             return -1;
03323          }
03324          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03325          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03326          p->whichwink = 0;
03327       }
03328          break;
03329       case SIG_E911:
03330          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03331          break;
03332       case SIG_FGC_CAMA:
03333          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03334          break;
03335       case SIG_FGC_CAMAMF:
03336       case SIG_FEATB:
03337          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03338          break;
03339       default:
03340          if (p->pulse)
03341             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03342          else
03343             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03344          break;
03345       }
03346 
03347       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03348          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03349          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03350          p->echorest[sizeof(p->echorest) - 1] = '\0';
03351          p->echobreak = 1;
03352          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03353       } else
03354          p->echobreak = 0;
03355 
03356       /* waitfordialtone ? */
03357 #ifdef HAVE_PRI
03358       if (!p->pri) {
03359 #endif
03360          if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03361             ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03362             gettimeofday(&p->waitingfordt,NULL);
03363             ast_setstate(ast, AST_STATE_OFFHOOK);
03364             break;
03365          }
03366 #ifdef HAVE_PRI
03367       }
03368 #endif
03369       if (!res) {
03370          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03371             int saveerr = errno;
03372 
03373             x = DAHDI_ONHOOK;
03374             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03375             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03376             ast_mutex_unlock(&p->lock);
03377             return -1;
03378          }
03379       } else
03380          ast_debug(1, "Deferring dialing...\n");
03381 
03382       p->dialing = 1;
03383       if (ast_strlen_zero(c))
03384          p->dialednone = 1;
03385       ast_setstate(ast, AST_STATE_DIALING);
03386       break;
03387    case 0:
03388       /* Special pseudo -- automatically up*/
03389       ast_setstate(ast, AST_STATE_UP);
03390       break;
03391    case SIG_PRI:
03392    case SIG_BRI:
03393    case SIG_BRI_PTMP:
03394    case SIG_SS7:
03395    case SIG_MFCR2:
03396       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03397       p->dialdest[0] = '\0';
03398       p->dialing = 1;
03399       break;
03400    default:
03401       ast_debug(1, "not yet implemented\n");
03402       ast_mutex_unlock(&p->lock);
03403       return -1;
03404    }
03405 #ifdef HAVE_SS7
03406    if (p->ss7) {
03407       char ss7_called_nai;
03408       int called_nai_strip;
03409       char ss7_calling_nai;
03410       int calling_nai_strip;
03411       const char *charge_str = NULL;
03412       const char *gen_address = NULL;
03413       const char *gen_digits = NULL;
03414       const char *gen_dig_type = NULL;
03415       const char *gen_dig_scheme = NULL;
03416       const char *gen_name = NULL;
03417       const char *jip_digits = NULL;
03418       const char *lspi_ident = NULL;
03419       const char *rlt_flag = NULL;
03420       const char *call_ref_id = NULL;
03421       const char *call_ref_pc = NULL;
03422       const char *send_far = NULL;
03423 
03424       c = strchr(dest, '/');
03425       if (c) {
03426          c++;
03427       } else {
03428          c = "";
03429       }
03430       if (strlen(c) < p->stripmsd) {
03431          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03432          ast_mutex_unlock(&p->lock);
03433          return -1;
03434       }
03435 
03436       if (!p->hidecallerid) {
03437          l = ast->cid.cid_num;
03438       } else {
03439          l = NULL;
03440       }
03441 
03442       if (ss7_grab(p, p->ss7)) {
03443          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03444          ast_mutex_unlock(&p->lock);
03445          return -1;
03446       }
03447       p->digital = IS_DIGITAL(ast->transfercapability);
03448       p->ss7call = isup_new_call(p->ss7->ss7);
03449 
03450       if (!p->ss7call) {
03451          ss7_rel(p->ss7);
03452          ast_mutex_unlock(&p->lock);
03453          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03454          return -1;
03455       }
03456 
03457       called_nai_strip = 0;
03458       ss7_called_nai = p->ss7->called_nai;
03459       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
03460          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03461             called_nai_strip = strlen(p->ss7->internationalprefix);
03462             ss7_called_nai = SS7_NAI_INTERNATIONAL;
03463          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03464             called_nai_strip = strlen(p->ss7->nationalprefix);
03465             ss7_called_nai = SS7_NAI_NATIONAL;
03466          } else {
03467             ss7_called_nai = SS7_NAI_SUBSCRIBER;
03468          }
03469       }
03470       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03471 
03472       calling_nai_strip = 0;
03473       ss7_calling_nai = p->ss7->calling_nai;
03474       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
03475          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03476             calling_nai_strip = strlen(p->ss7->internationalprefix);
03477             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03478          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03479             calling_nai_strip = strlen(p->ss7->nationalprefix);
03480             ss7_calling_nai = SS7_NAI_NATIONAL;
03481          } else {
03482             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03483          }
03484       }
03485       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03486          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03487          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03488 
03489       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03490       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03491 
03492       ast_channel_lock(ast);
03493       /* Set the charge number if it is set */
03494       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03495       if (charge_str)
03496          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03497 
03498       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03499       if (gen_address)
03500          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 */
03501 
03502       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03503       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03504       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03505       if (gen_digits)
03506          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03507 
03508       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03509       if (gen_name)
03510          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03511 
03512       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03513       if (jip_digits)
03514          isup_set_jip_digits(p->ss7call, jip_digits);
03515 
03516       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03517       if (lspi_ident)
03518          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03519 
03520       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03521       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03522          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
03523       }
03524 
03525       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03526       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03527       if (call_ref_id && call_ref_pc) {
03528          isup_set_callref(p->ss7call, atoi(call_ref_id),
03529                 call_ref_pc ? atoi(call_ref_pc) : 0);
03530       }
03531 
03532       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03533       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03534          (isup_far(p->ss7->ss7, p->ss7call));
03535 
03536       ast_channel_unlock(ast);
03537 
03538       isup_iam(p->ss7->ss7, p->ss7call);
03539       ast_setstate(ast, AST_STATE_DIALING);
03540       ss7_rel(p->ss7);
03541    }
03542 #endif /* HAVE_SS7 */
03543 #ifdef HAVE_OPENR2
03544    if (p->mfcr2) {
03545       openr2_calling_party_category_t chancat;
03546       int callres = 0;
03547       char *c, *l;
03548 
03549       c = strchr(dest, '/');
03550       if (c) {
03551          c++;
03552       } else {
03553          c = "";
03554       }
03555       if (!p->hidecallerid) {
03556          l = ast->cid.cid_num;
03557       } else {
03558          l = NULL;
03559       }
03560       if (strlen(c) < p->stripmsd) {
03561          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03562          ast_mutex_unlock(&p->lock);
03563          return -1;
03564       }
03565       p->dialing = 1;
03566       ast_channel_lock(ast);
03567       chancat = dahdi_r2_get_channel_category(ast);
03568       ast_channel_unlock(ast);
03569       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03570       if (-1 == callres) {
03571          ast_mutex_unlock(&p->lock);
03572          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03573          return -1;
03574       }
03575       ast_setstate(ast, AST_STATE_DIALING);
03576    }
03577 #endif /* HAVE_OPENR2 */
03578 #ifdef HAVE_PRI
03579    if (p->pri) {
03580       struct pri_sr *sr;
03581 #ifdef SUPPORT_USERUSER
03582       const char *useruser;
03583 #endif
03584       int pridialplan;
03585       int dp_strip;
03586       int prilocaldialplan;
03587       int ldp_strip;
03588       int exclusive;
03589       const char *rr_str;
03590       int redirect_reason;
03591 
03592       c = strchr(dest, '/');
03593       if (c) {
03594          c++;
03595       } else {
03596          c = "";
03597       }
03598 
03599       l = NULL;
03600       n = NULL;
03601       if (!p->hidecallerid) {
03602          l = ast->cid.cid_num;
03603          if (!p->hidecalleridname) {
03604             n = ast->cid.cid_name;
03605          }
03606       }
03607 
03608       if (strlen(c) < p->stripmsd) {
03609          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03610          ast_mutex_unlock(&p->lock);
03611          return -1;
03612       }
03613       if (mysig != SIG_FXSKS) {
03614          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03615          s = strchr(c + p->stripmsd, 'w');
03616          if (s) {
03617             if (strlen(s) > 1)
03618                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03619             else
03620                p->dop.dialstr[0] = '\0';
03621             *s = '\0';
03622          } else {
03623             p->dop.dialstr[0] = '\0';
03624          }
03625       }
03626       if (pri_grab(p, p->pri)) {
03627          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03628          ast_mutex_unlock(&p->lock);
03629          return -1;
03630       }
03631       if (!(p->call = pri_new_call(p->pri->pri))) {
03632          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03633          pri_rel(p->pri);
03634          ast_mutex_unlock(&p->lock);
03635          return -1;
03636       }
03637       if (!(sr = pri_sr_new())) {
03638          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03639          pri_rel(p->pri);
03640          ast_mutex_unlock(&p->lock);
03641       }
03642       if (p->bearer || (mysig == SIG_FXSKS)) {
03643          if (p->bearer) {
03644             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03645             p->bearer->call = p->call;
03646          } else
03647             ast_debug(1, "I'm being setup with no bearer right now...\n");
03648 
03649          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03650       }
03651       p->digital = IS_DIGITAL(ast->transfercapability);
03652 
03653       /* Should the picked channel be used exclusively? */
03654       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03655          exclusive = 1;
03656       } else {
03657          exclusive = 0;
03658       }
03659 
03660       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03661       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03662          (p->digital ? -1 :
03663             ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03664       if (p->pri->facilityenable)
03665          pri_facility_enable(p->pri->pri);
03666 
03667       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03668 
03669       dp_strip = 0;
03670       pridialplan = p->pri->dialplan - 1;
03671       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
03672          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03673             if (pridialplan == -2) {
03674                dp_strip = strlen(p->pri->internationalprefix);
03675             }
03676             pridialplan = PRI_INTERNATIONAL_ISDN;
03677          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03678             if (pridialplan == -2) {
03679                dp_strip = strlen(p->pri->nationalprefix);
03680             }
03681             pridialplan = PRI_NATIONAL_ISDN;
03682          } else {
03683             pridialplan = PRI_LOCAL_ISDN;
03684          }
03685       }
03686       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03687          switch (c[p->stripmsd]) {
03688          case 'U':
03689             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03690             break;
03691          case 'I':
03692             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03693             break;
03694          case 'N':
03695             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03696             break;
03697          case 'L':
03698             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03699             break;
03700          case 'S':
03701             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03702             break;
03703          case 'V':
03704             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03705             break;
03706          case 'R':
03707             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03708             break;
03709          case 'u':
03710             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03711             break;
03712          case 'e':
03713             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03714             break;
03715          case 'x':
03716             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03717             break;
03718          case 'f':
03719             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03720             break;
03721          case 'n':
03722             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03723             break;
03724          case 'p':
03725             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03726             break;
03727          case 'r':
03728             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03729             break;
03730          default:
03731             if (isalpha(c[p->stripmsd])) {
03732                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03733                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03734             }
03735             break;
03736          }
03737          c++;
03738       }
03739       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03740 
03741       ldp_strip = 0;
03742       prilocaldialplan = p->pri->localdialplan - 1;
03743       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03744          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03745             if (prilocaldialplan == -2) {
03746                ldp_strip = strlen(p->pri->internationalprefix);
03747             }
03748             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03749          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03750             if (prilocaldialplan == -2) {
03751                ldp_strip = strlen(p->pri->nationalprefix);
03752             }
03753             prilocaldialplan = PRI_NATIONAL_ISDN;
03754          } else {
03755             prilocaldialplan = PRI_LOCAL_ISDN;
03756          }
03757       }
03758       if (l != NULL) {
03759          while (*l > '9' && *l != '*' && *l != '#') {
03760             switch (*l) {
03761             case 'U':
03762                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03763                break;
03764             case 'I':
03765                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03766                break;
03767             case 'N':
03768                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03769                break;
03770             case 'L':
03771                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03772                break;
03773             case 'S':
03774                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03775                break;
03776             case 'V':
03777                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03778                break;
03779             case 'R':
03780                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03781                break;
03782             case 'u':
03783                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03784                break;
03785             case 'e':
03786                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03787                break;
03788             case 'x':
03789                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03790                break;
03791             case 'f':
03792                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03793                break;
03794             case 'n':
03795                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03796                break;
03797             case 'p':
03798                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03799                break;
03800             case 'r':
03801                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03802                break;
03803             default:
03804                if (isalpha(*l)) {
03805                   ast_log(LOG_WARNING,
03806                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03807                      *l > 'Z' ? "NPI" : "TON", *l);
03808                }
03809                break;
03810             }
03811             l++;
03812          }
03813       }
03814       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03815          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03816       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03817          if (!strcasecmp(rr_str, "UNKNOWN"))
03818             redirect_reason = 0;
03819          else if (!strcasecmp(rr_str, "BUSY"))
03820             redirect_reason = 1;
03821          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03822          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03823             redirect_reason = 2;
03824          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03825             redirect_reason = 15;
03826          else
03827             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03828       } else
03829          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03830       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03831 
03832 #ifdef SUPPORT_USERUSER
03833       /* User-user info */
03834       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03835       if (useruser)
03836          pri_sr_set_useruser(sr, useruser);
03837 #endif
03838 
03839       if (pri_setup(p->pri->pri, p->call, sr)) {
03840          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03841             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03842          pri_rel(p->pri);
03843          ast_mutex_unlock(&p->lock);
03844          pri_sr_free(sr);
03845          return -1;
03846       }
03847       pri_sr_free(sr);
03848       ast_setstate(ast, AST_STATE_DIALING);
03849       pri_rel(p->pri);
03850    }
03851 #endif
03852    ast_mutex_unlock(&p->lock);
03853    return 0;
03854 }
03855 
03856 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03857 {
03858    struct dahdi_pvt *p = *pvt;
03859    /* Remove channel from the list */
03860    if (p->prev)
03861       p->prev->next = p->next;
03862    if (p->next)
03863       p->next->prev = p->prev;
03864    if (p->use_smdi)
03865       ast_smdi_interface_unref(p->smdi_iface);
03866    if (p->mwi_event_sub)
03867       ast_event_unsubscribe(p->mwi_event_sub);
03868    if (p->vars) {
03869       ast_variables_destroy(p->vars);
03870    }
03871    ast_mutex_destroy(&p->lock);
03872    dahdi_close_sub(p, SUB_REAL);
03873    if (p->owner)
03874       p->owner->tech_pvt = NULL;
03875    free(p);
03876    *pvt = NULL;
03877 }
03878 
03879 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03880 {
03881    int owned = 0;
03882    int i = 0;
03883 
03884    if (!now) {
03885       if (cur->owner) {
03886          owned = 1;
03887       }
03888 
03889       for (i = 0; i < 3; i++) {
03890          if (cur->subs[i].owner) {
03891             owned = 1;
03892          }
03893       }
03894       if (!owned) {
03895          if (prev) {
03896             prev->next = cur->next;
03897             if (prev->next)
03898                prev->next->prev = prev;
03899             else
03900                ifend = prev;
03901          } else {
03902             iflist = cur->next;
03903             if (iflist)
03904                iflist->prev = NULL;
03905             else
03906                ifend = NULL;
03907          }
03908          destroy_dahdi_pvt(&cur);
03909       }
03910    } else {
03911       if (prev) {
03912          prev->next = cur->next;
03913          if (prev->next)
03914             prev->next->prev = prev;
03915          else
03916             ifend = prev;
03917       } else {
03918          iflist = cur->next;
03919          if (iflist)
03920             iflist->prev = NULL;
03921          else
03922             ifend = NULL;
03923       }
03924       destroy_dahdi_pvt(&cur);
03925    }
03926    return 0;
03927 }
03928 
03929 static void destroy_all_channels(void)
03930 {
03931    int x;
03932    struct dahdi_pvt *p, *pl;
03933 
03934    while (num_restart_pending) {
03935       usleep(1);
03936    }
03937 
03938    ast_mutex_lock(&iflock);
03939    /* Destroy all the interfaces and free their memory */
03940    p = iflist;
03941    while (p) {
03942       /* Free any callerid */
03943       if (p->cidspill)
03944          ast_free(p->cidspill);
03945       pl = p;
03946       p = p->next;
03947       x = pl->channel;
03948       /* Free associated memory */
03949       if (pl)
03950          destroy_dahdi_pvt(&pl);
03951       if (option_verbose > 2)
03952          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03953    }
03954    iflist = NULL;
03955    ifcount = 0;
03956    ast_mutex_unlock(&iflock);
03957 }
03958 
03959 #if defined(HAVE_PRI)
03960 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03961 
03962 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03963 {
03964    /* Data will be our digit string */
03965    struct dahdi_pvt *p;
03966    char *digits = (char *) data;
03967 
03968    if (ast_strlen_zero(digits)) {
03969       ast_debug(1, "No digit string sent to application!\n");
03970       return -1;
03971    }
03972 
03973    p = (struct dahdi_pvt *)chan->tech_pvt;
03974 
03975    if (!p) {
03976       ast_debug(1, "Unable to find technology private\n");
03977       return -1;
03978    }
03979 
03980    ast_mutex_lock(&p->lock);
03981 
03982    if (!p->pri || !p->call) {
03983       ast_debug(1, "Unable to find pri or call on channel!\n");
03984       ast_mutex_unlock(&p->lock);
03985       return -1;
03986    }
03987 
03988    if (!pri_grab(p, p->pri)) {
03989       pri_keypad_facility(p->pri->pri, p->call, digits);
03990       pri_rel(p->pri);
03991    } else {
03992       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03993       ast_mutex_unlock(&p->lock);
03994       return -1;
03995    }
03996 
03997    ast_mutex_unlock(&p->lock);
03998 
03999    return 0;
04000 }
04001 #endif   /* defined(HAVE_PRI) */
04002 
04003 #if defined(HAVE_PRI)
04004 #if defined(HAVE_PRI_PROG_W_CAUSE)
04005 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04006 
04007 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04008 {
04009    /* Data will be our digit string */
04010    struct dahdi_pvt *p;
04011    char *parse;
04012    int res = -1;
04013    AST_DECLARE_APP_ARGS(args,
04014       AST_APP_ARG(destination);
04015       AST_APP_ARG(original);
04016       AST_APP_ARG(reason);
04017    );
04018 
04019    if (ast_strlen_zero(data)) {
04020       ast_log(LOG_DEBUG, "No data sent to application!\n");
04021       return -1;
04022    }
04023 
04024    p = (struct dahdi_pvt *)chan->tech_pvt;
04025 
04026    if (!p) {
04027       ast_log(LOG_DEBUG, "Unable to find technology private\n");
04028       return -1;
04029    }
04030 
04031    parse = ast_strdupa(data);
04032    AST_STANDARD_APP_ARGS(args, parse);
04033 
04034    if (ast_strlen_zero(args.destination)) {
04035       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04036       return -1;
04037    }
04038 
04039    if (ast_strlen_zero(args.original)) {
04040       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04041       args.original = NULL;
04042    }
04043 
04044    if (ast_strlen_zero(args.reason)) {
04045       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04046       args.reason = NULL;
04047    }
04048 
04049    ast_mutex_lock(&p->lock);
04050 
04051    if (!p->pri || !p->call) {
04052       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04053       ast_mutex_unlock(&p->lock);
04054       return -1;
04055    }
04056 
04057    switch (p->sig) {
04058    case SIG_PRI:
04059       if (!pri_grab(p, p->pri)) {
04060          if (chan->_state == AST_STATE_RING) {
04061             res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04062          }
04063          pri_rel(p->pri);
04064       } else {
04065          ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04066          ast_mutex_unlock(&p->lock);
04067          return -1;
04068       }
04069       break;
04070    }
04071 
04072    ast_mutex_unlock(&p->lock);
04073 
04074    return res;
04075 }
04076 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
04077 #endif   /* defined(HAVE_PRI) */
04078 
04079 #if defined(HAVE_PRI)
04080 static int pri_is_up(struct dahdi_pri *pri)
04081 {
04082    int x;
04083    for (x = 0; x < NUM_DCHANS; x++) {
04084       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04085          return 1;
04086    }
04087    return 0;
04088 }
04089 #endif   /* defined(HAVE_PRI) */
04090 
04091 #if defined(HAVE_PRI)
04092 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04093 {
04094    bearer->owner = &inuse;
04095    bearer->realcall = crv;
04096    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04097    if (crv->subs[SUB_REAL].owner)
04098       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04099    crv->bearer = bearer;
04100    crv->call = bearer->call;
04101    crv->pri = pri;
04102    return 0;
04103 }
04104 #endif   /* defined(HAVE_PRI) */
04105 
04106 #if defined(HAVE_PRI)
04107 static char *pri_order(int level)
04108 {
04109    switch (level) {
04110    case 0:
04111       return "Primary";
04112    case 1:
04113       return "Secondary";
04114    case 2:
04115       return "Tertiary";
04116    case 3:
04117       return "Quaternary";
04118    default:
04119       return "<Unknown>";
04120    }
04121 }
04122 #endif   /* defined(HAVE_PRI) */
04123 
04124 #if defined(HAVE_PRI)
04125 /* Returns fd of the active dchan */
04126 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04127 {
04128    int x = -1;
04129 
04130    for (x = 0; x < NUM_DCHANS; x++) {
04131       if ((pri->dchans[x] == pri->pri))
04132          break;
04133    }
04134 
04135    return pri->fds[x];
04136 }
04137 #endif   /* defined(HAVE_PRI) */
04138 
04139 #if defined(HAVE_PRI)
04140 static int pri_find_dchan(struct dahdi_pri *pri)
04141 {
04142    int oldslot = -1;
04143    struct pri *old;
04144    int newslot = -1;
04145    int x;
04146    old = pri->pri;
04147    for (x = 0; x < NUM_DCHANS; x++) {
04148       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04149          newslot = x;
04150       if (pri->dchans[x] == old) {
04151          oldslot = x;
04152       }
04153    }
04154    if (newslot < 0) {
04155       newslot = 0;
04156       /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
04157       if (pri->sig != SIG_BRI_PTMP) {
04158          ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
04159             pri->dchannels[newslot]);
04160       }
04161    }
04162    if (old && (oldslot != newslot))
04163       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04164          pri->dchannels[oldslot], pri->dchannels[newslot]);
04165    pri->pri = pri->dchans[newslot];
04166    return 0;
04167 }
04168 #endif   /* defined(HAVE_PRI) */
04169 
04170 #if defined(HAVE_OPENR2)
04171 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04172 
04173 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04174 {
04175    /* data is whether to accept with charge or no charge */
04176    openr2_call_mode_t accept_mode;
04177    int res, timeout, maxloops;
04178    struct ast_frame *f;
04179    struct dahdi_pvt *p;
04180    char *parse;
04181    AST_DECLARE_APP_ARGS(args,
04182          AST_APP_ARG(charge);
04183    );
04184 
04185    if (ast_strlen_zero(data)) {
04186       ast_log(LOG_DEBUG, "No data sent to application!\n");
04187       return -1;
04188    }
04189 
04190    if (chan->tech != &dahdi_tech) {
04191       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04192       return -1;
04193    }
04194 
04195    p = (struct dahdi_pvt *)chan->tech_pvt;
04196    if (!p) {
04197       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04198       return -1;
04199    }
04200 
04201    parse = ast_strdupa(data);
04202    AST_STANDARD_APP_ARGS(args, parse);
04203 
04204    if (ast_strlen_zero(args.charge)) {
04205       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04206       return -1;
04207    }
04208 
04209    ast_mutex_lock(&p->lock);
04210    if (!p->mfcr2 || !p->mfcr2call) {
04211       ast_mutex_unlock(&p->lock);
04212       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04213       return -1;
04214    }
04215 
04216    if (p->mfcr2_call_accepted) {
04217       ast_mutex_unlock(&p->lock);
04218       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04219       return 0;
04220    }
04221    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04222    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04223       ast_mutex_unlock(&p->lock);
04224       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04225       return -1;
04226    }
04227    ast_mutex_unlock(&p->lock);
04228 
04229    res = 0;
04230    timeout = 100;
04231    maxloops = 50; /* wait up to 5 seconds */
04232    /* we need to read() until the call is accepted */
04233    while (maxloops > 0) {
04234       maxloops--;
04235       if (ast_check_hangup(chan)) {
04236          break;
04237       }
04238       res = ast_waitfor(chan, timeout);
04239       if (res < 0) {
04240          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04241          res = -1;
04242          break;
04243       }
04244       if (res == 0) {
04245          continue;
04246       }
04247       f = ast_read(chan);
04248       if (!f) {
04249          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04250          res = -1;
04251          break;
04252       }
04253       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04254          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04255          ast_frfree(f);
04256          res = -1;
04257          break;
04258       }
04259       ast_frfree(f);
04260       ast_mutex_lock(&p->lock);
04261       if (p->mfcr2_call_accepted) {
04262          ast_mutex_unlock(&p->lock);
04263          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04264          break;
04265       }
04266       ast_mutex_unlock(&p->lock);
04267    }
04268    if (res == -1) {
04269       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04270    }
04271    return res;
04272 }
04273 
04274 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04275 {
04276    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04277    switch (cause) {
04278    case AST_CAUSE_USER_BUSY:
04279    case AST_CAUSE_CALL_REJECTED:
04280    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
04281       r2cause = OR2_CAUSE_BUSY_NUMBER;
04282       break;
04283 
04284    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04285    case AST_CAUSE_SWITCH_CONGESTION:
04286       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04287       break;
04288 
04289    case AST_CAUSE_UNALLOCATED:
04290       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04291       break;
04292 
04293    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04294    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04295       r2cause = OR2_CAUSE_OUT_OF_ORDER;
04296       break;
04297 
04298    case AST_CAUSE_NO_ANSWER:
04299    case AST_CAUSE_NO_USER_RESPONSE:
04300       r2cause = OR2_CAUSE_NO_ANSWER;
04301       break;
04302 
04303    default:
04304       r2cause = OR2_CAUSE_NORMAL_CLEARING;
04305       break;
04306    }
04307    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04308          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04309    return r2cause;
04310 }
04311 #endif
04312 
04313 static int dahdi_hangup(struct ast_channel *ast)
04314 {
04315    int res;
04316    int idx,x, law;
04317    /*static int restore_gains(struct dahdi_pvt *p);*/
04318    struct dahdi_pvt *p = ast->tech_pvt;
04319    struct dahdi_pvt *tmp = NULL;
04320    struct dahdi_pvt *prev = NULL;
04321    struct dahdi_params par;
04322 
04323    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04324    if (!ast->tech_pvt) {
04325       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04326       return 0;
04327    }
04328 
04329    ast_mutex_lock(&p->lock);
04330 
04331    idx = dahdi_get_index(ast, p, 1);
04332 
04333    switch (p->sig) {
04334    case SIG_PRI:
04335    case SIG_BRI:
04336    case SIG_BRI_PTMP:
04337    case SIG_SS7:
04338       x = 1;
04339       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04340       /* Fall through */
04341    case SIG_MFCR2:
04342       p->cid_num[0] = '\0';
04343       p->cid_name[0] = '\0';
04344       break;
04345    default:
04346       break;
04347    }
04348 
04349    x = 0;
04350    dahdi_confmute(p, 0);
04351    p->muting = 0;
04352    restore_gains(p);
04353    if (p->origcid_num) {
04354       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04355       ast_free(p->origcid_num);
04356       p->origcid_num = NULL;
04357    }
04358    if (p->origcid_name) {
04359       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04360       ast_free(p->origcid_name);
04361       p->origcid_name = NULL;
04362    }
04363    if (p->dsp)
04364       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04365    p->exten[0] = '\0';
04366 
04367    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04368       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04369    p->ignoredtmf = 0;
04370 
04371    if (idx > -1) {
04372       /* Real channel, do some fixup */
04373       p->subs[idx].owner = NULL;
04374       p->subs[idx].needanswer = 0;
04375       p->subs[idx].needflash = 0;
04376       p->subs[idx].needringing = 0;
04377       p->subs[idx].needbusy = 0;
04378       p->subs[idx].needcongestion = 0;
04379       p->subs[idx].linear = 0;
04380       p->subs[idx].needcallerid = 0;
04381       p->polarity = POLARITY_IDLE;
04382       dahdi_setlinear(p->subs[idx].dfd, 0);
04383       if (idx == SUB_REAL) {
04384          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04385             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04386             if (p->subs[SUB_CALLWAIT].inthreeway) {
04387                /* We had flipped over to answer a callwait and now it's gone */
04388                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04389                /* Move to the call-wait, but un-own us until they flip back. */
04390                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04391                unalloc_sub(p, SUB_CALLWAIT);
04392                p->owner = NULL;
04393             } else {
04394                /* The three way hung up, but we still have a call wait */
04395                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
04396                swap_subs(p, SUB_THREEWAY, SUB_REAL);
04397                unalloc_sub(p, SUB_THREEWAY);
04398                if (p->subs[SUB_REAL].inthreeway) {
04399                   /* This was part of a three way call.  Immediately make way for
04400                      another call */
04401                   ast_debug(1, "Call was complete, setting owner to former third call\n");
04402                   p->owner = p->subs[SUB_REAL].owner;
04403                } else {
04404                   /* This call hasn't been completed yet...  Set owner to NULL */
04405                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04406                   p->owner = NULL;
04407                }
04408                p->subs[SUB_REAL].inthreeway = 0;
04409             }
04410          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04411             /* Move to the call-wait and switch back to them. */
04412             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04413             unalloc_sub(p, SUB_CALLWAIT);
04414             p->owner = p->subs[SUB_REAL].owner;
04415             if (p->owner->_state != AST_STATE_UP)
04416                p->subs[SUB_REAL].needanswer = 1;
04417             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04418                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04419          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04420             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04421             unalloc_sub(p, SUB_THREEWAY);
04422             if (p->subs[SUB_REAL].inthreeway) {
04423                /* This was part of a three way call.  Immediately make way for
04424                   another call */
04425                ast_debug(1, "Call was complete, setting owner to former third call\n");
04426                p->owner = p->subs[SUB_REAL].owner;
04427             } else {
04428                /* This call hasn't been completed yet...  Set owner to NULL */
04429                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04430                p->owner = NULL;
04431             }
04432             p->subs[SUB_REAL].inthreeway = 0;
04433          }
04434       } else if (idx == SUB_CALLWAIT) {
04435          /* Ditch the holding callwait call, and immediately make it availabe */
04436          if (p->subs[SUB_CALLWAIT].inthreeway) {
04437             /* This is actually part of a three way, placed on hold.  Place the third part
04438                on music on hold now */
04439             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04440                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04441                   S_OR(p->mohsuggest, NULL),
04442                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04443             }
04444             p->subs[SUB_THREEWAY].inthreeway = 0;
04445             /* Make it the call wait now */
04446             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04447             unalloc_sub(p, SUB_THREEWAY);
04448          } else
04449             unalloc_sub(p, SUB_CALLWAIT);
04450       } else if (idx == SUB_THREEWAY) {
04451          if (p->subs[SUB_CALLWAIT].inthreeway) {
04452             /* The other party of the three way call is currently in a call-wait state.
04453                Start music on hold for them, and take the main guy out of the third call */
04454             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04455                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04456                   S_OR(p->mohsuggest, NULL),
04457                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04458             }
04459             p->subs[SUB_CALLWAIT].inthreeway = 0;
04460          }
04461          p->subs[SUB_REAL].inthreeway = 0;
04462          /* If this was part of a three way call index, let us make
04463             another three way call */
04464          unalloc_sub(p, SUB_THREEWAY);
04465       } else {
04466          /* This wasn't any sort of call, but how are we an index? */
04467          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04468       }
04469    }
04470 
04471    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04472       p->owner = NULL;
04473       p->ringt = 0;
04474       p->distinctivering = 0;
04475       p->confirmanswer = 0;
04476       p->cidrings = 1;
04477       p->outgoing = 0;
04478       p->digital = 0;
04479       p->faxhandled = 0;
04480       p->pulsedial = 0;
04481       p->onhooktime = time(NULL);
04482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04483       p->proceeding = 0;
04484       p->dialing = 0;
04485       p->progress = 0;
04486       p->alerting = 0;
04487       p->setup_ack = 0;
04488       p->rlt = 0;
04489 #endif
04490       if (p->dsp) {
04491          ast_dsp_free(p->dsp);
04492          p->dsp = NULL;
04493       }
04494 
04495       if (p->faxbuffersinuse) {
04496          /* faxbuffers are in use, revert them */
04497          struct dahdi_bufferinfo bi = {
04498             .txbufpolicy = p->buf_policy,
04499             .rxbufpolicy = p->buf_policy,
04500             .bufsize = p->bufsize,
04501             .numbufs = p->buf_no
04502          };
04503          int bpres;
04504 
04505          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04506             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04507          }
04508          p->faxbuffersinuse = 0;
04509       }
04510 
04511       law = DAHDI_LAW_DEFAULT;
04512       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04513       if (res < 0)
04514          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04515       /* Perform low level hangup if no owner left */
04516 #ifdef HAVE_SS7
04517       if (p->ss7) {
04518          if (p->ss7call) {
04519             if (!ss7_grab(p, p->ss7)) {
04520                if (!p->alreadyhungup) {
04521                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04522                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04523 
04524                   if (cause) {
04525                      if (atoi(cause))
04526                         icause = atoi(cause);
04527                   }
04528                   isup_rel(p->ss7->ss7, p->ss7call, icause);
04529                   ss7_rel(p->ss7);
04530                   p->alreadyhungup = 1;
04531                } else
04532                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04533             } else {
04534                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04535                res = -1;
04536             }
04537          }
04538       }
04539 #endif
04540 #ifdef HAVE_OPENR2
04541       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04542          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04543          /* If it's an incoming call, check the mfcr2_forced_release setting */
04544          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04545             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04546          } else {
04547             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04548             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04549             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04550                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04551             dahdi_r2_disconnect_call(p, r2cause);
04552          }
04553       } else if (p->mfcr2call) {
04554          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04555          /* since ast_request() was called but not ast_call() we have not yet dialed
04556          and the openr2 stack will not call on_call_end callback, we need to unset
04557          the mfcr2call flag and bump the monitor count so the monitor thread can take
04558          care of this channel events from now on */
04559          p->mfcr2call = 0;
04560       }
04561 #endif
04562 #ifdef HAVE_PRI
04563       if (p->pri) {
04564 #ifdef SUPPORT_USERUSER
04565          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04566 #endif
04567 
04568          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
04569          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04570             if (!pri_grab(p, p->pri)) {
04571                if (p->alreadyhungup) {
04572                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
04573 
04574 #ifdef SUPPORT_USERUSER
04575                   pri_call_set_useruser(p->call, useruser);
04576 #endif
04577 
04578                   pri_hangup(p->pri->pri, p->call, -1);
04579                   p->call = NULL;
04580                   if (p->bearer)
04581                      p->bearer->call = NULL;
04582                } else {
04583                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04584                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04585                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
04586 
04587 #ifdef SUPPORT_USERUSER
04588                   pri_call_set_useruser(p->call, useruser);
04589 #endif
04590 
04591                   p->alreadyhungup = 1;
04592                   if (p->bearer)
04593                      p->bearer->alreadyhungup = 1;
04594                   if (cause) {
04595                      if (atoi(cause))
04596                         icause = atoi(cause);
04597                   }
04598                   pri_hangup(p->pri->pri, p->call, icause);
04599                }
04600                if (res < 0)
04601                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
04602                pri_rel(p->pri);
04603             } else {
04604                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04605                res = -1;
04606             }
04607          } else {
04608             if (p->bearer)
04609                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04610             p->call = NULL;
04611             res = 0;
04612          }
04613       }
04614 #endif
04615       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04616          && (p->sig != SIG_BRI)
04617          && (p->sig != SIG_BRI_PTMP))
04618          && (p->sig != SIG_MFCR2))
04619          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04620       if (res < 0) {
04621          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04622       }
04623       switch (p->sig) {
04624       case SIG_FXOGS:
04625       case SIG_FXOLS:
04626       case SIG_FXOKS:
04627          memset(&par, 0, sizeof(par));
04628          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04629          if (!res) {
04630 #if 0
04631             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04632 #endif
04633             /* If they're off hook, try playing congestion */
04634             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04635                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04636             else
04637                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04638             p->fxsoffhookstate = par.rxisoffhook;
04639          }
04640          break;
04641       case SIG_FXSGS:
04642       case SIG_FXSLS:
04643       case SIG_FXSKS:
04644          /* Make sure we're not made available for at least two seconds assuming
04645             we were actually used for an inbound or outbound call. */
04646          if (ast->_state != AST_STATE_RESERVED) {
04647             time(&p->guardtime);
04648             p->guardtime += 2;
04649          }
04650          break;
04651       default:
04652          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04653       }
04654       if (p->cidspill)
04655          ast_free(p->cidspill);
04656       if (p->sig)
04657          dahdi_disable_ec(p);
04658       x = 0;
04659       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04660       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04661       p->didtdd = 0;
04662       p->cidspill = NULL;
04663       p->callwaitcas = 0;
04664       p->callwaiting = p->permcallwaiting;
04665       p->hidecallerid = p->permhidecallerid;
04666       p->waitingfordt.tv_sec = 0;
04667       p->dialing = 0;
04668       p->rdnis[0] = '\0';
04669       update_conf(p);
04670       reset_conf(p);
04671       /* Restore data mode */
04672       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04673          x = 0;
04674          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04675       }
04676 #ifdef HAVE_PRI
04677       if (p->bearer) {
04678          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04679          /* Free up the bearer channel as well, and
04680             don't use its file descriptor anymore */
04681          update_conf(p->bearer);
04682          reset_conf(p->bearer);
04683          p->bearer->owner = NULL;
04684          p->bearer->realcall = NULL;
04685          p->bearer = NULL;
04686          p->subs[SUB_REAL].dfd = -1;
04687          p->pri = NULL;
04688       }
04689 #endif
04690       if (num_restart_pending == 0)
04691          restart_monitor();
04692    }
04693 
04694    p->callwaitingrepeat = 0;
04695    p->cidcwexpire = 0;
04696    p->oprmode = 0;
04697    ast->tech_pvt = NULL;
04698    ast_mutex_unlock(&p->lock);
04699    ast_module_unref(ast_module_info->self);
04700    ast_verb(3, "Hungup '%s'\n", ast->name);
04701 
04702    ast_mutex_lock(&iflock);
04703 
04704    if (p->restartpending) {
04705       num_restart_pending--;
04706    }
04707 
04708    tmp = iflist;
04709    prev = NULL;
04710    if (p->destroy) {
04711       while (tmp) {
04712          if (tmp == p) {
04713             destroy_channel(prev, tmp, 0);
04714             break;
04715          } else {
04716             prev = tmp;
04717             tmp = tmp->next;
04718          }
04719       }
04720    }
04721    ast_mutex_unlock(&iflock);
04722    return 0;
04723 }
04724 
04725 static int dahdi_answer(struct ast_channel *ast)
04726 {
04727    struct dahdi_pvt *p = ast->tech_pvt;
04728    int res = 0;
04729    int idx;
04730    int oldstate = ast->_state;
04731    ast_setstate(ast, AST_STATE_UP);
04732    ast_mutex_lock(&p->lock);
04733    idx = dahdi_get_index(ast, p, 0);
04734    if (idx < 0)
04735       idx = SUB_REAL;
04736    /* nothing to do if a radio channel */
04737    if ((p->radio || (p->oprmode < 0))) {
04738       ast_mutex_unlock(&p->lock);
04739       return 0;
04740    }
04741    switch (p->sig) {
04742    case SIG_FXSLS:
04743    case SIG_FXSGS:
04744    case SIG_FXSKS:
04745       p->ringt = 0;
04746       /* Fall through */
04747    case SIG_EM:
04748    case SIG_EM_E1:
04749    case SIG_EMWINK:
04750    case SIG_FEATD:
04751    case SIG_FEATDMF:
04752    case SIG_FEATDMF_TA:
04753    case SIG_E911:
04754    case SIG_FGC_CAMA:
04755    case SIG_FGC_CAMAMF:
04756    case SIG_FEATB:
04757    case SIG_SF:
04758    case SIG_SFWINK:
04759    case SIG_SF_FEATD:
04760    case SIG_SF_FEATDMF:
04761    case SIG_SF_FEATB:
04762    case SIG_FXOLS:
04763    case SIG_FXOGS:
04764    case SIG_FXOKS:
04765       /* Pick up the line */
04766       ast_debug(1, "Took %s off hook\n", ast->name);
04767       if (p->hanguponpolarityswitch) {
04768          p->polaritydelaytv = ast_tvnow();
04769       }
04770       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04771       tone_zone_play_tone(p->subs[idx].dfd, -1);
04772       p->dialing = 0;
04773       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04774          if (oldstate == AST_STATE_RINGING) {
04775             ast_debug(1, "Finally swapping real and threeway\n");
04776             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04777             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04778             p->owner = p->subs[SUB_REAL].owner;
04779          }
04780       }
04781       if (p->sig & __DAHDI_SIG_FXS) {
04782          dahdi_enable_ec(p);
04783          dahdi_train_ec(p);
04784       }
04785       break;
04786 #ifdef HAVE_PRI
04787    case SIG_BRI:
04788    case SIG_BRI_PTMP:
04789    case SIG_PRI:
04790       /* Send a pri acknowledge */
04791       if (!pri_grab(p, p->pri)) {
04792          p->proceeding = 1;
04793          p->dialing = 0;
04794          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04795          pri_rel(p->pri);
04796       } else {
04797          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04798          res = -1;
04799       }
04800       break;
04801 #endif
04802 #ifdef HAVE_SS7
04803    case SIG_SS7:
04804       if (!ss7_grab(p, p->ss7)) {
04805          p->proceeding = 1;
04806          res = isup_anm(p->ss7->ss7, p->ss7call);
04807          ss7_rel(p->ss7);
04808       } else {
04809          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04810          res = -1;
04811       }
04812       break;
04813 #endif
04814 #ifdef HAVE_OPENR2
04815    case SIG_MFCR2:
04816       if (!p->mfcr2_call_accepted) {
04817          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
04818             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
04819          p->mfcr2_answer_pending = 1;
04820          if (p->mfcr2_charge_calls) {
04821             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04822             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04823          } else {
04824             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04825             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04826          }
04827       } else {
04828          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04829          dahdi_r2_answer(p);
04830       }
04831       break;
04832 #endif
04833    case 0:
04834       ast_mutex_unlock(&p->lock);
04835       return 0;
04836    default:
04837       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04838       res = -1;
04839    }
04840    ast_mutex_unlock(&p->lock);
04841    return res;
04842 }
04843 
04844 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04845 {
04846    char *cp;
04847    signed char *scp;
04848    int x;
04849    int idx;
04850    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04851    struct oprmode *oprmode;
04852 
04853 
04854    /* all supported options require data */
04855    if (!data || (datalen < 1)) {
04856       errno = EINVAL;
04857       return -1;
04858    }
04859 
04860    switch (option) {
04861    case AST_OPTION_TXGAIN:
04862       scp = (signed char *) data;
04863       idx = dahdi_get_index(chan, p, 0);
04864       if (idx < 0) {
04865          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04866          return -1;
04867       }
04868       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04869       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04870    case AST_OPTION_RXGAIN:
04871       scp = (signed char *) data;
04872       idx = dahdi_get_index(chan, p, 0);
04873       if (idx < 0) {
04874          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04875          return -1;
04876       }
04877       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04878       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04879    case AST_OPTION_TONE_VERIFY:
04880       if (!p->dsp)
04881          break;
04882       cp = (char *) data;
04883       switch (*cp) {
04884       case 1:
04885          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04886          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04887          break;
04888       case 2:
04889          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04890          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04891          break;
04892       default:
04893          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04894          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04895          break;
04896       }
04897       break;
04898    case AST_OPTION_TDD:
04899       /* turn on or off TDD */
04900       cp = (char *) data;
04901       p->mate = 0;
04902       if (!*cp) { /* turn it off */
04903          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04904          if (p->tdd)
04905             tdd_free(p->tdd);
04906          p->tdd = 0;
04907          break;
04908       }
04909       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04910          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04911       dahdi_disable_ec(p);
04912       /* otherwise, turn it on */
04913       if (!p->didtdd) { /* if havent done it yet */
04914          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04915          unsigned char *buf;
04916          int size, res, fd, len;
04917          struct pollfd fds[1];
04918 
04919          buf = mybuf;
04920          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04921          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04922          len = 40000;
04923          idx = dahdi_get_index(chan, p, 0);
04924          if (idx < 0) {
04925             ast_log(LOG_WARNING, "No index in TDD?\n");
04926             return -1;
04927          }
04928          fd = p->subs[idx].dfd;
04929          while (len) {
04930             if (ast_check_hangup(chan))
04931                return -1;
04932             size = len;
04933             if (size > READ_SIZE)
04934                size = READ_SIZE;
04935             fds[0].fd = fd;
04936             fds[0].events = POLLPRI | POLLOUT;
04937             fds[0].revents = 0;
04938             res = poll(fds, 1, -1);
04939             if (!res) {
04940                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04941                continue;
04942             }
04943             /* if got exception */
04944             if (fds[0].revents & POLLPRI)
04945                return -1;
04946             if (!(fds[0].revents & POLLOUT)) {
04947                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04948                continue;
04949             }
04950             res = write(fd, buf, size);
04951             if (res != size) {
04952                if (res == -1) return -1;
04953                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04954                break;
04955             }
04956             len -= size;
04957             buf += size;
04958          }
04959          p->didtdd = 1; /* set to have done it now */
04960       }
04961       if (*cp == 2) { /* Mate mode */
04962          if (p->tdd)
04963             tdd_free(p->tdd);
04964          p->tdd = 0;
04965          p->mate = 1;
04966          break;
04967       }
04968       if (!p->tdd) { /* if we dont have one yet */
04969          p->tdd = tdd_new(); /* allocate one */
04970       }
04971       break;
04972    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04973       if (!p->dsp)
04974          break;
04975       cp = (char *) data;
04976       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04977          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04978       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04979       break;
04980    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04981       cp = (char *) data;
04982       if (!*cp) {
04983          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04984          x = 0;
04985          dahdi_disable_ec(p);
04986       } else {
04987          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04988          x = 1;
04989       }
04990       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04991          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04992       break;
04993    case AST_OPTION_OPRMODE:  /* Operator services mode */
04994       oprmode = (struct oprmode *) data;
04995       /* We don't support operator mode across technologies */
04996       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
04997          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
04998                chan->tech->type, oprmode->peer->tech->type);
04999          errno = EINVAL;
05000          return -1;
05001       }
05002       pp = oprmode->peer->tech_pvt;
05003       p->oprmode = pp->oprmode = 0;
05004       /* setup peers */
05005       p->oprpeer = pp;
05006       pp->oprpeer = p;
05007       /* setup modes, if any */
05008       if (oprmode->mode)
05009       {
05010          pp->oprmode = oprmode->mode;
05011          p->oprmode = -oprmode->mode;
05012       }
05013       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05014          oprmode->mode, chan->name,oprmode->peer->name);
05015       break;
05016    case AST_OPTION_ECHOCAN:
05017       cp = (char *) data;
05018       if (*cp) {
05019          ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
05020          dahdi_enable_ec(p);
05021       } else {
05022          ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
05023          dahdi_disable_ec(p);
05024       }
05025       break;
05026    }
05027    errno = 0;
05028 
05029    return 0;
05030 }
05031 
05032 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05033 {
05034    struct dahdi_pvt *p = chan->tech_pvt;
05035 
05036    if (!strcasecmp(data, "rxgain")) {
05037       ast_mutex_lock(&p->lock);
05038       snprintf(buf, len, "%f", p->rxgain);
05039       ast_mutex_unlock(&p->lock);
05040    } else if (!strcasecmp(data, "txgain")) {
05041       ast_mutex_lock(&p->lock);
05042       snprintf(buf, len, "%f", p->txgain);
05043       ast_mutex_unlock(&p->lock);
05044    } else {
05045       ast_copy_string(buf, "", len);
05046    }
05047    return 0;
05048 }
05049 
05050 
05051 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05052 {
05053    /* Unlink a specific slave or all slaves/masters from a given master */
05054    int x;
05055    int hasslaves;
05056    if (!master)
05057       return;
05058    if (needlock) {
05059       ast_mutex_lock(&master->lock);
05060       if (slave) {
05061          while (ast_mutex_trylock(&slave->lock)) {
05062             DEADLOCK_AVOIDANCE(&master->lock);
05063          }
05064       }
05065    }
05066    hasslaves = 0;
05067    for (x = 0; x < MAX_SLAVES; x++) {
05068       if (master->slaves[x]) {
05069          if (!slave || (master->slaves[x] == slave)) {
05070             /* Take slave out of the conference */
05071             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05072             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05073             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05074             master->slaves[x]->master = NULL;
05075             master->slaves[x] = NULL;
05076          } else
05077             hasslaves = 1;
05078       }
05079       if (!hasslaves)
05080          master->inconference = 0;
05081    }
05082    if (!slave) {
05083       if (master->master) {
05084          /* Take master out of the conference */
05085          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05086          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05087          hasslaves = 0;
05088          for (x = 0; x < MAX_SLAVES; x++) {
05089             if (master->master->slaves[x] == master)
05090                master->master->slaves[x] = NULL;
05091             else if (master->master->slaves[x])
05092                hasslaves = 1;
05093          }
05094          if (!hasslaves)
05095             master->master->inconference = 0;
05096       }
05097       master->master = NULL;
05098    }
05099    update_conf(master);
05100    if (needlock) {
05101       if (slave)
05102          ast_mutex_unlock(&slave->lock);
05103       ast_mutex_unlock(&master->lock);
05104    }
05105 }
05106 
05107 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05108    int x;
05109    if (!slave || !master) {
05110       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05111       return;
05112    }
05113    for (x = 0; x < MAX_SLAVES; x++) {
05114       if (!master->slaves[x]) {
05115          master->slaves[x] = slave;
05116          break;
05117       }
05118    }
05119    if (x >= MAX_SLAVES) {
05120       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05121       master->slaves[MAX_SLAVES - 1] = slave;
05122    }
05123    if (slave->master)
05124       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05125    slave->master = master;
05126 
05127    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05128 }
05129 
05130 static void disable_dtmf_detect(struct dahdi_pvt *p)
05131 {
05132    int val;
05133 
05134    p->ignoredtmf = 1;
05135 
05136    val = 0;
05137    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05138 
05139    if (!p->hardwaredtmf && p->dsp) {
05140       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05141       ast_dsp_set_features(p->dsp, p->dsp_features);
05142    }
05143 }
05144 
05145 static void enable_dtmf_detect(struct dahdi_pvt *p)
05146 {
05147    int val;
05148 
05149    if (p->channel == CHAN_PSEUDO)
05150       return;
05151 
05152    p->ignoredtmf = 0;
05153 
05154    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05155    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05156 
05157    if (!p->hardwaredtmf && p->dsp) {
05158       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05159       ast_dsp_set_features(p->dsp, p->dsp_features);
05160    }
05161 }
05162 
05163 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)
05164 {
05165    struct ast_channel *who;
05166    struct dahdi_pvt *p0, *p1, *op0, *op1;
05167    struct dahdi_pvt *master = NULL, *slave = NULL;
05168    struct ast_frame *f;
05169    int inconf = 0;
05170    int nothingok = 1;
05171    int ofd0, ofd1;
05172    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05173    int os0 = -1, os1 = -1;
05174    int priority = 0;
05175    struct ast_channel *oc0, *oc1;
05176    enum ast_bridge_result res;
05177 
05178 #ifdef PRI_2BCT
05179    int triedtopribridge = 0;
05180 #endif
05181 
05182    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
05183       There is code below to handle it properly until DTMF is actually seen,
05184       but due to currently unresolved issues it's ignored...
05185    */
05186 
05187    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05188       return AST_BRIDGE_FAILED_NOWARN;
05189 
05190    ast_channel_lock(c0);
05191    while (ast_channel_trylock(c1)) {
05192       CHANNEL_DEADLOCK_AVOIDANCE(c0);
05193    }
05194 
05195    p0 = c0->tech_pvt;
05196    p1 = c1->tech_pvt;
05197    /* cant do pseudo-channels here */
05198    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05199       ast_channel_unlock(c0);
05200       ast_channel_unlock(c1);
05201       return AST_BRIDGE_FAILED_NOWARN;
05202    }
05203 
05204    oi0 = dahdi_get_index(c0, p0, 0);
05205    oi1 = dahdi_get_index(c1, p1, 0);
05206    if ((oi0 < 0) || (oi1 < 0)) {
05207       ast_channel_unlock(c0);
05208       ast_channel_unlock(c1);
05209       return AST_BRIDGE_FAILED;
05210    }
05211 
05212    op0 = p0 = c0->tech_pvt;
05213    op1 = p1 = c1->tech_pvt;
05214    ofd0 = c0->fds[0];
05215    ofd1 = c1->fds[0];
05216    oc0 = p0->owner;
05217    oc1 = p1->owner;
05218 
05219    if (ast_mutex_trylock(&p0->lock)) {
05220       /* Don't block, due to potential for deadlock */
05221       ast_channel_unlock(c0);
05222       ast_channel_unlock(c1);
05223       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05224       return AST_BRIDGE_RETRY;
05225    }
05226    if (ast_mutex_trylock(&p1->lock)) {
05227       /* Don't block, due to potential for deadlock */
05228       ast_mutex_unlock(&p0->lock);
05229       ast_channel_unlock(c0);
05230       ast_channel_unlock(c1);
05231       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05232       return AST_BRIDGE_RETRY;
05233    }
05234 
05235    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05236       if (p0->owner && p1->owner) {
05237          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
05238          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05239             master = p0;
05240             slave = p1;
05241             inconf = 1;
05242          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05243             master = p1;
05244             slave = p0;
05245             inconf = 1;
05246          } else {
05247             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
05248             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05249                p0->channel,
05250                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05251                p0->subs[SUB_REAL].inthreeway, p0->channel,
05252                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05253                p1->subs[SUB_REAL].inthreeway);
05254          }
05255          nothingok = 0;
05256       }
05257    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05258       if (p1->subs[SUB_THREEWAY].inthreeway) {
05259          master = p1;
05260          slave = p0;
05261          nothingok = 0;
05262       }
05263    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05264       if (p0->subs[SUB_THREEWAY].inthreeway) {
05265          master = p0;
05266          slave = p1;
05267          nothingok = 0;
05268       }
05269    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05270       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
05271          don't put us in anything */
05272       if (p1->subs[SUB_CALLWAIT].inthreeway) {
05273          master = p1;
05274          slave = p0;
05275          nothingok = 0;
05276       }
05277    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05278       /* Same as previous */
05279       if (p0->subs[SUB_CALLWAIT].inthreeway) {
05280          master = p0;
05281          slave = p1;
05282          nothingok = 0;
05283       }
05284    }
05285    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05286       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05287    if (master && slave) {
05288       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
05289          in an active threeway call with a channel that is ringing, we should
05290          indicate ringing. */
05291       if ((oi1 == SUB_THREEWAY) &&
05292          p1->subs[SUB_THREEWAY].inthreeway &&
05293          p1->subs[SUB_REAL].owner &&
05294          p1->subs[SUB_REAL].inthreeway &&
05295          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05296          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05297          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05298          os1 = p1->subs[SUB_REAL].owner->_state;
05299       } else {
05300          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05301          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05302       }
05303       if ((oi0 == SUB_THREEWAY) &&
05304          p0->subs[SUB_THREEWAY].inthreeway &&
05305          p0->subs[SUB_REAL].owner &&
05306          p0->subs[SUB_REAL].inthreeway &&
05307          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05308          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05309          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05310          os0 = p0->subs[SUB_REAL].owner->_state;
05311       } else {
05312          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05313          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05314       }
05315       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05316          if (!p0->echocanbridged || !p1->echocanbridged) {
05317             /* Disable echo cancellation if appropriate */
05318             dahdi_disable_ec(p0);
05319             dahdi_disable_ec(p1);
05320          }
05321       }
05322       dahdi_link(slave, master);
05323       master->inconference = inconf;
05324    } else if (!nothingok)
05325       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05326 
05327    update_conf(p0);
05328    update_conf(p1);
05329    t0 = p0->subs[SUB_REAL].inthreeway;
05330    t1 = p1->subs[SUB_REAL].inthreeway;
05331 
05332    ast_mutex_unlock(&p0->lock);
05333    ast_mutex_unlock(&p1->lock);
05334 
05335    ast_channel_unlock(c0);
05336    ast_channel_unlock(c1);
05337 
05338    /* Native bridge failed */
05339    if ((!master || !slave) && !nothingok) {
05340       dahdi_enable_ec(p0);
05341       dahdi_enable_ec(p1);
05342       return AST_BRIDGE_FAILED;
05343    }
05344 
05345    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05346 
05347    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05348       disable_dtmf_detect(op0);
05349 
05350    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05351       disable_dtmf_detect(op1);
05352 
05353    for (;;) {
05354       struct ast_channel *c0_priority[2] = {c0, c1};
05355       struct ast_channel *c1_priority[2] = {c1, c0};
05356 
05357       /* Here's our main loop...  Start by locking things, looking for private parts,
05358          and then balking if anything is wrong */
05359 
05360       ast_channel_lock(c0);
05361       while (ast_channel_trylock(c1)) {
05362          CHANNEL_DEADLOCK_AVOIDANCE(c0);
05363       }
05364 
05365       p0 = c0->tech_pvt;
05366       p1 = c1->tech_pvt;
05367 
05368       if (op0 == p0)
05369          i0 = dahdi_get_index(c0, p0, 1);
05370       if (op1 == p1)
05371          i1 = dahdi_get_index(c1, p1, 1);
05372 
05373       ast_channel_unlock(c0);
05374       ast_channel_unlock(c1);
05375 
05376       if (!timeoutms ||
05377          (op0 != p0) ||
05378          (op1 != p1) ||
05379          (ofd0 != c0->fds[0]) ||
05380          (ofd1 != c1->fds[0]) ||
05381          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05382          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05383          (oc0 != p0->owner) ||
05384          (oc1 != p1->owner) ||
05385          (t0 != p0->subs[SUB_REAL].inthreeway) ||
05386          (t1 != p1->subs[SUB_REAL].inthreeway) ||
05387          (oi0 != i0) ||
05388          (oi1 != i1)) {
05389          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05390             op0->channel, oi0, op1->channel, oi1);
05391          res = AST_BRIDGE_RETRY;
05392          goto return_from_bridge;
05393       }
05394 
05395 #ifdef PRI_2BCT
05396       if (!triedtopribridge) {
05397          triedtopribridge = 1;
05398          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05399             ast_mutex_lock(&p0->pri->lock);
05400             if (p0->call && p1->call) {
05401                pri_channel_bridge(p0->call, p1->call);
05402             }
05403             ast_mutex_unlock(&p0->pri->lock);
05404          }
05405       }
05406 #endif
05407 
05408       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05409       if (!who) {
05410          ast_debug(1, "Ooh, empty read...\n");
05411          continue;
05412       }
05413       f = ast_read(who);
05414       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05415          *fo = f;
05416          *rc = who;
05417          res = AST_BRIDGE_COMPLETE;
05418          goto return_from_bridge;
05419       }
05420       if (f->frametype == AST_FRAME_DTMF) {
05421          if ((who == c0) && p0->pulsedial) {
05422             ast_write(c1, f);
05423          } else if ((who == c1) && p1->pulsedial) {
05424             ast_write(c0, f);
05425          } else {
05426             *fo = f;
05427             *rc = who;
05428             res = AST_BRIDGE_COMPLETE;
05429             goto return_from_bridge;
05430          }
05431       }
05432       ast_frfree(f);
05433 
05434       /* Swap who gets priority */
05435       priority = !priority;
05436    }
05437 
05438 return_from_bridge:
05439    if (op0 == p0)
05440       dahdi_enable_ec(p0);
05441 
05442    if (op1 == p1)
05443       dahdi_enable_ec(p1);
05444 
05445    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05446       enable_dtmf_detect(op0);
05447 
05448    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05449       enable_dtmf_detect(op1);
05450 
05451    dahdi_unlink(slave, master, 1);
05452 
05453    return res;
05454 }
05455 
05456 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05457 {
05458    struct dahdi_pvt *p = newchan->tech_pvt;
05459    int x;
05460    ast_mutex_lock(&p->lock);
05461    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05462    if (p->owner == oldchan) {
05463       p->owner = newchan;
05464    }
05465    for (x = 0; x < 3; x++)
05466       if (p->subs[x].owner == oldchan) {
05467          if (!x)
05468             dahdi_unlink(NULL, p, 0);
05469          p->subs[x].owner = newchan;
05470       }
05471    if (newchan->_state == AST_STATE_RINGING)
05472       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05473    update_conf(p);
05474    ast_mutex_unlock(&p->lock);
05475    return 0;
05476 }
05477 
05478 static int dahdi_ring_phone(struct dahdi_pvt *p)
05479 {
05480    int x;
05481    int res;
05482    /* Make sure our transmit state is on hook */
05483    x = 0;
05484    x = DAHDI_ONHOOK;
05485    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05486    do {
05487       x = DAHDI_RING;
05488       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05489       if (res) {
05490          switch (errno) {
05491          case EBUSY:
05492          case EINTR:
05493             /* Wait just in case */
05494             usleep(10000);
05495             continue;
05496          case EINPROGRESS:
05497             res = 0;
05498             break;
05499          default:
05500             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05501             res = 0;
05502          }
05503       }
05504    } while (res);
05505    return res;
05506 }
05507 
05508 static void *ss_thread(void *data);
05509 
05510 static int attempt_transfer(struct dahdi_pvt *p)
05511 {
05512    /* In order to transfer, we need at least one of the channels to
05513       actually be in a call bridge.  We can't conference two applications
05514       together (but then, why would we want to?) */
05515    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05516       /* The three-way person we're about to transfer to could still be in MOH, so
05517          stop if now if appropriate */
05518       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05519          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05520       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05521          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05522       }
05523       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05524          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05525       }
05526        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05527          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05528                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05529          return -1;
05530       }
05531       /* Orphan the channel after releasing the lock */
05532       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05533       unalloc_sub(p, SUB_THREEWAY);
05534    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05535       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05536       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05537          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05538       }
05539       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05540          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05541       }
05542       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05543          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05544                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05545          return -1;
05546       }
05547       /* Three-way is now the REAL */
05548       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05549       ast_channel_unlock(p->subs[SUB_REAL].owner);
05550       unalloc_sub(p, SUB_THREEWAY);
05551       /* Tell the caller not to hangup */
05552       return 1;
05553    } else {
05554       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05555          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05556       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05557       return -1;
05558    }
05559    return 0;
05560 }
05561 
05562 static int check_for_conference(struct dahdi_pvt *p)
05563 {
05564    struct dahdi_confinfo ci;
05565    /* Fine if we already have a master, etc */
05566    if (p->master || (p->confno > -1))
05567       return 0;
05568    memset(&ci, 0, sizeof(ci));
05569    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05570       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05571       return 0;
05572    }
05573    /* If we have no master and don't have a confno, then
05574       if we're in a conference, it's probably a MeetMe room or
05575       some such, so don't let us 3-way out! */
05576    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05577       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05578       return 1;
05579    }
05580    return 0;
05581 }
05582 
05583 /*! Checks channel for alarms
05584  * \param p a channel to check for alarms.
05585  * \returns the alarms on the span to which the channel belongs, or alarms on
05586  *          the channel if no span alarms.
05587  */
05588 static int get_alarms(struct dahdi_pvt *p)
05589 {
05590    int res;
05591    struct dahdi_spaninfo zi;
05592    struct dahdi_params params;
05593 
05594    memset(&zi, 0, sizeof(zi));
05595    zi.spanno = p->span;
05596 
05597    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05598       if (zi.alarms != DAHDI_ALARM_NONE)
05599          return zi.alarms;
05600    } else {
05601       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05602       return 0;
05603    }
05604 
05605    /* No alarms on the span. Check for channel alarms. */
05606    memset(&params, 0, sizeof(params));
05607    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05608       return params.chan_alarms;
05609 
05610    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05611 
05612    return DAHDI_ALARM_NONE;
05613 }
05614 
05615 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
05616 {
05617    struct dahdi_pvt *p = ast->tech_pvt;
05618    struct ast_frame *f = *dest;
05619 
05620    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05621 
05622    if (p->confirmanswer) {
05623       ast_debug(1, "Confirm answer on %s!\n", ast->name);
05624       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05625          of a DTMF digit */
05626       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05627       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05628       *dest = &p->subs[idx].f;
05629       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05630       p->confirmanswer = 0;
05631    } else if (p->callwaitcas) {
05632       if ((f->subclass == 'A') || (f->subclass == 'D')) {
05633          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05634          if (p->cidspill)
05635             ast_free(p->cidspill);
05636          send_cwcidspill(p);
05637       }
05638       p->callwaitcas = 0;
05639       p->subs[idx].f.frametype = AST_FRAME_NULL;
05640       p->subs[idx].f.subclass = 0;
05641       *dest = &p->subs[idx].f;
05642    } else if (f->subclass == 'f') {
05643       /* Fax tone -- Handle and return NULL */
05644       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05645          /* If faxbuffers are configured, use them for the fax transmission */
05646          if (p->usefaxbuffers && !p->faxbuffersinuse) {
05647             struct dahdi_bufferinfo bi = {
05648                .txbufpolicy = p->faxbuf_policy,
05649                .bufsize = p->bufsize,
05650                .numbufs = p->faxbuf_no
05651             };
05652             int res;
05653 
05654             if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05655                ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05656             } else {
05657                p->faxbuffersinuse = 1;
05658             }
05659          }
05660          p->faxhandled = 1;
05661          if (strcmp(ast->exten, "fax")) {
05662             const char *target_context = S_OR(ast->macrocontext, ast->context);
05663 
05664             /* We need to unlock 'ast' here because ast_exists_extension has the
05665              * potential to start autoservice on the channel. Such action is prone
05666              * to deadlock.
05667              */
05668             ast_mutex_unlock(&p->lock);
05669             ast_channel_unlock(ast);
05670             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05671                ast_channel_lock(ast);
05672                ast_mutex_lock(&p->lock);
05673                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05674                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05675                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05676                if (ast_async_goto(ast, target_context, "fax", 1))
05677                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05678             } else {
05679                ast_channel_lock(ast);
05680                ast_mutex_lock(&p->lock);
05681                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05682             }
05683          } else {
05684             ast_debug(1, "Already in a fax extension, not redirecting\n");
05685          }
05686       } else {
05687          ast_debug(1, "Fax already handled\n");
05688       }
05689       dahdi_confmute(p, 0);
05690       p->subs[idx].f.frametype = AST_FRAME_NULL;
05691       p->subs[idx].f.subclass = 0;
05692       *dest = &p->subs[idx].f;
05693    }
05694 }
05695 
05696 static void handle_alarms(struct dahdi_pvt *p, int alms)
05697 {
05698    const char *alarm_str = alarm2str(alms);
05699 
05700    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05701    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05702       "Alarm: %s\r\n"
05703       "Channel: %d\r\n",
05704       alarm_str, p->channel);
05705 }
05706 
05707 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05708 {
05709    int res, x;
05710    int idx, mysig;
05711    char *c;
05712    struct dahdi_pvt *p = ast->tech_pvt;
05713    pthread_t threadid;
05714    struct ast_channel *chan;
05715    struct ast_frame *f;
05716 
05717    idx = dahdi_get_index(ast, p, 0);
05718    mysig = p->sig;
05719    if (p->outsigmod > -1)
05720       mysig = p->outsigmod;
05721    p->subs[idx].f.frametype = AST_FRAME_NULL;
05722    p->subs[idx].f.subclass = 0;
05723    p->subs[idx].f.datalen = 0;
05724    p->subs[idx].f.samples = 0;
05725    p->subs[idx].f.mallocd = 0;
05726    p->subs[idx].f.offset = 0;
05727    p->subs[idx].f.src = "dahdi_handle_event";
05728    p->subs[idx].f.data.ptr = NULL;
05729    f = &p->subs[idx].f;
05730 
05731    if (idx < 0)
05732       return &p->subs[idx].f;
05733    if (p->fake_event) {
05734       res = p->fake_event;
05735       p->fake_event = 0;
05736    } else
05737       res = dahdi_get_event(p->subs[idx].dfd);
05738 
05739    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05740 
05741    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05742       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05743       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05744 #ifdef HAVE_PRI
05745       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05746          /* absorb event */
05747       } else {
05748 #endif
05749          dahdi_confmute(p, 0);
05750          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05751          p->subs[idx].f.subclass = res & 0xff;
05752 #ifdef HAVE_PRI
05753       }
05754 #endif
05755       dahdi_handle_dtmfup(ast, idx, &f);
05756       return f;
05757    }
05758 
05759    if (res & DAHDI_EVENT_DTMFDOWN) {
05760       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05761       /* Mute conference */
05762       dahdi_confmute(p, 1);
05763       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05764       p->subs[idx].f.subclass = res & 0xff;
05765       return &p->subs[idx].f;
05766    }
05767 
05768    switch (res) {
05769       case DAHDI_EVENT_EC_DISABLED:
05770          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05771          p->echocanon = 0;
05772          break;
05773       case DAHDI_EVENT_BITSCHANGED:
05774 #ifdef HAVE_OPENR2
05775          if (p->sig != SIG_MFCR2) {
05776             ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05777          } else {
05778             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05779             openr2_chan_handle_cas(p->r2chan);
05780          }
05781 #else
05782          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05783 #endif
05784       case DAHDI_EVENT_PULSE_START:
05785          /* Stop tone if there's a pulse start and the PBX isn't started */
05786          if (!ast->pbx)
05787             tone_zone_play_tone(p->subs[idx].dfd, -1);
05788          break;
05789       case DAHDI_EVENT_DIALCOMPLETE:
05790 #ifdef HAVE_OPENR2
05791          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05792             /* we don't need to do anything for this event for R2 signaling
05793                if the call is being setup */
05794             break;
05795          }
05796 #endif
05797          if (p->inalarm) break;
05798          if ((p->radio || (p->oprmode < 0))) break;
05799          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05800             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05801             return NULL;
05802          }
05803          if (!x) { /* if not still dialing in driver */
05804             dahdi_enable_ec(p);
05805             if (p->echobreak) {
05806                dahdi_train_ec(p);
05807                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05808                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05809                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05810                p->echobreak = 0;
05811             } else {
05812                p->dialing = 0;
05813                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05814                   /* if thru with dialing after offhook */
05815                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05816                      ast_setstate(ast, AST_STATE_UP);
05817                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05818                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05819                      break;
05820                   } else { /* if to state wait for offhook to dial rest */
05821                      /* we now wait for off hook */
05822                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05823                   }
05824                }
05825                if (ast->_state == AST_STATE_DIALING) {
05826                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05827                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05828                   } else if (p->confirmanswer || (!p->dialednone
05829                      && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05830                         || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05831                         || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05832                         || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05833                         || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05834                         || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05835                         || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05836                         || (mysig == SIG_SF_FEATB)))) {
05837                      ast_setstate(ast, AST_STATE_RINGING);
05838                   } else if (!p->answeronpolarityswitch) {
05839                      ast_setstate(ast, AST_STATE_UP);
05840                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05841                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05842                      /* If aops=0 and hops=1, this is necessary */
05843                      p->polarity = POLARITY_REV;
05844                   } else {
05845                      /* Start clean, so we can catch the change to REV polarity when party answers */
05846                      p->polarity = POLARITY_IDLE;
05847                   }
05848                }
05849             }
05850          }
05851          break;
05852       case DAHDI_EVENT_ALARM:
05853 #ifdef HAVE_PRI
05854          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05855             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05856                /* T309 is not enabled : hangup calls when alarm occurs */
05857                if (p->call) {
05858                   if (p->pri && p->pri->pri) {
05859                      if (!pri_grab(p, p->pri)) {
05860                         pri_hangup(p->pri->pri, p->call, -1);
05861                         pri_destroycall(p->pri->pri, p->call);
05862                         p->call = NULL;
05863                         pri_rel(p->pri);
05864                      } else
05865                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05866                   } else
05867                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05868                }
05869                if (p->owner)
05870                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05871             }
05872          }
05873          if (p->bearer)
05874             p->bearer->inalarm = 1;
05875          else
05876 #endif
05877          p->inalarm = 1;
05878          res = get_alarms(p);
05879          handle_alarms(p, res);
05880 #ifdef HAVE_PRI
05881          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05882             /* fall through intentionally */
05883          } else {
05884             break;
05885          }
05886 #endif
05887 #ifdef HAVE_SS7
05888          if (p->sig == SIG_SS7)
05889             break;
05890 #endif
05891 #ifdef HAVE_OPENR2
05892          if (p->sig == SIG_MFCR2)
05893             break;
05894 #endif
05895       case DAHDI_EVENT_ONHOOK:
05896          if (p->radio) {
05897             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05898             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05899             break;
05900          }
05901          if (p->oprmode < 0)
05902          {
05903             if (p->oprmode != -1) break;
05904             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05905             {
05906                /* Make sure it starts ringing */
05907                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05908                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05909                save_conference(p->oprpeer);
05910                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05911             }
05912             break;
05913          }
05914          switch (p->sig) {
05915          case SIG_FXOLS:
05916          case SIG_FXOGS:
05917          case SIG_FXOKS:
05918             p->onhooktime = time(NULL);
05919             p->fxsoffhookstate = 0;
05920             p->msgstate = -1;
05921             /* Check for some special conditions regarding call waiting */
05922             if (idx == SUB_REAL) {
05923                /* The normal line was hung up */
05924                if (p->subs[SUB_CALLWAIT].owner) {
05925                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05926                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05927                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05928                   unalloc_sub(p, SUB_CALLWAIT);
05929 #if 0
05930                   p->subs[idx].needanswer = 0;
05931                   p->subs[idx].needringing = 0;
05932 #endif
05933                   p->callwaitingrepeat = 0;
05934                   p->cidcwexpire = 0;
05935                   p->owner = NULL;
05936                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05937                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05938                      p->dialing = 1;
05939                   dahdi_ring_phone(p);
05940                } else if (p->subs[SUB_THREEWAY].owner) {
05941                   unsigned int mssinceflash;
05942                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
05943                      the private structure -- not especially easy or clean */
05944                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
05945                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
05946                      DLA_UNLOCK(&p->lock);
05947                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
05948                      /* We can grab ast and p in that order, without worry.  We should make sure
05949                         nothing seriously bad has happened though like some sort of bizarre double
05950                         masquerade! */
05951                      DLA_LOCK(&p->lock);
05952                      if (p->owner != ast) {
05953                         ast_log(LOG_WARNING, "This isn't good...\n");
05954                         return NULL;
05955                      }
05956                   }
05957                   if (!p->subs[SUB_THREEWAY].owner) {
05958                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05959                      return NULL;
05960                   }
05961                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05962                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
05963                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05964                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on
05965                         hanging up.  Hangup both channels now */
05966                      if (p->subs[SUB_THREEWAY].owner)
05967                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
05968                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05969                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05970                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05971                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05972                      if (p->transfer) {
05973                         /* In any case this isn't a threeway call anymore */
05974                         p->subs[SUB_REAL].inthreeway = 0;
05975                         p->subs[SUB_THREEWAY].inthreeway = 0;
05976                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05977                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05978                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05979                            /* Swap subs and dis-own channel */
05980                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05981                            p->owner = NULL;
05982                            /* Ring the phone */
05983                            dahdi_ring_phone(p);
05984                         } else {
05985                            if ((res = attempt_transfer(p)) < 0) {
05986                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05987                               if (p->subs[SUB_THREEWAY].owner)
05988                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05989                            } else if (res) {
05990                               /* Don't actually hang up at this point */
05991                               if (p->subs[SUB_THREEWAY].owner)
05992                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05993                               break;
05994                            }
05995                         }
05996                      } else {
05997                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05998                         if (p->subs[SUB_THREEWAY].owner)
05999                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06000                      }
06001                   } else {
06002                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06003                      /* Swap subs and dis-own channel */
06004                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06005                      p->owner = NULL;
06006                      /* Ring the phone */
06007                      dahdi_ring_phone(p);
06008                   }
06009                }
06010             } else {
06011                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06012             }
06013             /* Fall through */
06014          default:
06015             dahdi_disable_ec(p);
06016             return NULL;
06017          }
06018          break;
06019       case DAHDI_EVENT_RINGOFFHOOK:
06020          if (p->inalarm) break;
06021          if (p->oprmode < 0)
06022          {
06023             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06024             {
06025                /* Make sure it stops ringing */
06026                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06027                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06028                restore_conference(p->oprpeer);
06029             }
06030             break;
06031          }
06032          if (p->radio)
06033          {
06034             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06035             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06036             break;
06037          }
06038          /* for E911, its supposed to wait for offhook then dial
06039             the second half of the dial string */
06040          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06041             c = strchr(p->dialdest, '/');
06042             if (c)
06043                c++;
06044             else
06045                c = p->dialdest;
06046             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06047             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06048             if (strlen(p->dop.dialstr) > 4) {
06049                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06050                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06051                p->echorest[sizeof(p->echorest) - 1] = '\0';
06052                p->echobreak = 1;
06053                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06054             } else
06055                p->echobreak = 0;
06056             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06057                int saveerr = errno;
06058 
06059                x = DAHDI_ONHOOK;
06060                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06061                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06062                return NULL;
06063                }
06064             p->dialing = 1;
06065             return &p->subs[idx].f;
06066          }
06067          switch (p->sig) {
06068          case SIG_FXOLS:
06069          case SIG_FXOGS:
06070          case SIG_FXOKS:
06071             p->fxsoffhookstate = 1;
06072             switch (ast->_state) {
06073             case AST_STATE_RINGING:
06074                dahdi_enable_ec(p);
06075                dahdi_train_ec(p);
06076                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06077                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06078                /* Make sure it stops ringing */
06079                p->subs[SUB_REAL].needringing = 0;
06080                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06081                ast_debug(1, "channel %d answered\n", p->channel);
06082                if (p->cidspill) {
06083                   /* Cancel any running CallerID spill */
06084                   ast_free(p->cidspill);
06085                   p->cidspill = NULL;
06086                }
06087                p->dialing = 0;
06088                p->callwaitcas = 0;
06089                if (p->confirmanswer) {
06090                   /* Ignore answer if "confirm answer" is enabled */
06091                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06092                   p->subs[idx].f.subclass = 0;
06093                } else if (!ast_strlen_zero(p->dop.dialstr)) {
06094                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
06095                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06096                   if (res < 0) {
06097                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06098                      p->dop.dialstr[0] = '\0';
06099                      return NULL;
06100                   } else {
06101                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06102                      p->subs[idx].f.frametype = AST_FRAME_NULL;
06103                      p->subs[idx].f.subclass = 0;
06104                      p->dialing = 1;
06105                   }
06106                   p->dop.dialstr[0] = '\0';
06107                   ast_setstate(ast, AST_STATE_DIALING);
06108                } else
06109                   ast_setstate(ast, AST_STATE_UP);
06110                return &p->subs[idx].f;
06111             case AST_STATE_DOWN:
06112                ast_setstate(ast, AST_STATE_RING);
06113                ast->rings = 1;
06114                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06115                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06116                ast_debug(1, "channel %d picked up\n", p->channel);
06117                return &p->subs[idx].f;
06118             case AST_STATE_UP:
06119                /* Make sure it stops ringing */
06120                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06121                /* Okay -- probably call waiting*/
06122                if (ast_bridged_channel(p->owner))
06123                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06124                p->subs[idx].needunhold = 1;
06125                break;
06126             case AST_STATE_RESERVED:
06127                /* Start up dialtone */
06128                if (has_voicemail(p))
06129                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06130                else
06131                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06132                break;
06133             default:
06134                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06135             }
06136             break;
06137          case SIG_FXSLS:
06138          case SIG_FXSGS:
06139          case SIG_FXSKS:
06140             if (ast->_state == AST_STATE_RING) {
06141                p->ringt = p->ringt_base;
06142             }
06143 
06144             /* If we get a ring then we cannot be in
06145              * reversed polarity. So we reset to idle */
06146             ast_debug(1, "Setting IDLE polarity due "
06147                "to ring. Old polarity was %d\n",
06148                p->polarity);
06149             p->polarity = POLARITY_IDLE;
06150 
06151             /* Fall through */
06152          case SIG_EM:
06153          case SIG_EM_E1:
06154          case SIG_EMWINK:
06155          case SIG_FEATD:
06156          case SIG_FEATDMF:
06157          case SIG_FEATDMF_TA:
06158          case SIG_E911:
06159          case SIG_FGC_CAMA:
06160          case SIG_FGC_CAMAMF:
06161          case SIG_FEATB:
06162          case SIG_SF:
06163          case SIG_SFWINK:
06164          case SIG_SF_FEATD:
06165          case SIG_SF_FEATDMF:
06166          case SIG_SF_FEATB:
06167             if (ast->_state == AST_STATE_PRERING)
06168                ast_setstate(ast, AST_STATE_RING);
06169             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06170                ast_debug(1, "Ring detected\n");
06171                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06172                p->subs[idx].f.subclass = AST_CONTROL_RING;
06173             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06174                ast_debug(1, "Line answered\n");
06175                if (p->confirmanswer) {
06176                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06177                   p->subs[idx].f.subclass = 0;
06178                } else {
06179                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06180                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06181                   ast_setstate(ast, AST_STATE_UP);
06182                }
06183             } else if (ast->_state != AST_STATE_RING)
06184                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06185             break;
06186          default:
06187             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06188          }
06189          break;
06190       case DAHDI_EVENT_RINGBEGIN:
06191          switch (p->sig) {
06192          case SIG_FXSLS:
06193          case SIG_FXSGS:
06194          case SIG_FXSKS:
06195             if (ast->_state == AST_STATE_RING) {
06196                p->ringt = p->ringt_base;
06197             }
06198             break;
06199          }
06200          break;
06201       case DAHDI_EVENT_RINGEROFF:
06202          if (p->inalarm) break;
06203          if ((p->radio || (p->oprmode < 0))) break;
06204          ast->rings++;
06205          if ((ast->rings > p->cidrings) && (p->cidspill)) {
06206             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
06207             ast_free(p->cidspill);
06208             p->cidspill = NULL;
06209             p->callwaitcas = 0;
06210          }
06211          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06212          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06213          break;
06214       case DAHDI_EVENT_RINGERON:
06215          break;
06216       case DAHDI_EVENT_NOALARM:
06217          p->inalarm = 0;
06218 #ifdef HAVE_PRI
06219          /* Extremely unlikely but just in case */
06220          if (p->bearer)
06221             p->bearer->inalarm = 0;
06222 #endif
06223          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06224          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06225                         "Channel: %d\r\n", p->channel);
06226          break;
06227       case DAHDI_EVENT_WINKFLASH:
06228          if (p->inalarm) break;
06229          if (p->radio) break;
06230          if (p->oprmode < 0) break;
06231          if (p->oprmode > 1)
06232          {
06233             struct dahdi_params par;
06234 
06235             memset(&par, 0, sizeof(par));
06236             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06237             {
06238                if (!par.rxisoffhook)
06239                {
06240                   /* Make sure it stops ringing */
06241                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06242                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06243                   save_conference(p);
06244                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06245                }
06246             }
06247             break;
06248          }
06249          /* Remember last time we got a flash-hook */
06250          p->flashtime = ast_tvnow();
06251          switch (mysig) {
06252          case SIG_FXOLS:
06253          case SIG_FXOGS:
06254          case SIG_FXOKS:
06255             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06256                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06257             p->callwaitcas = 0;
06258 
06259             if (idx != SUB_REAL) {
06260                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06261                goto winkflashdone;
06262             }
06263 
06264             if (p->subs[SUB_CALLWAIT].owner) {
06265                /* Swap to call-wait */
06266                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06267                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06268                p->owner = p->subs[SUB_REAL].owner;
06269                ast_debug(1, "Making %s the new owner\n", p->owner->name);
06270                if (p->owner->_state == AST_STATE_RINGING) {
06271                   ast_setstate(p->owner, AST_STATE_UP);
06272                   p->subs[SUB_REAL].needanswer = 1;
06273                }
06274                p->callwaitingrepeat = 0;
06275                p->cidcwexpire = 0;
06276                /* Start music on hold if appropriate */
06277                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06278                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06279                      S_OR(p->mohsuggest, NULL),
06280                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06281                }
06282                p->subs[SUB_CALLWAIT].needhold = 1;
06283                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06284                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06285                      S_OR(p->mohsuggest, NULL),
06286                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06287                }
06288                p->subs[SUB_REAL].needunhold = 1;
06289             } else if (!p->subs[SUB_THREEWAY].owner) {
06290                if (!p->threewaycalling) {
06291                   /* Just send a flash if no 3-way calling */
06292                   p->subs[SUB_REAL].needflash = 1;
06293                   goto winkflashdone;
06294                } else if (!check_for_conference(p)) {
06295                   char cid_num[256];
06296                   char cid_name[256];
06297 
06298                   cid_num[0] = 0;
06299                   cid_name[0] = 0;
06300                   if (p->dahditrcallerid && p->owner) {
06301                      if (p->owner->cid.cid_num)
06302                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06303                      if (p->owner->cid.cid_name)
06304                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06305                   }
06306                   /* XXX This section needs much more error checking!!! XXX */
06307                   /* Start a 3-way call if feasible */
06308                   if (!((ast->pbx) ||
06309                      (ast->_state == AST_STATE_UP) ||
06310                      (ast->_state == AST_STATE_RING))) {
06311                      ast_debug(1, "Flash when call not up or ringing\n");
06312                      goto winkflashdone;
06313                   }
06314                   if (alloc_sub(p, SUB_THREEWAY)) {
06315                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06316                      goto winkflashdone;
06317                   }
06318                   /* Make new channel */
06319                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06320                   if (p->dahditrcallerid) {
06321                      if (!p->origcid_num)
06322                         p->origcid_num = ast_strdup(p->cid_num);
06323                      if (!p->origcid_name)
06324                         p->origcid_name = ast_strdup(p->cid_name);
06325                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06326                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06327                   }
06328                   /* Swap things around between the three-way and real call */
06329                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
06330                   /* Disable echo canceller for better dialing */
06331                   dahdi_disable_ec(p);
06332                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06333                   if (res)
06334                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06335                   p->owner = chan;
06336                   if (!chan) {
06337                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06338                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06339                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06340                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06341                      dahdi_enable_ec(p);
06342                      ast_hangup(chan);
06343                   } else {
06344                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06345                      int way3bridge = 0, cdr3way = 0;
06346 
06347                      if (!other) {
06348                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06349                      } else
06350                         way3bridge = 1;
06351 
06352                      if (p->subs[SUB_THREEWAY].owner->cdr)
06353                         cdr3way = 1;
06354 
06355                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
06356 
06357                      /* Start music on hold if appropriate */
06358                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06359                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06360                            S_OR(p->mohsuggest, NULL),
06361                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06362                      }
06363                      p->subs[SUB_THREEWAY].needhold = 1;
06364                   }
06365                }
06366             } else {
06367                /* Already have a 3 way call */
06368                if (p->subs[SUB_THREEWAY].inthreeway) {
06369                   /* Call is already up, drop the last person */
06370                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06371                   /* If the primary call isn't answered yet, use it */
06372                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06373                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
06374                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06375                      p->owner = p->subs[SUB_REAL].owner;
06376                   }
06377                   /* Drop the last call and stop the conference */
06378                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06379                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06380                   p->subs[SUB_REAL].inthreeway = 0;
06381                   p->subs[SUB_THREEWAY].inthreeway = 0;
06382                } else {
06383                   /* Lets see what we're up to */
06384                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06385                      (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06386                      int otherindex = SUB_THREEWAY;
06387                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06388                      int way3bridge = 0, cdr3way = 0;
06389 
06390                      if (!other) {
06391                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06392                      } else
06393                         way3bridge = 1;
06394 
06395                      if (p->subs[SUB_THREEWAY].owner->cdr)
06396                         cdr3way = 1;
06397 
06398                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06399                      /* Put them in the threeway, and flip */
06400                      p->subs[SUB_THREEWAY].inthreeway = 1;
06401                      p->subs[SUB_REAL].inthreeway = 1;
06402                      if (ast->_state == AST_STATE_UP) {
06403                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
06404                         otherindex = SUB_REAL;
06405                      }
06406                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06407                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06408                      p->subs[otherindex].needunhold = 1;
06409                      p->owner = p->subs[SUB_REAL].owner;
06410                      if (ast->_state == AST_STATE_RINGING) {
06411                         ast_debug(1, "Enabling ringtone on real and threeway\n");
06412                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06413                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06414                      }
06415                   } else {
06416                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06417                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06418                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06419                      p->owner = p->subs[SUB_REAL].owner;
06420                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06421                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06422                      p->subs[SUB_REAL].needunhold = 1;
06423                      dahdi_enable_ec(p);
06424                   }
06425                }
06426             }
06427 winkflashdone:
06428             update_conf(p);
06429             break;
06430          case SIG_EM:
06431          case SIG_EM_E1:
06432          case SIG_FEATD:
06433          case SIG_SF:
06434          case SIG_SFWINK:
06435          case SIG_SF_FEATD:
06436          case SIG_FXSLS:
06437          case SIG_FXSGS:
06438             if (option_debug) {
06439                if (p->dialing)
06440                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06441                else
06442                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06443             }
06444             break;
06445          case SIG_FEATDMF_TA:
06446             switch (p->whichwink) {
06447             case 0:
06448                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06449                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06450                break;
06451             case 1:
06452                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06453                break;
06454             case 2:
06455                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06456                return NULL;
06457             }
06458             p->whichwink++;
06459             /* Fall through */
06460          case SIG_FEATDMF:
06461          case SIG_E911:
06462          case SIG_FGC_CAMAMF:
06463          case SIG_FGC_CAMA:
06464          case SIG_FEATB:
06465          case SIG_SF_FEATDMF:
06466          case SIG_SF_FEATB:
06467          case SIG_EMWINK:
06468             /* FGD MF and EMWINK *Must* wait for wink */
06469             if (!ast_strlen_zero(p->dop.dialstr)) {
06470                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06471                if (res < 0) {
06472                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06473                   p->dop.dialstr[0] = '\0';
06474                   return NULL;
06475                } else
06476                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06477             }
06478             p->dop.dialstr[0] = '\0';
06479             break;
06480          default:
06481             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06482          }
06483          break;
06484       case DAHDI_EVENT_HOOKCOMPLETE:
06485          if (p->inalarm) break;
06486          if ((p->radio || (p->oprmode < 0))) break;
06487          if (p->waitingfordt.tv_sec) break;
06488          switch (mysig) {
06489          case SIG_FXSLS:  /* only interesting for FXS */
06490          case SIG_FXSGS:
06491          case SIG_FXSKS:
06492          case SIG_EM:
06493          case SIG_EM_E1:
06494          case SIG_EMWINK:
06495          case SIG_FEATD:
06496          case SIG_SF:
06497          case SIG_SFWINK:
06498          case SIG_SF_FEATD:
06499             if (!ast_strlen_zero(p->dop.dialstr)) {
06500                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06501                if (res < 0) {
06502                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06503                   p->dop.dialstr[0] = '\0';
06504                   return NULL;
06505                } else
06506                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06507             }
06508             p->dop.dialstr[0] = '\0';
06509             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06510             break;
06511          case SIG_FEATDMF:
06512          case SIG_FEATDMF_TA:
06513          case SIG_E911:
06514          case SIG_FGC_CAMA:
06515          case SIG_FGC_CAMAMF:
06516          case SIG_FEATB:
06517          case SIG_SF_FEATDMF:
06518          case SIG_SF_FEATB:
06519             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06520             break;
06521          default:
06522             break;
06523          }
06524          break;
06525       case DAHDI_EVENT_POLARITY:
06526          /*
06527           * If we get a Polarity Switch event, this could be
06528           * due to line seizure, remote end connect or remote end disconnect.
06529           *
06530           * Check to see if we should change the polarity state and
06531           * mark the channel as UP or if this is an indication
06532           * of remote end disconnect.
06533           */
06534 
06535          if (p->polarityonanswerdelay > 0) {
06536             /* check if event is not too soon after OffHook or Answer */
06537             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06538                switch (ast->_state) {
06539                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06540                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06541                   if (p->answeronpolarityswitch) {
06542                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06543                      ast_setstate(p->owner, AST_STATE_UP);
06544                      p->polarity = POLARITY_REV;
06545                      if (p->hanguponpolarityswitch) {
06546                         p->polaritydelaytv = ast_tvnow();
06547                      }
06548                   } else {
06549                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06550                   }
06551                   break;
06552 
06553                case AST_STATE_UP:         /*!< Line is up */
06554                case AST_STATE_RING:       /*!< Line is ringing */
06555                   if (p->hanguponpolarityswitch) {
06556                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06557                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06558                      p->polarity = POLARITY_IDLE;
06559                   } else {
06560                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06561                   }
06562                   break;
06563 
06564                case AST_STATE_DOWN:       /*!< Channel is down and available */
06565                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
06566                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
06567                case AST_STATE_BUSY:       /*!< Line is busy */
06568                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
06569                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
06570                default:
06571                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06572                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06573                   }
06574                }
06575 
06576             } else {
06577                /* event is too soon after OffHook or Answer */
06578                switch (ast->_state) {
06579                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06580                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06581                   if (p->answeronpolarityswitch) {
06582                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06583                   }
06584                   break;
06585 
06586                case AST_STATE_UP:         /*!< Line is up */
06587                case AST_STATE_RING:       /*!< Line is ringing */
06588                   if (p->hanguponpolarityswitch) {
06589                      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);
06590                   }
06591                   break;
06592 
06593                default: 
06594                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06595                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06596                   }
06597                }
06598             }
06599          }
06600 
06601          /* Added more log_debug information below to provide a better indication of what is going on */
06602          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) );
06603          break;
06604       default:
06605          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06606    }
06607    return &p->subs[idx].f;
06608 }
06609 
06610 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06611 {
06612    struct dahdi_pvt *p = ast->tech_pvt;
06613    int res;
06614    int usedindex=-1;
06615    int idx;
06616    struct ast_frame *f;
06617 
06618 
06619    idx = dahdi_get_index(ast, p, 1);
06620 
06621    p->subs[idx].f.frametype = AST_FRAME_NULL;
06622    p->subs[idx].f.datalen = 0;
06623    p->subs[idx].f.samples = 0;
06624    p->subs[idx].f.mallocd = 0;
06625    p->subs[idx].f.offset = 0;
06626    p->subs[idx].f.subclass = 0;
06627    p->subs[idx].f.delivery = ast_tv(0,0);
06628    p->subs[idx].f.src = "dahdi_exception";
06629    p->subs[idx].f.data.ptr = NULL;
06630 
06631 
06632    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06633       /* If nobody owns us, absorb the event appropriately, otherwise
06634          we loop indefinitely.  This occurs when, during call waiting, the
06635          other end hangs up our channel so that it no longer exists, but we
06636          have neither FLASH'd nor ONHOOK'd to signify our desire to
06637          change to the other channel. */
06638       if (p->fake_event) {
06639          res = p->fake_event;
06640          p->fake_event = 0;
06641       } else
06642          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06643       /* Switch to real if there is one and this isn't something really silly... */
06644       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06645          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06646          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06647          p->owner = p->subs[SUB_REAL].owner;
06648          if (p->owner && ast_bridged_channel(p->owner))
06649             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06650          p->subs[SUB_REAL].needunhold = 1;
06651       }
06652       switch (res) {
06653       case DAHDI_EVENT_ONHOOK:
06654          dahdi_disable_ec(p);
06655          if (p->owner) {
06656             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06657             dahdi_ring_phone(p);
06658             p->callwaitingrepeat = 0;
06659             p->cidcwexpire = 0;
06660          } else
06661             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06662          update_conf(p);
06663          break;
06664       case DAHDI_EVENT_RINGOFFHOOK:
06665          dahdi_enable_ec(p);
06666          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06667          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06668             p->subs[SUB_REAL].needanswer = 1;
06669             p->dialing = 0;
06670          }
06671          break;
06672       case DAHDI_EVENT_HOOKCOMPLETE:
06673       case DAHDI_EVENT_RINGERON:
06674       case DAHDI_EVENT_RINGEROFF:
06675          /* Do nothing */
06676          break;
06677       case DAHDI_EVENT_WINKFLASH:
06678          p->flashtime = ast_tvnow();
06679          if (p->owner) {
06680             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06681             if (p->owner->_state != AST_STATE_UP) {
06682                /* Answer if necessary */
06683                usedindex = dahdi_get_index(p->owner, p, 0);
06684                if (usedindex > -1) {
06685                   p->subs[usedindex].needanswer = 1;
06686                }
06687                ast_setstate(p->owner, AST_STATE_UP);
06688             }
06689             p->callwaitingrepeat = 0;
06690             p->cidcwexpire = 0;
06691             if (ast_bridged_channel(p->owner))
06692                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06693             p->subs[SUB_REAL].needunhold = 1;
06694          } else
06695             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06696          update_conf(p);
06697          break;
06698       default:
06699          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06700       }
06701       f = &p->subs[idx].f;
06702       return f;
06703    }
06704    if (!(p->radio || (p->oprmode < 0)))
06705       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06706    /* If it's not us, return NULL immediately */
06707    if (ast != p->owner) {
06708       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06709       f = &p->subs[idx].f;
06710       return f;
06711    }
06712    f = dahdi_handle_event(ast);
06713    return f;
06714 }
06715 
06716 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06717 {
06718    struct dahdi_pvt *p = ast->tech_pvt;
06719    struct ast_frame *f;
06720    ast_mutex_lock(&p->lock);
06721    f = __dahdi_exception(ast);
06722    ast_mutex_unlock(&p->lock);
06723    return f;
06724 }
06725 
06726 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06727 {
06728    struct dahdi_pvt *p = ast->tech_pvt;
06729    int res;
06730    int idx;
06731    void *readbuf;
06732    struct ast_frame *f;
06733 
06734    while (ast_mutex_trylock(&p->lock)) {
06735       CHANNEL_DEADLOCK_AVOIDANCE(ast);
06736    }
06737 
06738    idx = dahdi_get_index(ast, p, 0);
06739 
06740    /* Hang up if we don't really exist */
06741    if (idx < 0)   {
06742       ast_log(LOG_WARNING, "We dont exist?\n");
06743       ast_mutex_unlock(&p->lock);
06744       return NULL;
06745    }
06746 
06747    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06748       ast_mutex_unlock(&p->lock);
06749       return NULL;
06750    }
06751 
06752    p->subs[idx].f.frametype = AST_FRAME_NULL;
06753    p->subs[idx].f.datalen = 0;
06754    p->subs[idx].f.samples = 0;
06755    p->subs[idx].f.mallocd = 0;
06756    p->subs[idx].f.offset = 0;
06757    p->subs[idx].f.subclass = 0;
06758    p->subs[idx].f.delivery = ast_tv(0,0);
06759    p->subs[idx].f.src = "dahdi_read";
06760    p->subs[idx].f.data.ptr = NULL;
06761 
06762    /* make sure it sends initial key state as first frame */
06763    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06764    {
06765       struct dahdi_params ps;
06766 
06767       memset(&ps, 0, sizeof(ps));
06768       ps.channo = p->channel;
06769       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06770          ast_mutex_unlock(&p->lock);
06771          return NULL;
06772       }
06773       p->firstradio = 1;
06774       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06775       if (ps.rxisoffhook)
06776       {
06777          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06778       }
06779       else
06780       {
06781          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06782       }
06783       ast_mutex_unlock(&p->lock);
06784       return &p->subs[idx].f;
06785    }
06786    if (p->ringt == 1) {
06787       ast_mutex_unlock(&p->lock);
06788       return NULL;
06789    }
06790    else if (p->ringt > 0)
06791       p->ringt--;
06792 
06793 #ifdef HAVE_OPENR2
06794    if (p->mfcr2) {
06795       openr2_chan_process_event(p->r2chan);
06796    }
06797 #endif
06798 
06799    if (p->subs[idx].needringing) {
06800       /* Send ringing frame if requested */
06801       p->subs[idx].needringing = 0;
06802       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06803       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06804       ast_setstate(ast, AST_STATE_RINGING);
06805       ast_mutex_unlock(&p->lock);
06806       return &p->subs[idx].f;
06807    }
06808 
06809    if (p->subs[idx].needbusy) {
06810       /* Send busy frame if requested */
06811       p->subs[idx].needbusy = 0;
06812       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06813       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06814       ast_mutex_unlock(&p->lock);
06815       return &p->subs[idx].f;
06816    }
06817 
06818    if (p->subs[idx].needcongestion) {
06819       /* Send congestion frame if requested */
06820       p->subs[idx].needcongestion = 0;
06821       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06822       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06823       ast_mutex_unlock(&p->lock);
06824       return &p->subs[idx].f;
06825    }
06826 
06827    if (p->subs[idx].needcallerid) {
06828       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06829                      S_OR(p->lastcid_name, NULL),
06830                      S_OR(p->lastcid_num, NULL)
06831                      );
06832       p->subs[idx].needcallerid = 0;
06833    }
06834 
06835    if (p->subs[idx].needanswer) {
06836       /* Send answer frame if requested */
06837       p->subs[idx].needanswer = 0;
06838       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06839       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06840       ast_mutex_unlock(&p->lock);
06841       return &p->subs[idx].f;
06842    }
06843 #ifdef HAVE_OPENR2
06844    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06845       /* openr2 took care of reading and handling any event
06846         (needanswer, needbusy etc), if we continue we will read()
06847         twice, lets just return a null frame. This should only
06848         happen when openr2 is dialing out */
06849       ast_mutex_unlock(&p->lock);
06850       return &ast_null_frame;
06851    }
06852 #endif
06853 
06854    if (p->subs[idx].needflash) {
06855       /* Send answer frame if requested */
06856       p->subs[idx].needflash = 0;
06857       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06858       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06859       ast_mutex_unlock(&p->lock);
06860       return &p->subs[idx].f;
06861    }
06862 
06863    if (p->subs[idx].needhold) {
06864       /* Send answer frame if requested */
06865       p->subs[idx].needhold = 0;
06866       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06867       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06868       ast_mutex_unlock(&p->lock);
06869       ast_debug(1, "Sending hold on '%s'\n", ast->name);
06870       return &p->subs[idx].f;
06871    }
06872 
06873    if (p->subs[idx].needunhold) {
06874       /* Send answer frame if requested */
06875       p->subs[idx].needunhold = 0;
06876       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06877       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06878       ast_mutex_unlock(&p->lock);
06879       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06880       return &p->subs[idx].f;
06881    }
06882 
06883    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06884       if (!p->subs[idx].linear) {
06885          p->subs[idx].linear = 1;
06886          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06887          if (res)
06888             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06889       }
06890    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06891       (ast->rawreadformat == AST_FORMAT_ALAW)) {
06892       if (p->subs[idx].linear) {
06893          p->subs[idx].linear = 0;
06894          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06895          if (res)
06896             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06897       }
06898    } else {
06899       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06900       ast_mutex_unlock(&p->lock);
06901       return NULL;
06902    }
06903    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06904    CHECK_BLOCKING(ast);
06905    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06906    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06907    /* Check for hangup */
06908    if (res < 0) {
06909       f = NULL;
06910       if (res == -1) {
06911          if (errno == EAGAIN) {
06912             /* Return "NULL" frame if there is nobody there */
06913             ast_mutex_unlock(&p->lock);
06914             return &p->subs[idx].f;
06915          } else if (errno == ELAST) {
06916             f = __dahdi_exception(ast);
06917          } else
06918             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06919       }
06920       ast_mutex_unlock(&p->lock);
06921       return f;
06922    }
06923    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
06924       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06925       f = __dahdi_exception(ast);
06926       ast_mutex_unlock(&p->lock);
06927       return f;
06928    }
06929    if (p->tdd) { /* if in TDD mode, see if we receive that */
06930       int c;
06931 
06932       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06933       if (c < 0) {
06934          ast_debug(1,"tdd_feed failed\n");
06935          ast_mutex_unlock(&p->lock);
06936          return NULL;
06937       }
06938       if (c) { /* if a char to return */
06939          p->subs[idx].f.subclass = 0;
06940          p->subs[idx].f.frametype = AST_FRAME_TEXT;
06941          p->subs[idx].f.mallocd = 0;
06942          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06943          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
06944          p->subs[idx].f.datalen = 1;
06945          *((char *) p->subs[idx].f.data.ptr) = c;
06946          ast_mutex_unlock(&p->lock);
06947          return &p->subs[idx].f;
06948       }
06949    }
06950    /* Ensure the CW timer decrements only on a single subchannel */
06951    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06952       p->callwaitingrepeat--;
06953    }
06954    if (p->cidcwexpire)
06955       p->cidcwexpire--;
06956    /* Repeat callwaiting */
06957    if (p->callwaitingrepeat == 1) {
06958       p->callwaitrings++;
06959       dahdi_callwait(ast);
06960    }
06961    /* Expire CID/CW */
06962    if (p->cidcwexpire == 1) {
06963       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
06964       restore_conference(p);
06965    }
06966    if (p->subs[idx].linear) {
06967       p->subs[idx].f.datalen = READ_SIZE * 2;
06968    } else
06969       p->subs[idx].f.datalen = READ_SIZE;
06970 
06971    /* Handle CallerID Transmission */
06972    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06973       send_callerid(p);
06974    }
06975 
06976    p->subs[idx].f.frametype = AST_FRAME_VOICE;
06977    p->subs[idx].f.subclass = ast->rawreadformat;
06978    p->subs[idx].f.samples = READ_SIZE;
06979    p->subs[idx].f.mallocd = 0;
06980    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06981    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
06982 #if 0
06983    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
06984 #endif
06985    if (p->dialing || /* Transmitting something */
06986       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06987       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06988       ) {
06989       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06990          don't send anything */
06991       p->subs[idx].f.frametype = AST_FRAME_NULL;
06992       p->subs[idx].f.subclass = 0;
06993       p->subs[idx].f.samples = 0;
06994       p->subs[idx].f.mallocd = 0;
06995       p->subs[idx].f.offset = 0;
06996       p->subs[idx].f.data.ptr = NULL;
06997       p->subs[idx].f.datalen= 0;
06998    }
06999    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07000       /* Perform busy detection etc on the dahdi line */
07001       int mute;
07002 
07003       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07004 
07005       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
07006       mute = ast_dsp_was_muted(p->dsp);
07007       if (p->muting != mute) {
07008          p->muting = mute;
07009          dahdi_confmute(p, mute);
07010       }
07011 
07012       if (f) {
07013          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07014             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07015                /* Treat this as a "hangup" instead of a "busy" on the assumption that
07016                   a busy */
07017                f = NULL;
07018             }
07019          } else if (f->frametype == AST_FRAME_DTMF) {
07020 #ifdef HAVE_PRI
07021             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07022                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07023                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07024                /* Don't accept in-band DTMF when in overlap dial mode */
07025                f->frametype = AST_FRAME_NULL;
07026                f->subclass = 0;
07027             }
07028 #endif
07029             /* DSP clears us of being pulse */
07030             p->pulsedial = 0;
07031          } else if (p->waitingfordt.tv_sec) {
07032             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07033                p->waitingfordt.tv_sec = 0;
07034                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07035                f=NULL;
07036             } else if (f->frametype == AST_FRAME_VOICE) {
07037                f->frametype = AST_FRAME_NULL;
07038                f->subclass = 0;
07039                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) {
07040                   p->waitingfordt.tv_sec = 0;
07041                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07042                   ast_dsp_set_features(p->dsp, p->dsp_features);
07043                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07044                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
07045                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07046                      if (res < 0) {
07047                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07048                         p->dop.dialstr[0] = '\0';
07049                         ast_mutex_unlock(&p->lock);
07050                         return NULL;
07051                      } else {
07052                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07053                         p->dialing = 1;
07054                         p->dop.dialstr[0] = '\0';
07055                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
07056                         ast_setstate(ast, AST_STATE_DIALING);
07057                      }
07058                   }
07059                }
07060             }
07061          }
07062       }
07063    } else
07064       f = &p->subs[idx].f;
07065 
07066    if (f && (f->frametype == AST_FRAME_DTMF))
07067       dahdi_handle_dtmfup(ast, idx, &f);
07068 
07069    /* If we have a fake_event, trigger exception to handle it */
07070    if (p->fake_event)
07071       ast_set_flag(ast, AST_FLAG_EXCEPTION);
07072 
07073    ast_mutex_unlock(&p->lock);
07074    return f;
07075 }
07076 
07077 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07078 {
07079    int sent=0;
07080    int size;
07081    int res;
07082    int fd;
07083    fd = p->subs[idx].dfd;
07084    while (len) {
07085       size = len;
07086       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07087          size = (linear ? READ_SIZE * 2 : READ_SIZE);
07088       res = write(fd, buf, size);
07089       if (res != size) {
07090          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07091          return sent;
07092       }
07093       len -= size;
07094       buf += size;
07095    }
07096    return sent;
07097 }
07098 
07099 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07100 {
07101    struct dahdi_pvt *p = ast->tech_pvt;
07102    int res;
07103    int idx;
07104    idx = dahdi_get_index(ast, p, 0);
07105    if (idx < 0) {
07106       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07107       return -1;
07108    }
07109 
07110 #if 0
07111 #ifdef HAVE_PRI
07112    ast_mutex_lock(&p->lock);
07113    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07114       if (p->pri->pri) {
07115          if (!pri_grab(p, p->pri)) {
07116                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07117                pri_rel(p->pri);
07118          } else
07119                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07120       }
07121       p->proceeding=1;
07122    }
07123    ast_mutex_unlock(&p->lock);
07124 #endif
07125 #endif
07126    /* Write a frame of (presumably voice) data */
07127    if (frame->frametype != AST_FRAME_VOICE) {
07128       if (frame->frametype != AST_FRAME_IMAGE)
07129          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07130       return 0;
07131    }
07132    if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07133       (frame->subclass != AST_FORMAT_ULAW) &&
07134       (frame->subclass != AST_FORMAT_ALAW)) {
07135       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07136       return -1;
07137    }
07138    if (p->dialing) {
07139       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07140       return 0;
07141    }
07142    if (!p->owner) {
07143       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07144       return 0;
07145    }
07146    if (p->cidspill) {
07147       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07148       return 0;
07149    }
07150    /* Return if it's not valid data */
07151    if (!frame->data.ptr || !frame->datalen)
07152       return 0;
07153 
07154    if (frame->subclass == AST_FORMAT_SLINEAR) {
07155       if (!p->subs[idx].linear) {
07156          p->subs[idx].linear = 1;
07157          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07158          if (res)
07159             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07160       }
07161       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07162    } else {
07163       /* x-law already */
07164       if (p->subs[idx].linear) {
07165          p->subs[idx].linear = 0;
07166          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07167          if (res)
07168             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07169       }
07170       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07171    }
07172    if (res < 0) {
07173       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07174       return -1;
07175    }
07176    return 0;
07177 }
07178 
07179 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07180 {
07181    struct dahdi_pvt *p = chan->tech_pvt;
07182    int res=-1;
07183    int idx;
07184    int func = DAHDI_FLASH;
07185    ast_mutex_lock(&p->lock);
07186    idx = dahdi_get_index(chan, p, 0);
07187    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07188 #ifdef HAVE_OPENR2
07189    if (p->mfcr2 && !p->mfcr2_call_accepted) {
07190       ast_mutex_unlock(&p->lock);
07191       /* if this is an R2 call and the call is not yet accepted, we don't want the
07192          tone indications to mess up with the MF tones */
07193       return 0;
07194    }
07195 #endif
07196    if (idx == SUB_REAL) {
07197       switch (condition) {
07198       case AST_CONTROL_BUSY:
07199 #ifdef HAVE_PRI
07200          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07201             chan->hangupcause = AST_CAUSE_USER_BUSY;
07202             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07203             res = 0;
07204          } else if (!p->progress &&
07205                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07206                && p->pri && !p->outgoing) {
07207             if (p->pri->pri) {
07208                if (!pri_grab(p, p->pri)) {
07209 #ifdef HAVE_PRI_PROG_W_CAUSE
07210                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
07211 #else
07212                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07213 #endif
07214                   pri_rel(p->pri);
07215                }
07216                else
07217                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07218             }
07219             p->progress = 1;
07220             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07221          } else
07222 #endif
07223             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07224          break;
07225       case AST_CONTROL_RINGING:
07226 #ifdef HAVE_PRI
07227          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07228                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07229             if (p->pri->pri) {
07230                if (!pri_grab(p, p->pri)) {
07231                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07232                   pri_rel(p->pri);
07233                }
07234                else
07235                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07236             }
07237             p->alerting = 1;
07238          }
07239 
07240 #endif
07241 #ifdef HAVE_SS7
07242          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07243             if (p->ss7->ss7) {
07244                ss7_grab(p, p->ss7);
07245 
07246                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07247                   p->rlt = 1;
07248                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
07249                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07250                p->alerting = 1;
07251                ss7_rel(p->ss7);
07252             }
07253          }
07254 #endif
07255 
07256          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07257 
07258          if (chan->_state != AST_STATE_UP) {
07259             if ((chan->_state != AST_STATE_RING) ||
07260                ((p->sig != SIG_FXSKS) &&
07261              (p->sig != SIG_FXSLS) &&
07262              (p->sig != SIG_FXSGS)))
07263             ast_setstate(chan, AST_STATE_RINGING);
07264          }
07265          break;
07266       case AST_CONTROL_PROCEEDING:
07267          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07268 #ifdef HAVE_PRI
07269          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07270                && p->pri && !p->outgoing) {
07271             if (p->pri->pri) {
07272                if (!pri_grab(p, p->pri)) {
07273                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07274                   pri_rel(p->pri);
07275                }
07276                else
07277                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07278             }
07279             p->proceeding = 1;
07280             p->dialing = 0;
07281          }
07282 #endif
07283 #ifdef HAVE_SS7
07284          /* This IF sends the FAR for an answered ALEG call */
07285          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07286             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07287                p->rlt = 1;
07288          }
07289 
07290          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07291             if (p->ss7->ss7) {
07292                ss7_grab(p, p->ss7);
07293                isup_acm(p->ss7->ss7, p->ss7call);
07294                p->proceeding = 1;
07295                ss7_rel(p->ss7);
07296 
07297             }
07298          }
07299 #endif
07300          /* don't continue in ast_indicate */
07301          res = 0;
07302          break;
07303       case AST_CONTROL_PROGRESS:
07304          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07305 #ifdef HAVE_PRI
07306          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
07307          if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07308                && p->pri && !p->outgoing) {
07309             if (p->pri->pri) {
07310                if (!pri_grab(p, p->pri)) {
07311 #ifdef HAVE_PRI_PROG_W_CAUSE
07312                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07313 #else
07314                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07315 #endif
07316                   pri_rel(p->pri);
07317                }
07318                else
07319                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07320             }
07321             p->progress = 1;
07322          }
07323 #endif
07324 #ifdef HAVE_SS7
07325          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07326             if (p->ss7->ss7) {
07327                ss7_grab(p, p->ss7);
07328                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07329                p->progress = 1;
07330                ss7_rel(p->ss7);
07331                /* enable echo canceler here on SS7 calls */
07332                dahdi_enable_ec(p);
07333 
07334             }
07335          }
07336 #endif
07337          /* don't continue in ast_indicate */
07338          res = 0;
07339          break;
07340       case AST_CONTROL_CONGESTION:
07341          chan->hangupcause = AST_CAUSE_CONGESTION;
07342 #ifdef HAVE_PRI
07343          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07344             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07345             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07346             res = 0;
07347          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07348                && p->pri && !p->outgoing) {
07349             if (p->pri) {
07350                if (!pri_grab(p, p->pri)) {
07351 #ifdef HAVE_PRI_PROG_W_CAUSE
07352                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
07353 #else
07354                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07355 #endif
07356                   pri_rel(p->pri);
07357                } else
07358                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07359             }
07360             p->progress = 1;
07361             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07362          } else
07363 #endif
07364             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07365          break;
07366       case AST_CONTROL_HOLD:
07367 #ifdef HAVE_PRI
07368          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07369             if (!pri_grab(p, p->pri)) {
07370                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07371                pri_rel(p->pri);
07372             } else
07373                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07374          } else
07375 #endif
07376             ast_moh_start(chan, data, p->mohinterpret);
07377          break;
07378       case AST_CONTROL_UNHOLD:
07379 #ifdef HAVE_PRI
07380          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07381             if (!pri_grab(p, p->pri)) {
07382                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07383                pri_rel(p->pri);
07384             } else
07385                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07386          } else
07387 #endif
07388             ast_moh_stop(chan);
07389          break;
07390       case AST_CONTROL_RADIO_KEY:
07391          if (p->radio)
07392             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07393          res = 0;
07394          break;
07395       case AST_CONTROL_RADIO_UNKEY:
07396          if (p->radio)
07397             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07398          res = 0;
07399          break;
07400       case AST_CONTROL_FLASH:
07401          /* flash hookswitch */
07402          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07403             /* Clear out the dial buffer */
07404             p->dop.dialstr[0] = '\0';
07405             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07406                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07407                   chan->name, strerror(errno));
07408             } else
07409                res = 0;
07410          } else
07411             res = 0;
07412          break;
07413       case AST_CONTROL_SRCUPDATE:
07414          res = 0;
07415          break;
07416       case -1:
07417          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07418          break;
07419       }
07420    } else
07421       res = 0;
07422    ast_mutex_unlock(&p->lock);
07423    return res;
07424 }
07425 
07426 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07427 {
07428    struct ast_channel *tmp;
07429    int deflaw;
07430    int res;
07431    int x,y;
07432    int features;
07433    struct ast_str *chan_name;
07434    struct ast_variable *v;
07435    struct dahdi_params ps;
07436    if (i->subs[idx].owner) {
07437       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07438       return NULL;
07439    }
07440    y = 1;
07441    chan_name = ast_str_alloca(32);
07442    do {
07443 #ifdef HAVE_PRI
07444       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07445          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07446       else
07447 #endif
07448       if (i->channel == CHAN_PSEUDO)
07449          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07450       else
07451          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07452       for (x = 0; x < 3; x++) {
07453          if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07454             break;
07455       }
07456       y++;
07457    } while (x < 3);
07458    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));
07459    if (!tmp)
07460       return NULL;
07461    tmp->tech = &dahdi_tech;
07462    memset(&ps, 0, sizeof(ps));
07463    ps.channo = i->channel;
07464    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07465    if (res) {
07466       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07467       ps.curlaw = DAHDI_LAW_MULAW;
07468    }
07469    if (ps.curlaw == DAHDI_LAW_ALAW)
07470       deflaw = AST_FORMAT_ALAW;
07471    else
07472       deflaw = AST_FORMAT_ULAW;
07473    if (law) {
07474       if (law == DAHDI_LAW_ALAW)
07475          deflaw = AST_FORMAT_ALAW;
07476       else
07477          deflaw = AST_FORMAT_ULAW;
07478    }
07479    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07480    tmp->nativeformats = deflaw;
07481    /* Start out assuming ulaw since it's smaller :) */
07482    tmp->rawreadformat = deflaw;
07483    tmp->readformat = deflaw;
07484    tmp->rawwriteformat = deflaw;
07485    tmp->writeformat = deflaw;
07486    i->subs[idx].linear = 0;
07487    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07488    features = 0;
07489    if (idx == SUB_REAL) {
07490       if (i->busydetect && CANBUSYDETECT(i))
07491          features |= DSP_FEATURE_BUSY_DETECT;
07492       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07493          features |= DSP_FEATURE_CALL_PROGRESS;
07494       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07495          features |= DSP_FEATURE_WAITDIALTONE;
07496       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07497          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07498          features |= DSP_FEATURE_FAX_DETECT;
07499       }
07500       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07501       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07502          i->hardwaredtmf = 0;
07503          features |= DSP_FEATURE_DIGIT_DETECT;
07504       } else if (NEED_MFDETECT(i)) {
07505          i->hardwaredtmf = 1;
07506          features |= DSP_FEATURE_DIGIT_DETECT;
07507       }
07508    }
07509    if (features) {
07510       if (i->dsp) {
07511          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07512       } else {
07513          if (i->channel != CHAN_PSEUDO)
07514             i->dsp = ast_dsp_new();
07515          else
07516             i->dsp = NULL;
07517          if (i->dsp) {
07518             i->dsp_features = features;
07519 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07520             /* We cannot do progress detection until receives PROGRESS message */
07521             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07522                /* Remember requested DSP features, don't treat
07523                   talking as ANSWER */
07524                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07525                features = 0;
07526             }
07527 #endif
07528             ast_dsp_set_features(i->dsp, features);
07529             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07530             if (!ast_strlen_zero(progzone))
07531                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07532             if (i->busydetect && CANBUSYDETECT(i)) {
07533                ast_dsp_set_busy_count(i->dsp, i->busycount);
07534                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07535             }
07536          }
07537       }
07538    }
07539 
07540    if (state == AST_STATE_RING)
07541       tmp->rings = 1;
07542    tmp->tech_pvt = i;
07543    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07544       /* Only FXO signalled stuff can be picked up */
07545       tmp->callgroup = i->callgroup;
07546       tmp->pickupgroup = i->pickupgroup;
07547    }
07548    if (!ast_strlen_zero(i->parkinglot))
07549       ast_string_field_set(tmp, parkinglot, i->parkinglot);
07550    if (!ast_strlen_zero(i->language))
07551       ast_string_field_set(tmp, language, i->language);
07552    if (!i->owner)
07553       i->owner = tmp;
07554    if (!ast_strlen_zero(i->accountcode))
07555       ast_string_field_set(tmp, accountcode, i->accountcode);
07556    if (i->amaflags)
07557       tmp->amaflags = i->amaflags;
07558    i->subs[idx].owner = tmp;
07559    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07560    ast_string_field_set(tmp, call_forward, i->call_forward);
07561    /* If we've been told "no ADSI" then enforce it */
07562    if (!i->adsi)
07563       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07564    if (!ast_strlen_zero(i->exten))
07565       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07566    if (!ast_strlen_zero(i->rdnis))
07567       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07568    if (!ast_strlen_zero(i->dnid))
07569       tmp->cid.cid_dnid = ast_strdup(i->dnid);
07570 
07571    /* Don't use ast_set_callerid() here because it will
07572     * generate a needless NewCallerID event */
07573 #ifdef PRI_ANI
07574    if (!ast_strlen_zero(i->cid_ani))
07575       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07576    else
07577       tmp->cid.cid_ani = ast_strdup(i->cid_num);
07578 #else
07579    tmp->cid.cid_ani = ast_strdup(i->cid_num);
07580 #endif
07581    tmp->cid.cid_pres = i->callingpres;
07582    tmp->cid.cid_ton = i->cid_ton;
07583    tmp->cid.cid_ani2 = i->cid_ani2;
07584 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07585    tmp->transfercapability = transfercapability;
07586    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07587    if (transfercapability & AST_TRANS_CAP_DIGITAL)
07588       i->digital = 1;
07589    /* Assume calls are not idle calls unless we're told differently */
07590    i->isidlecall = 0;
07591    i->alreadyhungup = 0;
07592 #endif
07593    /* clear the fake event in case we posted one before we had ast_channel */
07594    i->fake_event = 0;
07595    /* Assure there is no confmute on this channel */
07596    dahdi_confmute(i, 0);
07597    i->muting = 0;
07598    /* Configure the new channel jb */
07599    ast_jb_configure(tmp, &global_jbconf);
07600 
07601    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07602 
07603    for (v = i->vars ; v ; v = v->next)
07604       pbx_builtin_setvar_helper(tmp, v->name, v->value);
07605 
07606    if (startpbx) {
07607 #ifdef HAVE_OPENR2
07608       if (i->mfcr2call) {
07609          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07610       }
07611 #endif
07612       if (ast_pbx_start(tmp)) {
07613          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07614          ast_hangup(tmp);
07615          i->owner = NULL;
07616          return NULL;
07617       }
07618    }
07619 
07620    ast_module_ref(ast_module_info->self);
07621    return tmp;
07622 }
07623 
07624 
07625 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07626 {
07627    char c;
07628 
07629    *str = 0; /* start with empty output buffer */
07630    for (;;)
07631    {
07632       /* Wait for the first digit (up to specified ms). */
07633       c = ast_waitfordigit(chan, ms);
07634       /* if timeout, hangup or error, return as such */
07635       if (c < 1)
07636          return c;
07637       *str++ = c;
07638       *str = 0;
07639       if (strchr(term, c))
07640          return 1;
07641    }
07642 }
07643 
07644 static int dahdi_wink(struct dahdi_pvt *p, int idx)
07645 {
07646    int j;
07647    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07648    for (;;)
07649    {
07650       /* set bits of interest */
07651       j = DAHDI_IOMUX_SIGEVENT;
07652       /* wait for some happening */
07653       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07654       /* exit loop if we have it */
07655       if (j & DAHDI_IOMUX_SIGEVENT) break;
07656    }
07657    /* get the event info */
07658    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07659    return 0;
07660 }
07661 
07662 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
07663  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
07664  * \param on 1 to enable, 0 to disable
07665  *
07666  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
07667  * DAHDI channel). Use this to enable or disable it.
07668  *
07669  * \bug the use of the word "channel" for those dahdichans is really confusing.
07670  */
07671 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
07672 {
07673    /* Do not disturb */
07674    dahdichan->dnd = on;
07675    ast_verb(3, "%s DND on channel %d\n",
07676          on? "Enabled" : "Disabled",
07677          dahdichan->channel);
07678    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07679          "Channel: DAHDI/%d\r\n"
07680          "Status: %s\r\n", dahdichan->channel,
07681          on? "enabled" : "disabled");
07682 }
07683 
07684 static void *ss_thread(void *data)
07685 {
07686    struct ast_channel *chan = data;
07687    struct dahdi_pvt *p = chan->tech_pvt;
07688    char exten[AST_MAX_EXTENSION] = "";
07689    char exten2[AST_MAX_EXTENSION] = "";
07690    unsigned char buf[256];
07691    char dtmfcid[300];
07692    char dtmfbuf[300];
07693    struct callerid_state *cs = NULL;
07694    char *name = NULL, *number = NULL;
07695    int distMatches;
07696    int curRingData[3];
07697    int receivedRingT;
07698    int counter1;
07699    int counter;
07700    int samples = 0;
07701    struct ast_smdi_md_message *smdi_msg = NULL;
07702    int flags = 0;
07703    int i;
07704    int timeout;
07705    int getforward = 0;
07706    char *s1, *s2;
07707    int len = 0;
07708    int res;
07709    int idx;
07710 
07711    ast_mutex_lock(&ss_thread_lock);
07712    ss_thread_count++;
07713    ast_mutex_unlock(&ss_thread_lock);
07714    /* in the bizarre case where the channel has become a zombie before we
07715       even get started here, abort safely
07716    */
07717    if (!p) {
07718       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07719       ast_hangup(chan);
07720       goto quit;
07721    }
07722    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07723    idx = dahdi_get_index(chan, p, 1);
07724    if (idx < 0) {
07725       ast_log(LOG_WARNING, "Huh?\n");
07726       ast_hangup(chan);
07727       goto quit;
07728    }
07729    if (p->dsp)
07730       ast_dsp_digitreset(p->dsp);
07731    switch (p->sig) {
07732 #ifdef HAVE_PRI
07733    case SIG_PRI:
07734    case SIG_BRI:
07735    case SIG_BRI_PTMP:
07736       /* Now loop looking for an extension */
07737       ast_copy_string(exten, p->exten, sizeof(exten));
07738       len = strlen(exten);
07739       res = 0;
07740       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07741          if (len && !ast_ignore_pattern(chan->context, exten))
07742             tone_zone_play_tone(p->subs[idx].dfd, -1);
07743          else
07744             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07745          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07746             timeout = matchdigittimeout;
07747          else
07748             timeout = gendigittimeout;
07749          res = ast_waitfordigit(chan, timeout);
07750          if (res < 0) {
07751             ast_debug(1, "waitfordigit returned < 0...\n");
07752             ast_hangup(chan);
07753             goto quit;
07754          } else if (res) {
07755             exten[len++] = res;
07756             exten[len] = '\0';
07757          } else
07758             break;
07759       }
07760       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
07761       if (ast_strlen_zero(exten)) {
07762          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07763          exten[0] = 's';
07764          exten[1] = '\0';
07765       }
07766       tone_zone_play_tone(p->subs[idx].dfd, -1);
07767       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07768          /* Start the real PBX */
07769          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07770          if (p->dsp) {
07771             ast_dsp_digitreset(p->dsp);
07772          }
07773          if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07774             if (p->pri->pri) {      
07775                if (!pri_grab(p, p->pri)) {
07776                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07777                   p->proceeding = 1;
07778                   pri_rel(p->pri);
07779                } else {
07780                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07781                }
07782             }
07783          }
07784          dahdi_enable_ec(p);
07785          ast_setstate(chan, AST_STATE_RING);
07786          res = ast_pbx_run(chan);
07787          if (res) {
07788             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07789          }
07790       } else {
07791          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07792          chan->hangupcause = AST_CAUSE_UNALLOCATED;
07793          ast_hangup(chan);
07794          p->exten[0] = '\0';
07795          /* Since we send release complete here, we won't get one */
07796          p->call = NULL;
07797       }
07798       goto quit;
07799       break;
07800 #endif
07801    case SIG_FEATD:
07802    case SIG_FEATDMF:
07803    case SIG_FEATDMF_TA:
07804    case SIG_E911:
07805    case SIG_FGC_CAMAMF:
07806    case SIG_FEATB:
07807    case SIG_EMWINK:
07808    case SIG_SF_FEATD:
07809    case SIG_SF_FEATDMF:
07810    case SIG_SF_FEATB:
07811    case SIG_SFWINK:
07812       if (dahdi_wink(p, idx))
07813          goto quit;
07814       /* Fall through */
07815    case SIG_EM:
07816    case SIG_EM_E1:
07817    case SIG_SF:
07818    case SIG_FGC_CAMA:
07819       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07820       if (p->dsp)
07821          ast_dsp_digitreset(p->dsp);
07822       /* set digit mode appropriately */
07823       if (p->dsp) {
07824          if (NEED_MFDETECT(p))
07825             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07826          else
07827             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07828       }
07829       memset(dtmfbuf, 0, sizeof(dtmfbuf));
07830       /* Wait for the first digit only if immediate=no */
07831       if (!p->immediate)
07832          /* Wait for the first digit (up to 5 seconds). */
07833          res = ast_waitfordigit(chan, 5000);
07834       else
07835          res = 0;
07836       if (res > 0) {
07837          /* save first char */
07838          dtmfbuf[0] = res;
07839          switch (p->sig) {
07840          case SIG_FEATD:
07841          case SIG_SF_FEATD:
07842             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07843             if (res > 0)
07844                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07845             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07846             break;
07847          case SIG_FEATDMF_TA:
07848             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07849             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07850             if (dahdi_wink(p, idx)) goto quit;
07851             dtmfbuf[0] = 0;
07852             /* Wait for the first digit (up to 5 seconds). */
07853             res = ast_waitfordigit(chan, 5000);
07854             if (res <= 0) break;
07855             dtmfbuf[0] = res;
07856             /* fall through intentionally */
07857          case SIG_FEATDMF:
07858          case SIG_E911:
07859          case SIG_FGC_CAMAMF:
07860          case SIG_SF_FEATDMF:
07861             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07862             /* if international caca, do it again to get real ANO */
07863             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07864             {
07865                if (dahdi_wink(p, idx)) goto quit;
07866                dtmfbuf[0] = 0;
07867                /* Wait for the first digit (up to 5 seconds). */
07868                res = ast_waitfordigit(chan, 5000);
07869                if (res <= 0) break;
07870                dtmfbuf[0] = res;
07871                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07872             }
07873             if (res > 0) {
07874                /* if E911, take off hook */
07875                if (p->sig == SIG_E911)
07876                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07877                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07878             }
07879             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07880             break;
07881          case SIG_FEATB:
07882          case SIG_SF_FEATB:
07883             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07884             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07885             break;
07886          case SIG_EMWINK:
07887             /* if we received a '*', we are actually receiving Feature Group D
07888                dial syntax, so use that mode; otherwise, fall through to normal
07889                mode
07890             */
07891             if (res == '*') {
07892                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07893                if (res > 0)
07894                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07895                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07896                break;
07897             }
07898          default:
07899             /* If we got the first digit, get the rest */
07900             len = 1;
07901             dtmfbuf[len] = '\0';
07902             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07903                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07904                   timeout = matchdigittimeout;
07905                } else {
07906                   timeout = gendigittimeout;
07907                }
07908                res = ast_waitfordigit(chan, timeout);
07909                if (res < 0) {
07910                   ast_debug(1, "waitfordigit returned < 0...\n");
07911                   ast_hangup(chan);
07912                   goto quit;
07913                } else if (res) {
07914                   dtmfbuf[len++] = res;
07915                   dtmfbuf[len] = '\0';
07916                } else {
07917                   break;
07918                }
07919             }
07920             break;
07921          }
07922       }
07923       if (res == -1) {
07924          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07925          ast_hangup(chan);
07926          goto quit;
07927       } else if (res < 0) {
07928          ast_debug(1, "Got hung up before digits finished\n");
07929          ast_hangup(chan);
07930          goto quit;
07931       }
07932 
07933       if (p->sig == SIG_FGC_CAMA) {
07934          char anibuf[100];
07935 
07936          if (ast_safe_sleep(chan,1000) == -1) {
07937             ast_hangup(chan);
07938             goto quit;
07939          }
07940          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07941          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07942          res = my_getsigstr(chan, anibuf, "#", 10000);
07943          if ((res > 0) && (strlen(anibuf) > 2)) {
07944             if (anibuf[strlen(anibuf) - 1] == '#')
07945                anibuf[strlen(anibuf) - 1] = 0;
07946             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07947          }
07948          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07949       }
07950 
07951       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07952       if (ast_strlen_zero(exten))
07953          ast_copy_string(exten, "s", sizeof(exten));
07954       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07955          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07956          if (exten[0] == '*') {
07957             char *stringp=NULL;
07958             ast_copy_string(exten2, exten, sizeof(exten2));
07959             /* Parse out extension and callerid */
07960             stringp=exten2 +1;
07961             s1 = strsep(&stringp, "*");
07962             s2 = strsep(&stringp, "*");
07963             if (s2) {
07964                if (!ast_strlen_zero(p->cid_num))
07965                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07966                else
07967                   ast_set_callerid(chan, s1, NULL, s1);
07968                ast_copy_string(exten, s2, sizeof(exten));
07969             } else
07970                ast_copy_string(exten, s1, sizeof(exten));
07971          } else if (p->sig == SIG_FEATD)
07972             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07973       }
07974       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07975          if (exten[0] == '*') {
07976             char *stringp=NULL;
07977             ast_copy_string(exten2, exten, sizeof(exten2));
07978             /* Parse out extension and callerid */
07979             stringp=exten2 +1;
07980             s1 = strsep(&stringp, "#");
07981             s2 = strsep(&stringp, "#");
07982             if (s2) {
07983                if (!ast_strlen_zero(p->cid_num))
07984                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07985                else
07986                   if (*(s1 + 2))
07987                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07988                ast_copy_string(exten, s2 + 1, sizeof(exten));
07989             } else
07990                ast_copy_string(exten, s1 + 2, sizeof(exten));
07991          } else
07992             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07993       }
07994       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07995          if (exten[0] == '*') {
07996             char *stringp=NULL;
07997             ast_copy_string(exten2, exten, sizeof(exten2));
07998             /* Parse out extension and callerid */
07999             stringp=exten2 +1;
08000             s1 = strsep(&stringp, "#");
08001             s2 = strsep(&stringp, "#");
08002             if (s2 && (*(s2 + 1) == '0')) {
08003                if (*(s2 + 2))
08004                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08005             }
08006             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
08007             else ast_copy_string(exten, "911", sizeof(exten));
08008          } else
08009             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08010       }
08011       if (p->sig == SIG_FEATB) {
08012          if (exten[0] == '*') {
08013             char *stringp=NULL;
08014             ast_copy_string(exten2, exten, sizeof(exten2));
08015             /* Parse out extension and callerid */
08016             stringp=exten2 +1;
08017             s1 = strsep(&stringp, "#");
08018             ast_copy_string(exten, exten2 + 1, sizeof(exten));
08019          } else
08020             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08021       }
08022       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08023          dahdi_wink(p, idx);
08024          /* some switches require a minimum guard time between
08025             the last FGD wink and something that answers
08026             immediately. This ensures it */
08027          if (ast_safe_sleep(chan,100)) goto quit;
08028       }
08029       dahdi_enable_ec(p);
08030       if (NEED_MFDETECT(p)) {
08031          if (p->dsp) {
08032             if (!p->hardwaredtmf)
08033                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08034             else {
08035                ast_dsp_free(p->dsp);
08036                p->dsp = NULL;
08037             }
08038          }
08039       }
08040 
08041       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08042          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08043          if (p->dsp) ast_dsp_digitreset(p->dsp);
08044          res = ast_pbx_run(chan);
08045          if (res) {
08046             ast_log(LOG_WARNING, "PBX exited non-zero\n");
08047             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08048          }
08049          goto quit;
08050       } else {
08051          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08052          sleep(2);
08053          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08054          if (res < 0)
08055             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08056          else
08057             sleep(1);
08058          res = ast_streamfile(chan, "ss-noservice", chan->language);
08059          if (res >= 0)
08060             ast_waitstream(chan, "");
08061          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08062          ast_hangup(chan);
08063          goto quit;
08064       }
08065       break;
08066    case SIG_FXOLS:
08067    case SIG_FXOGS:
08068    case SIG_FXOKS:
08069       /* Read the first digit */
08070       timeout = firstdigittimeout;
08071       /* If starting a threeway call, never timeout on the first digit so someone
08072          can use flash-hook as a "hold" feature */
08073       if (p->subs[SUB_THREEWAY].owner)
08074          timeout = 999999;
08075       while (len < AST_MAX_EXTENSION-1) {
08076          /* Read digit unless it's supposed to be immediate, in which case the
08077             only answer is 's' */
08078          if (p->immediate)
08079             res = 's';
08080          else
08081             res = ast_waitfordigit(chan, timeout);
08082          timeout = 0;
08083          if (res < 0) {
08084             ast_debug(1, "waitfordigit returned < 0...\n");
08085             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08086             ast_hangup(chan);
08087             goto quit;
08088          } else if (res) {
08089             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08090             exten[len++]=res;
08091             exten[len] = '\0';
08092          }
08093          if (!ast_ignore_pattern(chan->context, exten))
08094             tone_zone_play_tone(p->subs[idx].dfd, -1);
08095          else
08096             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08097          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08098             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08099                if (getforward) {
08100                   /* Record this as the forwarding extension */
08101                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08102                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08103                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08104                   if (res)
08105                      break;
08106                   usleep(500000);
08107                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08108                   sleep(1);
08109                   memset(exten, 0, sizeof(exten));
08110                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08111                   len = 0;
08112                   getforward = 0;
08113                } else {
08114                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08115                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08116                   if (!ast_strlen_zero(p->cid_num)) {
08117                      if (!p->hidecallerid)
08118                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08119                      else
08120                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
08121                   }
08122                   if (!ast_strlen_zero(p->cid_name)) {
08123                      if (!p->hidecallerid)
08124                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
08125                   }
08126                   ast_setstate(chan, AST_STATE_RING);
08127                   dahdi_enable_ec(p);
08128                   res = ast_pbx_run(chan);
08129                   if (res) {
08130                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
08131                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08132                   }
08133                   goto quit;
08134                }
08135             } else {
08136                /* It's a match, but they just typed a digit, and there is an ambiguous match,
08137                   so just set the timeout to matchdigittimeout and wait some more */
08138                timeout = matchdigittimeout;
08139             }
08140          } else if (res == 0) {
08141             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08142             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08143             dahdi_wait_event(p->subs[idx].dfd);
08144             ast_hangup(chan);
08145             goto quit;
08146          } else if (p->callwaiting && !strcmp(exten, "*70")) {
08147             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08148             /* Disable call waiting if enabled */
08149             p->callwaiting = 0;
08150             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08151             if (res) {
08152                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08153                   chan->name, strerror(errno));
08154             }
08155             len = 0;
08156             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08157             memset(exten, 0, sizeof(exten));
08158             timeout = firstdigittimeout;
08159 
08160          } else if (!strcmp(exten,ast_pickup_ext())) {
08161             /* Scan all channels and see if there are any
08162              * ringing channels that have call groups
08163              * that equal this channels pickup group
08164              */
08165             if (idx == SUB_REAL) {
08166                /* Switch us from Third call to Call Wait */
08167                if (p->subs[SUB_THREEWAY].owner) {
08168                   /* If you make a threeway call and the *8# a call, it should actually
08169                      look like a callwait */
08170                   alloc_sub(p, SUB_CALLWAIT);
08171                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08172                   unalloc_sub(p, SUB_THREEWAY);
08173                }
08174                dahdi_enable_ec(p);
08175                if (ast_pickup_call(chan)) {
08176                   ast_debug(1, "No call pickup possible...\n");
08177                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08178                   dahdi_wait_event(p->subs[idx].dfd);
08179                }
08180                ast_hangup(chan);
08181                goto quit;
08182             } else {
08183                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
08184                ast_hangup(chan);
08185                goto quit;
08186             }
08187 
08188          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08189             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08190             /* Disable Caller*ID if enabled */
08191             p->hidecallerid = 1;
08192             if (chan->cid.cid_num)
08193                ast_free(chan->cid.cid_num);
08194             chan->cid.cid_num = NULL;
08195             if (chan->cid.cid_name)
08196                ast_free(chan->cid.cid_name);
08197             chan->cid.cid_name = NULL;
08198             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08199             if (res) {
08200                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08201                   chan->name, strerror(errno));
08202             }
08203             len = 0;
08204             memset(exten, 0, sizeof(exten));
08205             timeout = firstdigittimeout;
08206          } else if (p->callreturn && !strcmp(exten, "*69")) {
08207             res = 0;
08208             if (!ast_strlen_zero(p->lastcid_num)) {
08209                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08210             }
08211             if (!res)
08212                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08213             break;
08214          } else if (!strcmp(exten, "*78")) {
08215             dahdi_dnd(p, 1);
08216             /* Do not disturb */
08217             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08218             getforward = 0;
08219             memset(exten, 0, sizeof(exten));
08220             len = 0;
08221          } else if (!strcmp(exten, "*79")) {
08222             dahdi_dnd(p, 0);
08223             /* Do not disturb */
08224             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08225             getforward = 0;
08226             memset(exten, 0, sizeof(exten));
08227             len = 0;
08228          } else if (p->cancallforward && !strcmp(exten, "*72")) {
08229             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08230             getforward = 1;
08231             memset(exten, 0, sizeof(exten));
08232             len = 0;
08233          } else if (p->cancallforward && !strcmp(exten, "*73")) {
08234             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08235             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08236             memset(p->call_forward, 0, sizeof(p->call_forward));
08237             getforward = 0;
08238             memset(exten, 0, sizeof(exten));
08239             len = 0;
08240          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08241                   p->subs[SUB_THREEWAY].owner &&
08242                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08243             /* This is a three way call, the main call being a real channel,
08244                and we're parking the first call. */
08245             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08246             ast_verb(3, "Parking call to '%s'\n", chan->name);
08247             break;
08248          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08249             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08250             res = ast_db_put("blacklist", p->lastcid_num, "1");
08251             if (!res) {
08252                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08253                memset(exten, 0, sizeof(exten));
08254                len = 0;
08255             }
08256          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08257             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08258             /* Enable Caller*ID if enabled */
08259             p->hidecallerid = 0;
08260             if (chan->cid.cid_num)
08261                ast_free(chan->cid.cid_num);
08262             chan->cid.cid_num = NULL;
08263             if (chan->cid.cid_name)
08264                ast_free(chan->cid.cid_name);
08265             chan->cid.cid_name = NULL;
08266             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08267             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08268             if (res) {
08269                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08270                   chan->name, strerror(errno));
08271             }
08272             len = 0;
08273             memset(exten, 0, sizeof(exten));
08274             timeout = firstdigittimeout;
08275          } else if (!strcmp(exten, "*0")) {
08276             struct ast_channel *nbridge =
08277                p->subs[SUB_THREEWAY].owner;
08278             struct dahdi_pvt *pbridge = NULL;
08279             /* set up the private struct of the bridged one, if any */
08280             if (nbridge && ast_bridged_channel(nbridge))
08281                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08282             if (nbridge && pbridge &&
08283                (nbridge->tech == &dahdi_tech) &&
08284                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08285                ISTRUNK(pbridge)) {
08286                int func = DAHDI_FLASH;
08287                /* Clear out the dial buffer */
08288                p->dop.dialstr[0] = '\0';
08289                /* flash hookswitch */
08290                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08291                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08292                      nbridge->name, strerror(errno));
08293                }
08294                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08295                unalloc_sub(p, SUB_THREEWAY);
08296                p->owner = p->subs[SUB_REAL].owner;
08297                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08298                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08299                ast_hangup(chan);
08300                goto quit;
08301             } else {
08302                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08303                dahdi_wait_event(p->subs[idx].dfd);
08304                tone_zone_play_tone(p->subs[idx].dfd, -1);
08305                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08306                unalloc_sub(p, SUB_THREEWAY);
08307                p->owner = p->subs[SUB_REAL].owner;
08308                ast_hangup(chan);
08309                goto quit;
08310             }
08311          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08312                      ((exten[0] != '*') || (strlen(exten) > 2))) {
08313             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);
08314             break;
08315          }
08316          if (!timeout)
08317             timeout = gendigittimeout;
08318          if (len && !ast_ignore_pattern(chan->context, exten))
08319             tone_zone_play_tone(p->subs[idx].dfd, -1);
08320       }
08321       break;
08322    case SIG_FXSLS:
08323    case SIG_FXSGS:
08324    case SIG_FXSKS:
08325 #ifdef HAVE_PRI
08326       if (p->pri) {
08327          /* This is a GR-303 trunk actually.  Wait for the first ring... */
08328          struct ast_frame *f;
08329          int res;
08330          time_t start;
08331 
08332          time(&start);
08333          ast_setstate(chan, AST_STATE_RING);
08334          while (time(NULL) < start + 3) {
08335             res = ast_waitfor(chan, 1000);
08336             if (res) {
08337                f = ast_read(chan);
08338                if (!f) {
08339                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08340                   ast_hangup(chan);
08341                   goto quit;
08342                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08343                   res = 1;
08344                } else
08345                   res = 0;
08346                ast_frfree(f);
08347                if (res) {
08348                   ast_debug(1, "Got ring!\n");
08349                   res = 0;
08350                   break;
08351                }
08352             }
08353          }
08354       }
08355 #endif
08356       /* check for SMDI messages */
08357       if (p->use_smdi && p->smdi_iface) {
08358          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08359 
08360          if (smdi_msg != NULL) {
08361             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08362 
08363             if (smdi_msg->type == 'B')
08364                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08365             else if (smdi_msg->type == 'N')
08366                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08367 
08368             ast_debug(1, "Received SMDI message on %s\n", chan->name);
08369          } else {
08370             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08371          }
08372       }
08373 
08374       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08375          number = smdi_msg->calling_st;
08376 
08377       /* If we want caller id, we're in a prering state due to a polarity reversal
08378        * and we're set to use a polarity reversal to trigger the start of caller id,
08379        * grab the caller id and wait for ringing to start... */
08380       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08381          /* If set to use DTMF CID signalling, listen for DTMF */
08382          if (p->cid_signalling == CID_SIG_DTMF) {
08383             int k = 0;
08384             cs = NULL;
08385             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08386             dahdi_setlinear(p->subs[idx].dfd, 0);
08387             /*
08388              * We are the only party interested in the Rx stream since
08389              * we have not answered yet.  We don't need or even want DTMF
08390              * emulation.  The DTMF digits can come so fast that emulation
08391              * can drop some of them.
08392              */
08393             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08394             res = 4000;/* This is a typical OFF time between rings. */
08395             for (;;) {
08396                struct ast_frame *f;
08397                res = ast_waitfor(chan, res);
08398                if (res <= 0) {
08399                   /*
08400                    * We do not need to restore the dahdi_setlinear()
08401                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
08402                    * are hanging up the channel.
08403                    */
08404                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08405                      "Exiting simple switch\n");
08406                   ast_hangup(chan);
08407                   goto quit;
08408                }
08409                f = ast_read(chan);
08410                if (!f)
08411                   break;
08412                if (f->frametype == AST_FRAME_DTMF) {
08413                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
08414                      dtmfbuf[k++] = f->subclass;
08415                   }
08416                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
08417                   res = 4000;/* This is a typical OFF time between rings. */
08418                }
08419                ast_frfree(f);
08420                if (chan->_state == AST_STATE_RING ||
08421                   chan->_state == AST_STATE_RINGING)
08422                   break; /* Got ring */
08423             }
08424             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08425             dtmfbuf[k] = '\0';
08426             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08427             /* Got cid and ring. */
08428             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08429             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08430             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08431             /* If first byte is NULL, we have no cid */
08432             if (!ast_strlen_zero(dtmfcid))
08433                number = dtmfcid;
08434             else
08435                number = NULL;
08436          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08437          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08438             cs = callerid_new(p->cid_signalling);
08439             if (cs) {
08440                samples = 0;
08441 #if 1
08442                bump_gains(p);
08443 #endif
08444                /* Take out of linear mode for Caller*ID processing */
08445                dahdi_setlinear(p->subs[idx].dfd, 0);
08446 
08447                /* First we wait and listen for the Caller*ID */
08448                for (;;) {
08449                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08450                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08451                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08452                      callerid_free(cs);
08453                      ast_hangup(chan);
08454                      goto quit;
08455                   }
08456                   if (i & DAHDI_IOMUX_SIGEVENT) {
08457                      res = dahdi_get_event(p->subs[idx].dfd);
08458                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08459                      if (res == DAHDI_EVENT_NOALARM) {
08460                         p->inalarm = 0;
08461                      }
08462 
08463                      if (p->cid_signalling == CID_SIG_V23_JP) {
08464                         if (res == DAHDI_EVENT_RINGBEGIN) {
08465                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08466                            usleep(1);
08467                         }
08468                      } else {
08469                         res = 0;
08470                         break;
08471                      }
08472                   } else if (i & DAHDI_IOMUX_READ) {
08473                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08474                      if (res < 0) {
08475                         if (errno != ELAST) {
08476                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08477                            callerid_free(cs);
08478                            ast_hangup(chan);
08479                            goto quit;
08480                         }
08481                         break;
08482                      }
08483                      samples += res;
08484 
08485                      if (p->cid_signalling == CID_SIG_V23_JP) {
08486                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08487                      } else {
08488                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08489                      }
08490                      if (res < 0) {
08491                         /*
08492                          * The previous diagnostic message output likely
08493                          * explains why it failed.
08494                          */
08495                         ast_log(LOG_WARNING,
08496                            "Failed to decode CallerID on channel '%s'\n",
08497                            chan->name);
08498                         break;
08499                      } else if (res)
08500                         break;
08501                      else if (samples > (8000 * 10))
08502                         break;
08503                   }
08504                }
08505                if (res == 1) {
08506                   callerid_get(cs, &name, &number, &flags);
08507                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08508                }
08509 
08510                if (p->cid_signalling == CID_SIG_V23_JP) {
08511                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08512                   usleep(1);
08513                }
08514 
08515                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08516                res = 4000;/* This is a typical OFF time between rings. */
08517                for (;;) {
08518                   struct ast_frame *f;
08519                   res = ast_waitfor(chan, res);
08520                   if (res <= 0) {
08521                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08522                         "Exiting simple switch\n");
08523                      ast_hangup(chan);
08524                      goto quit;
08525                   }
08526                   if (!(f = ast_read(chan))) {
08527                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08528                      ast_hangup(chan);
08529                      goto quit;
08530                   }
08531                   ast_frfree(f);
08532                   if (chan->_state == AST_STATE_RING ||
08533                      chan->_state == AST_STATE_RINGING)
08534                      break; /* Got ring */
08535                }
08536 
08537                /* We must have a ring by now, so, if configured, lets try to listen for
08538                 * distinctive ringing */
08539                if (p->usedistinctiveringdetection) {
08540                   len = 0;
08541                   distMatches = 0;
08542                   /* Clear the current ring data array so we dont have old data in it. */
08543                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08544                      curRingData[receivedRingT] = 0;
08545                   receivedRingT = 0;
08546                   counter = 0;
08547                   counter1 = 0;
08548                   /* Check to see if context is what it should be, if not set to be. */
08549                   if (strcmp(p->context,p->defcontext) != 0) {
08550                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08551                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08552                   }
08553 
08554                   for (;;) {
08555                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08556                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08557                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08558                         callerid_free(cs);
08559                         ast_hangup(chan);
08560                         goto quit;
08561                      }
08562                      if (i & DAHDI_IOMUX_SIGEVENT) {
08563                         res = dahdi_get_event(p->subs[idx].dfd);
08564                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08565                         if (res == DAHDI_EVENT_NOALARM) {
08566                            p->inalarm = 0;
08567                         }
08568                         res = 0;
08569                         /* Let us detect distinctive ring */
08570 
08571                         curRingData[receivedRingT] = p->ringt;
08572 
08573                         if (p->ringt < p->ringt_base/2)
08574                            break;
08575                         /* Increment the ringT counter so we can match it against
08576                            values in chan_dahdi.conf for distinctive ring */
08577                         if (++receivedRingT == ARRAY_LEN(curRingData))
08578                            break;
08579                      } else if (i & DAHDI_IOMUX_READ) {
08580                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08581                         if (res < 0) {
08582                            if (errno != ELAST) {
08583                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08584                               callerid_free(cs);
08585                               ast_hangup(chan);
08586                               goto quit;
08587                            }
08588                            break;
08589                         }
08590                         if (p->ringt)
08591                            p->ringt--;
08592                         if (p->ringt == 1) {
08593                            res = -1;
08594                            break;
08595                         }
08596                      }
08597                   }
08598                      /* this only shows up if you have n of the dring patterns filled in */
08599                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08600                   for (counter = 0; counter < 3; counter++) {
08601                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08602                      channel */
08603                      distMatches = 0;
08604                      for (counter1 = 0; counter1 < 3; counter1++) {
08605                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08606                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08607                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08608                            curRingData[counter1]);
08609                            distMatches++;
08610                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08611                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08612                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08613                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08614                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08615                            distMatches++;
08616                         }
08617                      }
08618 
08619                      if (distMatches == 3) {
08620                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08621                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08622                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08623                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08624                         break;
08625                      }
08626                   }
08627                }
08628                /* Restore linear mode (if appropriate) for Caller*ID processing */
08629                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08630 #if 1
08631                restore_gains(p);
08632 #endif
08633             } else
08634                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08635          } else {
08636             ast_log(LOG_WARNING, "Channel %s in prering "
08637                "state, but I have nothing to do. "
08638                "Terminating simple switch, should be "
08639                "restarted by the actual ring.\n",
08640                chan->name);
08641             ast_hangup(chan);
08642             goto quit;
08643          }
08644       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08645          if (p->cid_signalling == CID_SIG_DTMF) {
08646             int k = 0;
08647             cs = NULL;
08648             dahdi_setlinear(p->subs[idx].dfd, 0);
08649             res = 2000;
08650             for (;;) {
08651                struct ast_frame *f;
08652                res = ast_waitfor(chan, res);
08653                if (res <= 0) {
08654                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08655                      "Exiting simple switch\n");
08656                   ast_hangup(chan);
08657                   return NULL;
08658                }
08659                f = ast_read(chan);
08660                if (f->frametype == AST_FRAME_DTMF) {
08661                   dtmfbuf[k++] = f->subclass;
08662                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08663                   res = 2000;
08664                }
08665                ast_frfree(f);
08666 
08667                if (p->ringt_base == p->ringt)
08668                   break;
08669             }
08670             dtmfbuf[k] = '\0';
08671             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08672             /* Got cid and ring. */
08673             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08674             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08675                dtmfcid, flags);
08676             /* If first byte is NULL, we have no cid */
08677             if (!ast_strlen_zero(dtmfcid))
08678                number = dtmfcid;
08679             else
08680                number = NULL;
08681             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08682          } else {
08683             /* FSK Bell202 callerID */
08684             cs = callerid_new(p->cid_signalling);
08685             if (cs) {
08686 #if 1
08687                bump_gains(p);
08688 #endif
08689                samples = 0;
08690                len = 0;
08691                distMatches = 0;
08692                /* Clear the current ring data array so we dont have old data in it. */
08693                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08694                   curRingData[receivedRingT] = 0;
08695                receivedRingT = 0;
08696                counter = 0;
08697                counter1 = 0;
08698                /* Check to see if context is what it should be, if not set to be. */
08699                if (strcmp(p->context,p->defcontext) != 0) {
08700                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08701                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08702                }
08703 
08704                /* Take out of linear mode for Caller*ID processing */
08705                dahdi_setlinear(p->subs[idx].dfd, 0);
08706                for (;;) {
08707                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08708                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08709                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08710                      callerid_free(cs);
08711                      ast_hangup(chan);
08712                      goto quit;
08713                   }
08714                   if (i & DAHDI_IOMUX_SIGEVENT) {
08715                      res = dahdi_get_event(p->subs[idx].dfd);
08716                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08717                      if (res == DAHDI_EVENT_NOALARM) {
08718                         p->inalarm = 0;
08719                      }
08720                      /* If we get a PR event, they hung up while processing calerid */
08721                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08722                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08723                         p->polarity = POLARITY_IDLE;
08724                         callerid_free(cs);
08725                         ast_hangup(chan);
08726                         goto quit;
08727                      }
08728                      res = 0;
08729                      /* Let us detect callerid when the telco uses distinctive ring */
08730 
08731                      curRingData[receivedRingT] = p->ringt;
08732 
08733                      if (p->ringt < p->ringt_base/2)
08734                         break;
08735                      /* Increment the ringT counter so we can match it against
08736                         values in chan_dahdi.conf for distinctive ring */
08737                      if (++receivedRingT == ARRAY_LEN(curRingData))
08738                         break;
08739                   } else if (i & DAHDI_IOMUX_READ) {
08740                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08741                      if (res < 0) {
08742                         if (errno != ELAST) {
08743                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08744                            callerid_free(cs);
08745                            ast_hangup(chan);
08746                            goto quit;
08747                         }
08748                         break;
08749                      }
08750                      if (p->ringt)
08751                         p->ringt--;
08752                      if (p->ringt == 1) {
08753                         res = -1;
08754                         break;
08755                      }
08756                      samples += res;
08757                      res = callerid_feed(cs, buf, res, AST_LAW(p));
08758                      if (res < 0) {
08759                         /*
08760                          * The previous diagnostic message output likely
08761                          * explains why it failed.
08762                          */
08763                         ast_log(LOG_WARNING,
08764                            "Failed to decode CallerID on channel '%s'\n",
08765                            chan->name);
08766                         break;
08767                      } else if (res)
08768                         break;
08769                      else if (samples > (8000 * 10))
08770                         break;
08771                   }
08772                }
08773                if (res == 1) {
08774                   callerid_get(cs, &name, &number, &flags);
08775                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08776                }
08777                if (distinctiveringaftercid == 1) {
08778                   /* Clear the current ring data array so we dont have old data in it. */
08779                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08780                      curRingData[receivedRingT] = 0;
08781                   }
08782                   receivedRingT = 0;
08783                   ast_verb(3, "Detecting post-CID distinctive ring\n");
08784                   for (;;) {
08785                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08786                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08787                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08788                         callerid_free(cs);
08789                         ast_hangup(chan);
08790                         goto quit;
08791                      }
08792                      if (i & DAHDI_IOMUX_SIGEVENT) {
08793                         res = dahdi_get_event(p->subs[idx].dfd);
08794                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08795                         if (res == DAHDI_EVENT_NOALARM) {
08796                            p->inalarm = 0;
08797                         }
08798                         res = 0;
08799                         /* Let us detect callerid when the telco uses distinctive ring */
08800 
08801                         curRingData[receivedRingT] = p->ringt;
08802 
08803                         if (p->ringt < p->ringt_base/2)
08804                            break;
08805                         /* Increment the ringT counter so we can match it against
08806                            values in chan_dahdi.conf for distinctive ring */
08807                         if (++receivedRingT == ARRAY_LEN(curRingData))
08808                            break;
08809                      } else if (i & DAHDI_IOMUX_READ) {
08810                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08811                         if (res < 0) {
08812                            if (errno != ELAST) {
08813                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08814                               callerid_free(cs);
08815                               ast_hangup(chan);
08816                               goto quit;
08817                            }
08818                            break;
08819                         }
08820                      if (p->ringt)
08821                         p->ringt--;
08822                         if (p->ringt == 1) {
08823                            res = -1;
08824                            break;
08825                         }
08826                      }
08827                   }
08828                }
08829                if (p->usedistinctiveringdetection) {
08830                   /* this only shows up if you have n of the dring patterns filled in */
08831                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08832 
08833                   for (counter = 0; counter < 3; counter++) {
08834                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08835                      channel */
08836                      /* this only shows up if you have n of the dring patterns filled in */
08837                      ast_verb(3, "Checking %d,%d,%d\n",
08838                            p->drings.ringnum[counter].ring[0],
08839                            p->drings.ringnum[counter].ring[1],
08840                            p->drings.ringnum[counter].ring[2]);
08841                      distMatches = 0;
08842                      for (counter1 = 0; counter1 < 3; counter1++) {
08843                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08844                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08845                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08846                            curRingData[counter1]);
08847                            distMatches++;
08848                         }
08849                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08850                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08851                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08852                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08853                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08854                            distMatches++;
08855                         }
08856                      }
08857                      if (distMatches == 3) {
08858                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08859                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08860                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08861                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08862                         break;
08863                      }
08864                   }
08865                }
08866                /* Restore linear mode (if appropriate) for Caller*ID processing */
08867                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08868 #if 1
08869                restore_gains(p);
08870 #endif
08871                if (res < 0) {
08872                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08873                }
08874             } else
08875                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08876          }
08877       } else
08878          cs = NULL;
08879 
08880       if (number)
08881          ast_shrink_phone_number(number);
08882       ast_set_callerid(chan, number, name, number);
08883 
08884       if (smdi_msg)
08885          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08886 
08887       if (cs)
08888          callerid_free(cs);
08889       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
08890       if (flags & CID_MSGWAITING) {
08891          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08892          notify_message(p->mailbox, 1);
08893          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08894          if (p->mwimonitor_rpas) {
08895             ast_hangup(chan);
08896             return NULL;
08897          }
08898       } else if (flags & CID_NOMSGWAITING) {
08899          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08900          notify_message(p->mailbox, 0);
08901          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08902          if (p->mwimonitor_rpas) {
08903             ast_hangup(chan);
08904             return NULL;
08905          }
08906       }
08907 
08908       ast_setstate(chan, AST_STATE_RING);
08909       chan->rings = 1;
08910       p->ringt = p->ringt_base;
08911       res = ast_pbx_run(chan);
08912       if (res) {
08913          ast_hangup(chan);
08914          ast_log(LOG_WARNING, "PBX exited non-zero\n");
08915       }
08916       goto quit;
08917    default:
08918       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08919       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08920       if (res < 0)
08921             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08922    }
08923    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08924    if (res < 0)
08925          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08926    ast_hangup(chan);
08927 quit:
08928    ast_mutex_lock(&ss_thread_lock);
08929    ss_thread_count--;
08930    ast_cond_signal(&ss_thread_complete);
08931    ast_mutex_unlock(&ss_thread_lock);
08932    return NULL;
08933 }
08934 
08935 struct mwi_thread_data {
08936    struct dahdi_pvt *pvt;
08937    unsigned char buf[READ_SIZE];
08938    size_t len;
08939 };
08940 
08941 static int calc_energy(const unsigned char *buf, int len, int law)
08942 {
08943    int x;
08944    int sum = 0;
08945 
08946    if (!len)
08947       return 0;
08948 
08949    for (x = 0; x < len; x++)
08950       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08951 
08952    return sum / len;
08953 }
08954 
08955 static void *mwi_thread(void *data)
08956 {
08957    struct mwi_thread_data *mtd = data;
08958    struct callerid_state *cs;
08959    pthread_t threadid;
08960    int samples = 0;
08961    char *name, *number;
08962    int flags;
08963    int i, res;
08964    unsigned int spill_done = 0;
08965    int spill_result = -1;
08966 
08967    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
08968       mtd->pvt->mwimonitoractive = 0;
08969 
08970       return NULL;
08971    }
08972 
08973    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
08974 
08975    bump_gains(mtd->pvt);
08976 
08977    for (;;) {
08978       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08979       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08980          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08981          goto quit;
08982       }
08983 
08984       if (i & DAHDI_IOMUX_SIGEVENT) {
08985          struct ast_channel *chan;
08986 
08987          /* If we get an event, screen out events that we do not act on.
08988           * Otherwise, cancel and go to the simple switch to let it deal with it.
08989           */
08990          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08991 
08992          switch (res) {
08993          case DAHDI_EVENT_NEONMWI_ACTIVE:
08994          case DAHDI_EVENT_NEONMWI_INACTIVE:
08995          case DAHDI_EVENT_NONE:
08996          case DAHDI_EVENT_BITSCHANGED:
08997             break;
08998          case DAHDI_EVENT_NOALARM:
08999             mtd->pvt->inalarm = 0;
09000             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09001             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09002                "Channel: %d\r\n", mtd->pvt->channel);
09003             break;
09004          case DAHDI_EVENT_ALARM:
09005             mtd->pvt->inalarm = 1;
09006             res = get_alarms(mtd->pvt);
09007             handle_alarms(mtd->pvt, res);
09008             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
09009          default:
09010             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
09011             callerid_free(cs);
09012 
09013             restore_gains(mtd->pvt);
09014             mtd->pvt->ringt = mtd->pvt->ringt_base;
09015 
09016             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09017                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09018                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09019                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09020                   if (res < 0)
09021                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09022                   ast_hangup(chan);
09023                   goto quit;
09024                }
09025                goto quit_no_clean;
09026 
09027             } else {
09028                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09029             }
09030          }
09031       } else if (i & DAHDI_IOMUX_READ) {
09032          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09033             if (errno != ELAST) {
09034                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09035                goto quit;
09036             }
09037             break;
09038          }
09039          samples += res;
09040          if (!spill_done) {
09041             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09042                /*
09043                 * The previous diagnostic message output likely
09044                 * explains why it failed.
09045                 */
09046                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09047                break;
09048             } else if (spill_result) {
09049                spill_done = 1;
09050             }
09051          } else {
09052             /* keep reading data until the energy level drops below the threshold
09053                so we don't get another 'trigger' on the remaining carrier signal
09054             */
09055             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09056                break;
09057          }
09058          if (samples > (8000 * 4)) /*Termination case - time to give up*/
09059             break;
09060       }
09061    }
09062 
09063    if (spill_result == 1) {
09064       callerid_get(cs, &name, &number, &flags);
09065       if (flags & CID_MSGWAITING) {
09066          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09067          notify_message(mtd->pvt->mailbox, 1);
09068       } else if (flags & CID_NOMSGWAITING) {
09069          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09070          notify_message(mtd->pvt->mailbox, 0);
09071       } else {
09072          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09073       }
09074    }
09075 
09076 
09077 quit:
09078    callerid_free(cs);
09079 
09080    restore_gains(mtd->pvt);
09081 
09082 quit_no_clean:
09083    mtd->pvt->mwimonitoractive = 0;
09084 
09085    ast_free(mtd);
09086 
09087    return NULL;
09088 }
09089 
09090 /*
09091 * The following three functions (mwi_send_init, mwi_send_process_buffer,
09092 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
09093 * that are sent out via FXA port on voicemail state change.  The execution of
09094 * the mwi send is state driven and can either generate a ring pulse prior to
09095 * sending the fsk spill or simply send an fsk spill.
09096 */
09097 static int mwi_send_init(struct dahdi_pvt * pvt)
09098 {
09099    int x, res;
09100 
09101 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09102    /* Determine how this spill is to be sent */
09103    if (pvt->mwisend_rpas) {
09104       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09105       pvt->mwisendactive = 1;
09106    } else if (pvt->mwisend_fsk) {
09107       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09108       pvt->mwisendactive = 1;
09109    } else {
09110       pvt->mwisendactive = 0;
09111       return 0;
09112    }
09113 #else
09114    if (mwisend_rpas) {
09115       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09116    } else {
09117       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09118    }
09119    pvt->mwisendactive = 1;
09120 #endif
09121 
09122    if (pvt->cidspill) {
09123       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09124       ast_free(pvt->cidspill);
09125       pvt->cidspill = NULL;
09126       pvt->cidpos = 0;
09127       pvt->cidlen = 0;
09128    }
09129    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09130    if (!pvt->cidspill) {
09131       pvt->mwisendactive = 0;
09132       return -1;
09133    }
09134    x = DAHDI_FLUSH_BOTH;
09135    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09136    x = 3000;
09137    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09138 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09139    if (pvt->mwisend_fsk) {
09140 #endif
09141       pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09142                         AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09143       pvt->cidpos = 0;
09144 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09145    }
09146 #endif
09147    return 0;
09148 }
09149 
09150 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09151 {
09152    struct timeval    now;
09153    int         res;
09154 
09155    /* sanity check to catch if this had been interrupted previously
09156    *  i.e. state says there is more to do but there is no spill allocated
09157    */
09158    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09159       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09160    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09161       /* Normal processing -- Perform mwi send action */
09162       switch ( pvt->mwisend_data.mwisend_current) {
09163       case MWI_SEND_SA:
09164          /* Send the Ring Pulse Signal Alert */
09165          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09166          if (res) {
09167             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09168             goto quit;
09169          }
09170          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09171          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09172          break;
09173       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
09174          break;
09175       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
09176 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09177          if (pvt->mwisend_fsk) {
09178 #endif
09179             gettimeofday(&now, NULL);
09180             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09181                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09182             }
09183 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09184          } else { /* support for mwisendtype=nofsk */
09185             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09186          }
09187 #endif
09188          break;
09189       case MWI_SEND_SPILL:
09190          /* We read some number of bytes.  Write an equal amount of data */
09191          if(0 < num_read) {
09192             if (num_read > pvt->cidlen - pvt->cidpos)
09193                num_read = pvt->cidlen - pvt->cidpos;
09194             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09195             if (res > 0) {
09196                pvt->cidpos += res;
09197                if (pvt->cidpos >= pvt->cidlen) {
09198                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09199                }
09200             } else {
09201                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09202                goto quit;
09203             }
09204          }
09205          break;
09206       case MWI_SEND_CLEANUP:
09207          /* For now, do nothing */
09208          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09209          break;
09210       default:
09211          /* Should not get here, punt*/
09212          goto quit;
09213       }
09214    }
09215 
09216    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09217       if (pvt->cidspill) {
09218          ast_free(pvt->cidspill);
09219          pvt->cidspill = NULL;
09220          pvt->cidpos = 0;
09221          pvt->cidlen = 0;
09222       }
09223       pvt->mwisendactive = 0;
09224    }
09225    return 0;
09226 quit:
09227    if (pvt->cidspill) {
09228       ast_free(pvt->cidspill);
09229       pvt->cidspill = NULL;
09230       pvt->cidpos = 0;
09231       pvt->cidlen = 0;
09232    }
09233    pvt->mwisendactive = 0;
09234    return -1;
09235 }
09236 
09237 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09238 {
09239    int handled = 0;
09240 
09241    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09242       switch (event) {
09243       case DAHDI_EVENT_RINGEROFF:
09244          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09245             handled = 1;
09246 
09247             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09248                ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09249                if(pvt->cidspill) {
09250                   ast_free(pvt->cidspill);
09251                   pvt->cidspill = NULL;
09252                }
09253                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09254                pvt->mwisendactive = 0;
09255             } else {
09256                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09257                gettimeofday(&pvt->mwisend_data.pause, NULL);
09258             }
09259          }
09260          break;
09261       /* Going off hook, I need to punt this spill */
09262       case DAHDI_EVENT_RINGOFFHOOK:
09263          if (pvt->cidspill) {
09264             ast_free(pvt->cidspill);
09265             pvt->cidspill = NULL;
09266             pvt->cidpos = 0;
09267             pvt->cidlen = 0;
09268          }
09269          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09270          pvt->mwisendactive = 0;
09271          break;
09272       case DAHDI_EVENT_RINGERON:
09273       case DAHDI_EVENT_HOOKCOMPLETE:
09274          break;
09275       default:
09276          break;
09277       }
09278    }
09279    return handled;
09280 }
09281 
09282 /* destroy a DAHDI channel, identified by its number */
09283 static int dahdi_destroy_channel_bynum(int channel)
09284 {
09285    struct dahdi_pvt *tmp = NULL;
09286    struct dahdi_pvt *prev = NULL;
09287 
09288    tmp = iflist;
09289    while (tmp) {
09290       if (tmp->channel == channel) {
09291          int x = DAHDI_FLASH;
09292          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 */
09293          destroy_channel(prev, tmp, 1);
09294          ast_module_unref(ast_module_info->self);
09295          return RESULT_SUCCESS;
09296       }
09297       prev = tmp;
09298       tmp = tmp->next;
09299    }
09300    return RESULT_FAILURE;
09301 }
09302 
09303 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09304 {
09305    int res;
09306    pthread_t threadid;
09307    struct ast_channel *chan;
09308 
09309    /* Handle an event on a given channel for the monitor thread. */
09310 
09311    switch (event) {
09312    case DAHDI_EVENT_NONE:
09313    case DAHDI_EVENT_BITSCHANGED:
09314       break;
09315    case DAHDI_EVENT_WINKFLASH:
09316    case DAHDI_EVENT_RINGOFFHOOK:
09317       if (i->inalarm) break;
09318       if (i->radio) break;
09319       /* Got a ring/answer.  What kind of channel are we? */
09320       switch (i->sig) {
09321       case SIG_FXOLS:
09322       case SIG_FXOGS:
09323       case SIG_FXOKS:
09324          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09325          i->fxsoffhookstate = 1;
09326          if (res && (errno == EBUSY))
09327             break;
09328          if (i->cidspill) {
09329             /* Cancel VMWI spill */
09330             ast_free(i->cidspill);
09331             i->cidspill = NULL;
09332          }
09333          if (i->immediate) {
09334             dahdi_enable_ec(i);
09335             /* The channel is immediately up.  Start right away */
09336             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09337             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09338             if (!chan) {
09339                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09340                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09341                if (res < 0)
09342                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09343             }
09344          } else {
09345             /* Check for callerid, digits, etc */
09346             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09347             if (chan) {
09348                if (has_voicemail(i))
09349                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09350                else
09351                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09352                if (res < 0)
09353                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09354                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09355                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09356                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09357                   if (res < 0)
09358                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09359                   ast_hangup(chan);
09360                }
09361             } else
09362                ast_log(LOG_WARNING, "Unable to create channel\n");
09363          }
09364          break;
09365       case SIG_FXSLS:
09366       case SIG_FXSGS:
09367       case SIG_FXSKS:
09368             i->ringt = i->ringt_base;
09369             /* Fall through */
09370       case SIG_EMWINK:
09371       case SIG_FEATD:
09372       case SIG_FEATDMF:
09373       case SIG_FEATDMF_TA:
09374       case SIG_E911:
09375       case SIG_FGC_CAMA:
09376       case SIG_FGC_CAMAMF:
09377       case SIG_FEATB:
09378       case SIG_EM:
09379       case SIG_EM_E1:
09380       case SIG_SFWINK:
09381       case SIG_SF_FEATD:
09382       case SIG_SF_FEATDMF:
09383       case SIG_SF_FEATB:
09384       case SIG_SF:
09385          /* Check for callerid, digits, etc */
09386          if (i->cid_start == CID_START_POLARITY_IN) {
09387             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09388          } else {
09389             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09390          }
09391 
09392          if (!chan) {
09393             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09394          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09395             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09396             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09397             if (res < 0) {
09398                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09399             }
09400             ast_hangup(chan);
09401          }
09402          break;
09403       default:
09404          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09405          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09406          if (res < 0)
09407             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09408          return NULL;
09409       }
09410       break;
09411    case DAHDI_EVENT_NOALARM:
09412       i->inalarm = 0;
09413       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09414       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09415          "Channel: %d\r\n", i->channel);
09416       break;
09417    case DAHDI_EVENT_ALARM:
09418       i->inalarm = 1;
09419       res = get_alarms(i);
09420       handle_alarms(i, res);
09421       /* fall thru intentionally */
09422    case DAHDI_EVENT_ONHOOK:
09423       if (i->radio)
09424          break;
09425       /* Back on hook.  Hang up. */
09426       switch (i->sig) {
09427       case SIG_FXOLS:
09428       case SIG_FXOGS:
09429       case SIG_FEATD:
09430       case SIG_FEATDMF:
09431       case SIG_FEATDMF_TA:
09432       case SIG_E911:
09433       case SIG_FGC_CAMA:
09434       case SIG_FGC_CAMAMF:
09435       case SIG_FEATB:
09436       case SIG_EM:
09437       case SIG_EM_E1:
09438       case SIG_EMWINK:
09439       case SIG_SF_FEATD:
09440       case SIG_SF_FEATDMF:
09441       case SIG_SF_FEATB:
09442       case SIG_SF:
09443       case SIG_SFWINK:
09444       case SIG_FXSLS:
09445       case SIG_FXSGS:
09446       case SIG_FXSKS:
09447       case SIG_GR303FXSKS:
09448          dahdi_disable_ec(i);
09449          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09450          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09451          break;
09452       case SIG_GR303FXOKS:
09453       case SIG_FXOKS:
09454          dahdi_disable_ec(i);
09455          /* Diddle the battery for the zhone */
09456 #ifdef ZHONE_HACK
09457          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09458          usleep(1);
09459 #endif
09460          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09461          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09462          break;
09463       case SIG_PRI:
09464       case SIG_SS7:
09465       case SIG_BRI:
09466       case SIG_BRI_PTMP:
09467          dahdi_disable_ec(i);
09468          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09469          break;
09470       default:
09471          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09472          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09473          return NULL;
09474       }
09475       if (i->sig & __DAHDI_SIG_FXO) {
09476          i->fxsoffhookstate = 0;
09477       }
09478       break;
09479    case DAHDI_EVENT_POLARITY:
09480       switch (i->sig) {
09481       case SIG_FXSLS:
09482       case SIG_FXSKS:
09483       case SIG_FXSGS:
09484          /* We have already got a PR before the channel was
09485             created, but it wasn't handled. We need polarity
09486             to be REV for remote hangup detection to work.
09487             At least in Spain */
09488          if (i->hanguponpolarityswitch)
09489             i->polarity = POLARITY_REV;
09490          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09491             i->polarity = POLARITY_REV;
09492             ast_verb(2, "Starting post polarity "
09493                "CID detection on channel %d\n",
09494                i->channel);
09495             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09496             if (!chan) {
09497                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09498             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09499                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09500             }
09501          }
09502          break;
09503       default:
09504          ast_log(LOG_WARNING, "handle_init_event detected "
09505             "polarity reversal on non-FXO (SIG_FXS) "
09506             "interface %d\n", i->channel);
09507       }
09508       break;
09509    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
09510       ast_log(LOG_NOTICE,
09511             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09512             i->channel);
09513       return i;
09514    case DAHDI_EVENT_NEONMWI_ACTIVE:
09515       if (i->mwimonitor_neon) {
09516          notify_message(i->mailbox, 1);
09517          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09518       }
09519       break;
09520    case DAHDI_EVENT_NEONMWI_INACTIVE:
09521       if (i->mwimonitor_neon) {
09522          notify_message(i->mailbox, 0);
09523          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09524       }
09525       break;
09526    }
09527    return NULL;
09528 }
09529 
09530 static void *do_monitor(void *data)
09531 {
09532    int count, res, res2, spoint, pollres=0;
09533    struct dahdi_pvt *i;
09534    struct dahdi_pvt *last = NULL;
09535    struct dahdi_pvt *doomed;
09536    time_t thispass = 0, lastpass = 0;
09537    int found;
09538    char buf[1024];
09539    struct pollfd *pfds=NULL;
09540    int lastalloc = -1;
09541    /* This thread monitors all the frame relay interfaces which are not yet in use
09542       (and thus do not have a separate thread) indefinitely */
09543    /* From here on out, we die whenever asked */
09544 #if 0
09545    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09546       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09547       return NULL;
09548    }
09549    ast_debug(1, "Monitor starting...\n");
09550 #endif
09551    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09552 
09553    for (;;) {
09554       /* Lock the interface list */
09555       ast_mutex_lock(&iflock);
09556       if (!pfds || (lastalloc != ifcount)) {
09557          if (pfds) {
09558             ast_free(pfds);
09559             pfds = NULL;
09560          }
09561          if (ifcount) {
09562             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09563                ast_mutex_unlock(&iflock);
09564                return NULL;
09565             }
09566          }
09567          lastalloc = ifcount;
09568       }
09569       /* Build the stuff we're going to poll on, that is the socket of every
09570          dahdi_pvt that does not have an associated owner channel */
09571       count = 0;
09572       i = iflist;
09573       while (i) {
09574          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09575             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09576                /* This needs to be watched, as it lacks an owner */
09577                pfds[count].fd = i->subs[SUB_REAL].dfd;
09578                pfds[count].events = POLLPRI;
09579                pfds[count].revents = 0;
09580                /* If we are monitoring for VMWI or sending CID, we need to
09581                   read from the channel as well */
09582                if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09583                   pfds[count].events |= POLLIN;
09584                count++;
09585             }
09586          }
09587          i = i->next;
09588       }
09589       /* Okay, now that we know what to do, release the interface lock */
09590       ast_mutex_unlock(&iflock);
09591 
09592       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09593       pthread_testcancel();
09594       /* Wait at least a second for something to happen */
09595       res = poll(pfds, count, 1000);
09596       pthread_testcancel();
09597       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09598 
09599       /* Okay, poll has finished.  Let's see what happened.  */
09600       if (res < 0) {
09601          if ((errno != EAGAIN) && (errno != EINTR))
09602             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09603          continue;
09604       }
09605       /* Alright, lock the interface list again, and let's look and see what has
09606          happened */
09607       ast_mutex_lock(&iflock);
09608       found = 0;
09609       spoint = 0;
09610       lastpass = thispass;
09611       thispass = time(NULL);
09612       i = iflist;
09613       doomed = NULL;
09614       for (i = iflist;; i = i->next) {
09615          if (doomed) {
09616             int res;
09617             res = dahdi_destroy_channel_bynum(doomed->channel);
09618             if (!res) {
09619                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09620             }
09621             doomed = NULL;
09622          }
09623          if (!i) {
09624             break;
09625          }
09626 
09627          if (thispass != lastpass) {
09628             if (!found && ((i == last) || ((i == iflist) && !last))) {
09629                last = i;
09630                if (last) {
09631                   /* Only allow MWI to be initiated on a quiescent fxs port */
09632                   if (!last->mwisendactive &&   last->sig & __DAHDI_SIG_FXO &&
09633                         !last->fxsoffhookstate && !last->owner &&
09634                         !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09635                      res = has_voicemail(last);
09636                      if (last->msgstate != res) {
09637                         /* Set driver resources for signalling VMWI */
09638                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09639                         if (res2) {
09640                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
09641                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09642                         }
09643                         /* If enabled for FSK spill then initiate it */
09644                         if (mwi_send_init(last)) {
09645                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09646                         }
09647                         last->msgstate = res;
09648                         found ++;
09649                      }
09650                   }
09651                   last = last->next;
09652                }
09653             }
09654          }
09655          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09656             if (i->radio && !i->owner)
09657             {
09658                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09659                if (res)
09660                {
09661                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09662                   /* Don't hold iflock while handling init events */
09663                   ast_mutex_unlock(&iflock);
09664                   doomed = handle_init_event(i, res);
09665                   ast_mutex_lock(&iflock);
09666                }
09667                continue;
09668             }
09669             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09670             if (pollres & POLLIN) {
09671                if (i->owner || i->subs[SUB_REAL].owner) {
09672 #ifdef HAVE_PRI
09673                   if (!i->pri)
09674 #endif
09675                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09676                   continue;
09677                }
09678                if (!i->mwimonitor_fsk && !i->mwisendactive) {
09679                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09680                   continue;
09681                }
09682                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09683                if (res > 0) {
09684                   if (i->mwimonitor_fsk) {
09685                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09686                         pthread_attr_t attr;
09687                         pthread_t threadid;
09688                         struct mwi_thread_data *mtd;
09689 
09690                         pthread_attr_init(&attr);
09691                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09692 
09693                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09694                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09695                            mtd->pvt = i;
09696                            memcpy(mtd->buf, buf, res);
09697                            mtd->len = res;
09698                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09699                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09700                               ast_free(mtd);
09701                            }
09702                            i->mwimonitoractive = 1;
09703                         }
09704                      }
09705                   }
09706                   if (i->mwisendactive) {
09707                      mwi_send_process_buffer(i, res);
09708                   }
09709                } else {
09710                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09711                }
09712             }
09713             if (pollres & POLLPRI) {
09714                if (i->owner || i->subs[SUB_REAL].owner) {
09715 #ifdef HAVE_PRI
09716                   if (!i->pri)
09717 #endif
09718                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09719                   continue;
09720                }
09721                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09722                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09723                /* Don't hold iflock while handling init events */
09724                ast_mutex_unlock(&iflock);
09725                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09726                   doomed = handle_init_event(i, res);
09727                }
09728                ast_mutex_lock(&iflock);
09729             }
09730          }
09731       }
09732       ast_mutex_unlock(&iflock);
09733    }
09734    /* Never reached */
09735    return NULL;
09736 
09737 }
09738 
09739 static int restart_monitor(void)
09740 {
09741    /* If we're supposed to be stopped -- stay stopped */
09742    if (monitor_thread == AST_PTHREADT_STOP)
09743       return 0;
09744    ast_mutex_lock(&monlock);
09745    if (monitor_thread == pthread_self()) {
09746       ast_mutex_unlock(&monlock);
09747       ast_log(LOG_WARNING, "Cannot kill myself\n");
09748       return -1;
09749    }
09750    if (monitor_thread != AST_PTHREADT_NULL) {
09751       /* Wake up the thread */
09752       pthread_kill(monitor_thread, SIGURG);
09753    } else {
09754       /* Start a new monitor */
09755       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09756          ast_mutex_unlock(&monlock);
09757          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09758          return -1;
09759       }
09760    }
09761    ast_mutex_unlock(&monlock);
09762    return 0;
09763 }
09764 
09765 #if defined(HAVE_PRI)
09766 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
09767 {
09768    int x;
09769    int trunkgroup;
09770    /* Get appropriate trunk group if there is one */
09771    trunkgroup = pris[*span].mastertrunkgroup;
09772    if (trunkgroup) {
09773       /* Select a specific trunk group */
09774       for (x = 0; x < NUM_SPANS; x++) {
09775          if (pris[x].trunkgroup == trunkgroup) {
09776             *span = x;
09777             return 0;
09778          }
09779       }
09780       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09781       *span = -1;
09782    } else {
09783       if (pris[*span].trunkgroup) {
09784          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09785          *span = -1;
09786       } else if (pris[*span].mastertrunkgroup) {
09787          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09788          *span = -1;
09789       } else {
09790          if (si->totalchans == 31) {
09791             /* E1 */
09792             pris[*span].dchannels[0] = 16 + offset;
09793          } else if (si->totalchans == 24) {
09794             /* T1 or J1 */
09795             pris[*span].dchannels[0] = 24 + offset;
09796          } else if (si->totalchans == 3) {
09797             /* BRI */
09798             pris[*span].dchannels[0] = 3 + offset;
09799          } else {
09800             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);
09801             *span = -1;
09802             return 0;
09803          }
09804          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09805          pris[*span].offset = offset;
09806          pris[*span].span = *span + 1;
09807       }
09808    }
09809    return 0;
09810 }
09811 #endif   /* defined(HAVE_PRI) */
09812 
09813 #if defined(HAVE_PRI)
09814 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09815 {
09816    struct dahdi_spaninfo si;
09817    struct dahdi_params p;
09818    int fd;
09819    int span;
09820    int ospan=0;
09821    int x,y;
09822    for (x = 0; x < NUM_SPANS; x++) {
09823       if (pris[x].trunkgroup == trunkgroup) {
09824          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09825          return -1;
09826       }
09827    }
09828    for (y = 0; y < NUM_DCHANS; y++) {
09829       if (!channels[y])
09830          break;
09831       memset(&si, 0, sizeof(si));
09832       memset(&p, 0, sizeof(p));
09833       fd = open("/dev/dahdi/channel", O_RDWR);
09834       if (fd < 0) {
09835          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09836          return -1;
09837       }
09838       x = channels[y];
09839       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09840          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09841          close(fd);
09842          return -1;
09843       }
09844       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09845          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09846          return -1;
09847       }
09848       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09849          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09850          close(fd);
09851          return -1;
09852       }
09853       span = p.spanno - 1;
09854       if (pris[span].trunkgroup) {
09855          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09856          close(fd);
09857          return -1;
09858       }
09859       if (pris[span].pvts[0]) {
09860          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09861          close(fd);
09862          return -1;
09863       }
09864       if (!y) {
09865          pris[span].trunkgroup = trunkgroup;
09866          pris[span].offset = channels[y] - p.chanpos;
09867          ospan = span;
09868       }
09869       pris[ospan].dchannels[y] = channels[y];
09870       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09871       pris[span].span = span + 1;
09872       close(fd);
09873    }
09874    return 0;
09875 }
09876 #endif   /* defined(HAVE_PRI) */
09877 
09878 #if defined(HAVE_PRI)
09879 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09880 {
09881    if (pris[span].mastertrunkgroup) {
09882       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);
09883       return -1;
09884    }
09885    pris[span].mastertrunkgroup = trunkgroup;
09886    pris[span].prilogicalspan = logicalspan;
09887    return 0;
09888 }
09889 #endif   /* defined(HAVE_PRI) */
09890 
09891 #if defined(HAVE_SS7)
09892 static unsigned int parse_pointcode(const char *pcstring)
09893 {
09894    unsigned int code1, code2, code3;
09895    int numvals;
09896 
09897    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09898    if (numvals == 1)
09899       return code1;
09900    if (numvals == 3)
09901       return (code1 << 16) | (code2 << 8) | code3;
09902 
09903    return 0;
09904 }
09905 #endif   /* defined(HAVE_SS7) */
09906 
09907 #if defined(HAVE_SS7)
09908 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
09909 {
09910    if ((linkset < 0) || (linkset >= NUM_SPANS))
09911       return NULL;
09912    else
09913       return &linksets[linkset - 1];
09914 }
09915 #endif   /* defined(HAVE_SS7) */
09916 
09917 #ifdef HAVE_OPENR2
09918 static void dahdi_r2_destroy_links(void)
09919 {
09920    int i = 0;
09921    if (!r2links) {
09922       return;
09923    }
09924    for (; i < r2links_count; i++) {
09925       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
09926          pthread_cancel(r2links[i]->r2master);
09927          pthread_join(r2links[i]->r2master, NULL);
09928          openr2_context_delete(r2links[i]->protocol_context);
09929       }
09930       ast_free(r2links[i]);
09931    }
09932    ast_free(r2links);
09933    r2links = NULL;
09934    r2links_count = 0;
09935 }
09936 
09937 #define R2_LINK_CAPACITY 10
09938 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
09939 {
09940    struct dahdi_mfcr2 *new_r2link = NULL;
09941    struct dahdi_mfcr2 **new_r2links = NULL;
09942    /* this function is called just when starting up and no monitor threads have been launched,
09943       no need to lock monitored_count member */
09944    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
09945       new_r2link = ast_calloc(1, sizeof(**r2links));
09946       if (!new_r2link) {
09947          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09948          return NULL;
09949       }
09950       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
09951       if (!new_r2links) {
09952          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09953          ast_free(new_r2link);
09954          return NULL;
09955       }
09956       r2links = new_r2links;
09957       new_r2link->r2master = AST_PTHREADT_NULL;
09958       r2links[r2links_count] = new_r2link;
09959       r2links_count++;
09960       ast_log(LOG_DEBUG, "Created new R2 link!\n");
09961    }
09962    return r2links[r2links_count - 1];
09963 }
09964 
09965 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
09966 {
09967    char tmplogdir[] = "/tmp";
09968    char logdir[OR2_MAX_PATH];
09969    int threshold = 0;
09970    int snres = 0;
09971    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
09972          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
09973          conf->mfcr2.max_dnis);
09974    if (!r2_link->protocol_context) {
09975       return -1;
09976    }
09977    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
09978    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
09979 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
09980    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
09981 #endif
09982    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
09983    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
09984    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
09985    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
09986    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
09987    if (ast_strlen_zero(conf->mfcr2.logdir)) {
09988       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09989          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09990       }
09991    } else {
09992       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
09993       if (snres >= sizeof(logdir)) {
09994          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09995          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09996             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09997          }
09998       } else {
09999          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10000             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10001          }
10002       }
10003    }
10004    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10005       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10006          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10007       }
10008    }
10009    r2_link->monitored_count = 0;
10010    return 0;
10011 }
10012 #endif
10013 
10014 /* converts a DAHDI sigtype to signalling as can be configured from
10015  * chan_dahdi.conf.
10016  * While both have basically the same values, this will later be the
10017  * place to add filters and sanity checks
10018  */
10019 static int sigtype_to_signalling(int sigtype)
10020 {
10021    return sigtype;
10022 }
10023 
10024 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10025 {
10026    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
10027    struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10028    char fn[80];
10029    struct dahdi_bufferinfo bi;
10030 
10031    int res;
10032    int span = 0;
10033    int here = 0;
10034    int x;
10035    struct dahdi_pvt **wlist;
10036    struct dahdi_pvt **wend;
10037    struct dahdi_params p;
10038 
10039    wlist = &iflist;
10040    wend = &ifend;
10041 
10042 #ifdef HAVE_PRI
10043    if (pri) {
10044       wlist = &pri->crvs;
10045       wend = &pri->crvend;
10046    }
10047 #endif
10048 
10049    tmp2 = *wlist;
10050    prev = NULL;
10051 
10052    while (tmp2) {
10053       if (!tmp2->destroy) {
10054          if (tmp2->channel == channel) {
10055             tmp = tmp2;
10056             here = 1;
10057             break;
10058          }
10059          if (tmp2->channel > channel) {
10060             break;
10061          }
10062       }
10063       prev = tmp2;
10064       tmp2 = tmp2->next;
10065    }
10066 
10067    if (!here && reloading != 1) {
10068       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10069          if (tmp)
10070             free(tmp);
10071          return NULL;
10072       }
10073       ast_mutex_init(&tmp->lock);
10074       ifcount++;
10075       for (x = 0; x < 3; x++)
10076          tmp->subs[x].dfd = -1;
10077       tmp->channel = channel;
10078       tmp->priindication_oob = conf->chan.priindication_oob;
10079    }
10080 
10081    if (tmp) {
10082       int chan_sig = conf->chan.sig;
10083       if (!here) {
10084          if ((channel != CHAN_PSEUDO) && !pri) {
10085             int count = 0;
10086             snprintf(fn, sizeof(fn), "%d", channel);
10087             /* Open non-blocking */
10088             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10089             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 */
10090                usleep(1);
10091                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10092                count++;
10093             }
10094             /* Allocate a DAHDI structure */
10095             if (tmp->subs[SUB_REAL].dfd < 0) {
10096                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);
10097                destroy_dahdi_pvt(&tmp);
10098                return NULL;
10099             }
10100             memset(&p, 0, sizeof(p));
10101             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10102             if (res < 0) {
10103                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10104                destroy_dahdi_pvt(&tmp);
10105                return NULL;
10106             }
10107             if (conf->is_sig_auto)
10108                chan_sig = sigtype_to_signalling(p.sigtype);
10109             if (p.sigtype != (chan_sig & 0x3ffff)) {
10110                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));
10111                destroy_dahdi_pvt(&tmp);
10112                return NULL;
10113             }
10114             tmp->law = p.curlaw;
10115             tmp->span = p.spanno;
10116             span = p.spanno - 1;
10117          } else {
10118             if (channel == CHAN_PSEUDO)
10119                chan_sig = 0;
10120             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10121                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10122                return NULL;
10123             }
10124          }
10125 #ifdef HAVE_SS7
10126          if (chan_sig == SIG_SS7) {
10127             struct dahdi_ss7 *ss7;
10128             int clear = 0;
10129             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10130                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10131                destroy_dahdi_pvt(&tmp);
10132                return NULL;
10133             }
10134 
10135             ss7 = ss7_resolve_linkset(cur_linkset);
10136             if (!ss7) {
10137                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10138                destroy_dahdi_pvt(&tmp);
10139                return NULL;
10140             }
10141             if (cur_cicbeginswith < 0) {
10142                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10143                destroy_dahdi_pvt(&tmp);
10144                return NULL;
10145             }
10146 
10147             tmp->cic = cur_cicbeginswith++;
10148 
10149             /* DB: Add CIC's DPC information */
10150             tmp->dpc = cur_defaultdpc;
10151 
10152             tmp->ss7 = ss7;
10153             tmp->ss7call = NULL;
10154             ss7->pvts[ss7->numchans++] = tmp;
10155 
10156             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10157             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10158             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10159             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10160 
10161             ss7->called_nai = conf->ss7.called_nai;
10162             ss7->calling_nai = conf->ss7.calling_nai;
10163          }
10164 #endif
10165 #ifdef HAVE_OPENR2
10166          if (chan_sig == SIG_MFCR2 && reloading != 1) {
10167             struct dahdi_mfcr2 *r2_link;
10168             r2_link = dahdi_r2_get_link();
10169             if (!r2_link) {
10170                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10171                destroy_dahdi_pvt(&tmp);
10172                return NULL;
10173             }
10174             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10175                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10176                destroy_dahdi_pvt(&tmp);
10177                return NULL;
10178             }
10179             if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10180                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10181                destroy_dahdi_pvt(&tmp);
10182                return NULL;
10183             }
10184             r2_link->pvts[r2_link->numchans++] = tmp;
10185             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10186                                         tmp->subs[SUB_REAL].dfd,
10187                                         NULL, NULL);
10188             if (!tmp->r2chan) {
10189                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10190                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10191                destroy_dahdi_pvt(&tmp);
10192                return NULL;
10193             }
10194             tmp->mfcr2 = r2_link;
10195             if (conf->mfcr2.call_files) {
10196                openr2_chan_enable_call_files(tmp->r2chan);
10197             }
10198             openr2_chan_set_client_data(tmp->r2chan, tmp);
10199             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10200             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10201             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10202             tmp->mfcr2_category = conf->mfcr2.category;
10203             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10204             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10205             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10206             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10207             tmp->mfcr2call = 0;
10208             tmp->mfcr2_dnis_index = 0;
10209             tmp->mfcr2_ani_index = 0;
10210             r2_link->monitored_count++;
10211          }
10212 #endif
10213 #ifdef HAVE_PRI
10214          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10215             int offset;
10216             int myswitchtype;
10217             int matchesdchan;
10218             int x,y;
10219             offset = 0;
10220             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10221                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10222                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10223                destroy_dahdi_pvt(&tmp);
10224                return NULL;
10225             }
10226             if (span >= NUM_SPANS) {
10227                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10228                destroy_dahdi_pvt(&tmp);
10229                return NULL;
10230             } else {
10231                struct dahdi_spaninfo si;
10232                si.spanno = 0;
10233                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10234                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10235                   destroy_dahdi_pvt(&tmp);
10236                   return NULL;
10237                }
10238                /* Store the logical span first based upon the real span */
10239                tmp->logicalspan = pris[span].prilogicalspan;
10240                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10241                if (span < 0) {
10242                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10243                   destroy_dahdi_pvt(&tmp);
10244                   return NULL;
10245                }
10246                if ((chan_sig == SIG_PRI) ||
10247                      (chan_sig == SIG_BRI) ||
10248                      (chan_sig == SIG_BRI_PTMP))
10249                   myswitchtype = conf->pri.switchtype;
10250                else
10251                   myswitchtype = PRI_SWITCH_GR303_TMC;
10252                /* Make sure this isn't a d-channel */
10253                matchesdchan=0;
10254                for (x = 0; x < NUM_SPANS; x++) {
10255                   for (y = 0; y < NUM_DCHANS; y++) {
10256                      if (pris[x].dchannels[y] == tmp->channel) {
10257                         matchesdchan = 1;
10258                         break;
10259                      }
10260                   }
10261                }
10262                offset = p.chanpos;
10263                if (!matchesdchan) {
10264                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10265                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10266                      destroy_dahdi_pvt(&tmp);
10267                      return NULL;
10268                   }
10269                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10270                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10271                      destroy_dahdi_pvt(&tmp);
10272                      return NULL;
10273                   }
10274                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10275                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10276                      destroy_dahdi_pvt(&tmp);
10277                      return NULL;
10278                   }
10279                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10280                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10281                      destroy_dahdi_pvt(&tmp);
10282                      return NULL;
10283                   }
10284                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10285                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10286                      destroy_dahdi_pvt(&tmp);
10287                      return NULL;
10288                   }
10289                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10290                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10291                      destroy_dahdi_pvt(&tmp);
10292                      return NULL;
10293                   }
10294                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10295                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10296                      destroy_dahdi_pvt(&tmp);
10297                      return NULL;
10298                   }
10299                   if (pris[span].numchans >= MAX_CHANNELS) {
10300                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10301                         pris[span].trunkgroup);
10302                      destroy_dahdi_pvt(&tmp);
10303                      return NULL;
10304                   }
10305 
10306                   pris[span].sig = chan_sig;
10307                   pris[span].nodetype = conf->pri.nodetype;
10308                   pris[span].switchtype = myswitchtype;
10309                   pris[span].nsf = conf->pri.nsf;
10310                   pris[span].dialplan = conf->pri.dialplan;
10311                   pris[span].localdialplan = conf->pri.localdialplan;
10312                   pris[span].pvts[pris[span].numchans++] = tmp;
10313                   pris[span].minunused = conf->pri.minunused;
10314                   pris[span].minidle = conf->pri.minidle;
10315                   pris[span].overlapdial = conf->pri.overlapdial;
10316                   pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10317                   pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10318 #ifdef HAVE_PRI_INBANDDISCONNECT
10319                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10320 #endif
10321                   pris[span].facilityenable = conf->pri.facilityenable;
10322                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10323                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10324                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10325                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10326                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10327                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10328                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10329                   pris[span].resetinterval = conf->pri.resetinterval;
10330 
10331                   tmp->pri = &pris[span];
10332                   tmp->prioffset = offset;
10333                   tmp->call = NULL;
10334                } else {
10335                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10336                   destroy_dahdi_pvt(&tmp);
10337                   return NULL;
10338                }
10339             }
10340          } else {
10341             tmp->prioffset = 0;
10342          }
10343 #endif
10344       } else {
10345          chan_sig = tmp->sig;
10346          if (tmp->subs[SUB_REAL].dfd > -1) {
10347             memset(&p, 0, sizeof(p));
10348             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10349          }
10350       }
10351       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10352       switch (chan_sig) {
10353       case SIG_FXSKS:
10354       case SIG_FXSLS:
10355       case SIG_EM:
10356       case SIG_EM_E1:
10357       case SIG_EMWINK:
10358       case SIG_FEATD:
10359       case SIG_FEATDMF:
10360       case SIG_FEATDMF_TA:
10361       case SIG_FEATB:
10362       case SIG_E911:
10363       case SIG_SF:
10364       case SIG_SFWINK:
10365       case SIG_FGC_CAMA:
10366       case SIG_FGC_CAMAMF:
10367       case SIG_SF_FEATD:
10368       case SIG_SF_FEATDMF:
10369       case SIG_SF_FEATB:
10370          p.starttime = 250;
10371          break;
10372       }
10373 
10374       if (tmp->radio) {
10375          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10376          p.channo = channel;
10377          p.rxwinktime = 1;
10378          p.rxflashtime = 1;
10379          p.starttime = 1;
10380          p.debouncetime = 5;
10381       }
10382       if (!tmp->radio) {
10383          p.channo = channel;
10384          /* Override timing settings based on config file */
10385          if (conf->timing.prewinktime >= 0)
10386             p.prewinktime = conf->timing.prewinktime;
10387          if (conf->timing.preflashtime >= 0)
10388             p.preflashtime = conf->timing.preflashtime;
10389          if (conf->timing.winktime >= 0)
10390             p.winktime = conf->timing.winktime;
10391          if (conf->timing.flashtime >= 0)
10392             p.flashtime = conf->timing.flashtime;
10393          if (conf->timing.starttime >= 0)
10394             p.starttime = conf->timing.starttime;
10395          if (conf->timing.rxwinktime >= 0)
10396             p.rxwinktime = conf->timing.rxwinktime;
10397          if (conf->timing.rxflashtime >= 0)
10398             p.rxflashtime = conf->timing.rxflashtime;
10399          if (conf->timing.debouncetime >= 0)
10400             p.debouncetime = conf->timing.debouncetime;
10401       }
10402 
10403       /* dont set parms on a pseudo-channel (or CRV) */
10404       if (tmp->subs[SUB_REAL].dfd >= 0)
10405       {
10406          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10407          if (res < 0) {
10408             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10409             destroy_dahdi_pvt(&tmp);
10410             return NULL;
10411          }
10412       }
10413 #if 1
10414       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10415          memset(&bi, 0, sizeof(bi));
10416          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10417          if (!res) {
10418             bi.txbufpolicy = conf->chan.buf_policy;
10419             bi.rxbufpolicy = conf->chan.buf_policy;
10420             bi.numbufs = conf->chan.buf_no;
10421             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10422             if (res < 0) {
10423                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10424             }
10425          } else {
10426             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10427          }
10428          tmp->buf_policy = conf->chan.buf_policy;
10429          tmp->buf_no = conf->chan.buf_no;
10430          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10431          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10432          tmp->faxbuf_no = conf->chan.faxbuf_no;
10433          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10434           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10435           * The reason the ioctl call above failed should to be determined before worrying about the
10436           * faxbuffer-related ioctl calls */
10437          tmp->bufsize = bi.bufsize;
10438       }
10439 #endif
10440       tmp->immediate = conf->chan.immediate;
10441       tmp->transfertobusy = conf->chan.transfertobusy;
10442       if (chan_sig & __DAHDI_SIG_FXS) {
10443          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10444          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10445          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10446       }
10447       tmp->sig = chan_sig;
10448       tmp->outsigmod = conf->chan.outsigmod;
10449       tmp->ringt_base = ringt_base;
10450       tmp->firstradio = 0;
10451       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10452          tmp->permcallwaiting = conf->chan.callwaiting;
10453       else
10454          tmp->permcallwaiting = 0;
10455       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10456       tmp->destroy = 0;
10457       tmp->drings = conf->chan.drings;
10458 
10459       /* 10 is a nice default. */
10460       if (tmp->drings.ringnum[0].range == 0)
10461          tmp->drings.ringnum[0].range = 10;
10462       if (tmp->drings.ringnum[1].range == 0)
10463          tmp->drings.ringnum[1].range = 10;
10464       if (tmp->drings.ringnum[2].range == 0)
10465          tmp->drings.ringnum[2].range = 10;
10466 
10467       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10468       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10469       tmp->threewaycalling = conf->chan.threewaycalling;
10470       tmp->adsi = conf->chan.adsi;
10471       tmp->use_smdi = conf->chan.use_smdi;
10472       tmp->permhidecallerid = conf->chan.hidecallerid;
10473       tmp->hidecalleridname = conf->chan.hidecalleridname;
10474       tmp->callreturn = conf->chan.callreturn;
10475       tmp->echocancel = conf->chan.echocancel;
10476       tmp->echotraining = conf->chan.echotraining;
10477       tmp->pulse = conf->chan.pulse;
10478       if (tmp->echocancel.head.tap_length) {
10479          tmp->echocanbridged = conf->chan.echocanbridged;
10480       } else {
10481          if (conf->chan.echocanbridged)
10482             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10483          tmp->echocanbridged = 0;
10484       }
10485       tmp->busydetect = conf->chan.busydetect;
10486       tmp->busycount = conf->chan.busycount;
10487       tmp->busy_tonelength = conf->chan.busy_tonelength;
10488       tmp->busy_quietlength = conf->chan.busy_quietlength;
10489       tmp->callprogress = conf->chan.callprogress;
10490       tmp->waitfordialtone = conf->chan.waitfordialtone;
10491       tmp->cancallforward = conf->chan.cancallforward;
10492       tmp->dtmfrelax = conf->chan.dtmfrelax;
10493       tmp->callwaiting = tmp->permcallwaiting;
10494       tmp->hidecallerid = tmp->permhidecallerid;
10495       tmp->channel = channel;
10496       tmp->stripmsd = conf->chan.stripmsd;
10497       tmp->use_callerid = conf->chan.use_callerid;
10498       tmp->cid_signalling = conf->chan.cid_signalling;
10499       tmp->cid_start = conf->chan.cid_start;
10500       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10501       tmp->restrictcid = conf->chan.restrictcid;
10502       tmp->use_callingpres = conf->chan.use_callingpres;
10503       tmp->priexclusive = conf->chan.priexclusive;
10504       if (tmp->usedistinctiveringdetection) {
10505          if (!tmp->use_callerid) {
10506             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10507             tmp->use_callerid = 1;
10508          }
10509       }
10510 
10511       if (tmp->cid_signalling == CID_SIG_SMDI) {
10512          if (!tmp->use_smdi) {
10513             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10514             tmp->use_smdi = 1;
10515          }
10516       }
10517       if (tmp->use_smdi) {
10518          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10519          if (!(tmp->smdi_iface)) {
10520             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10521             tmp->use_smdi = 0;
10522          }
10523       }
10524 
10525       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10526       tmp->amaflags = conf->chan.amaflags;
10527       if (!here) {
10528          tmp->confno = -1;
10529          tmp->propconfno = -1;
10530       }
10531       tmp->canpark = conf->chan.canpark;
10532       tmp->transfer = conf->chan.transfer;
10533       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10534       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10535       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10536       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10537       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10538       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10539       tmp->cid_ton = 0;
10540       switch (tmp->sig) {
10541       case SIG_PRI:
10542       case SIG_BRI:
10543       case SIG_BRI_PTMP:
10544       case SIG_SS7:
10545       case SIG_MFCR2:
10546          tmp->cid_num[0] = '\0';
10547          tmp->cid_name[0] = '\0';
10548          break;
10549       default:
10550          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10551          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10552          break;
10553       }
10554       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10555       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10556          char *mailbox, *context;
10557          mailbox = context = ast_strdupa(tmp->mailbox);
10558          strsep(&context, "@");
10559          if (ast_strlen_zero(context))
10560             context = "default";
10561          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10562             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10563             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10564             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10565             AST_EVENT_IE_END);
10566       }
10567       tmp->msgstate = -1;
10568 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10569       tmp->mwisend_setting = conf->chan.mwisend_setting;
10570       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
10571       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10572 #endif
10573       if (chan_sig & __DAHDI_SIG_FXO) {
10574          memset(&p, 0, sizeof(p));
10575          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10576          if (!res) {
10577             tmp->fxsoffhookstate = p.rxisoffhook;
10578          }
10579 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10580          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10581 #endif
10582       }
10583       tmp->onhooktime = time(NULL);
10584       tmp->group = conf->chan.group;
10585       tmp->callgroup = conf->chan.callgroup;
10586       tmp->pickupgroup= conf->chan.pickupgroup;
10587       if (conf->chan.vars) {
10588          struct ast_variable *v, *tmpvar;
10589                    for (v = conf->chan.vars ; v ; v = v->next) {
10590                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10591                                   tmpvar->next = tmp->vars;
10592                                    tmp->vars = tmpvar;
10593                            }
10594                   }
10595       }
10596       tmp->cid_rxgain = conf->chan.cid_rxgain;
10597       tmp->rxgain = conf->chan.rxgain;
10598       tmp->txgain = conf->chan.txgain;
10599       tmp->tonezone = conf->chan.tonezone;
10600       if (tmp->subs[SUB_REAL].dfd > -1) {
10601          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10602          if (tmp->dsp)
10603             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10604          update_conf(tmp);
10605          if (!here) {
10606             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10607                 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10608                /* Hang it up to be sure it's good */
10609                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10610          }
10611          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10612 #ifdef HAVE_PRI
10613          /* the dchannel is down so put the channel in alarm */
10614          if (tmp->pri && !pri_is_up(tmp->pri))
10615             tmp->inalarm = 1;
10616 #endif
10617          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10618             tmp->inalarm = 1;
10619             handle_alarms(tmp, res);
10620          }
10621       }
10622 
10623       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10624       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10625       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10626       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10627       if (!here) {
10628          tmp->locallyblocked = tmp->remotelyblocked = 0;
10629          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10630             tmp->inservice = 0;
10631          else /* We default to in service on protocols that don't have a reset */
10632             tmp->inservice = 1;
10633       }
10634    }
10635    if (tmp && !here) {
10636       /* nothing on the iflist */
10637       if (!*wlist) {
10638          *wlist = tmp;
10639          tmp->prev = NULL;
10640          tmp->next = NULL;
10641          *wend = tmp;
10642       } else {
10643          /* at least one member on the iflist */
10644          struct dahdi_pvt *working = *wlist;
10645 
10646          /* check if we maybe have to put it on the begining */
10647          if (working->channel > tmp->channel) {
10648             tmp->next = *wlist;
10649             tmp->prev = NULL;
10650             (*wlist)->prev = tmp;
10651             *wlist = tmp;
10652          } else {
10653          /* go through all the members and put the member in the right place */
10654             while (working) {
10655                /* in the middle */
10656                if (working->next) {
10657                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10658                      tmp->next = working->next;
10659                      tmp->prev = working;
10660                      working->next->prev = tmp;
10661                      working->next = tmp;
10662                      break;
10663                   }
10664                } else {
10665                /* the last */
10666                   if (working->channel < tmp->channel) {
10667                      working->next = tmp;
10668                      tmp->next = NULL;
10669                      tmp->prev = working;
10670                      *wend = tmp;
10671                      break;
10672                   }
10673                }
10674                working = working->next;
10675             }
10676          }
10677       }
10678    }
10679    return tmp;
10680 }
10681 
10682 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10683 {
10684    int res;
10685    struct dahdi_params par;
10686 
10687    /* First, check group matching */
10688    if (groupmatch) {
10689       if ((p->group & groupmatch) != groupmatch)
10690          return 0;
10691       *groupmatched = 1;
10692    }
10693    /* Check to see if we have a channel match */
10694    if (channelmatch != -1) {
10695       if (p->channel != channelmatch)
10696          return 0;
10697       *channelmatched = 1;
10698    }
10699    /* We're at least busy at this point */
10700    if (busy) {
10701       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10702          *busy = 1;
10703    }
10704    /* If do not disturb, definitely not */
10705    if (p->dnd)
10706       return 0;
10707    /* If guard time, definitely not */
10708    if (p->guardtime && (time(NULL) < p->guardtime))
10709       return 0;
10710 
10711    if (p->locallyblocked || p->remotelyblocked)
10712       return 0;
10713 
10714    /* If no owner definitely available */
10715    if (!p->owner) {
10716 #ifdef HAVE_PRI
10717       /* Trust PRI */
10718       if (p->pri) {
10719          if (p->resetting || p->call)
10720             return 0;
10721          else
10722             return 1;
10723       }
10724 #endif
10725 #ifdef HAVE_SS7
10726       /* Trust SS7 */
10727       if (p->ss7) {
10728          if (p->ss7call)
10729             return 0;
10730          else
10731             return 1;
10732       }
10733 #endif
10734 #ifdef HAVE_OPENR2
10735       /* Trust MFC/R2 */
10736       if (p->mfcr2) {
10737          if (p->mfcr2call)
10738             return 0;
10739          else
10740             return 1;
10741       }
10742 #endif
10743       if (!(p->radio || (p->oprmode < 0)))
10744       {
10745          if (!p->sig || (p->sig == SIG_FXSLS))
10746             return 1;
10747          /* Check hook state */
10748          if (p->subs[SUB_REAL].dfd > -1) {
10749             memset(&par, 0, sizeof(par));
10750             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10751          } else {
10752             /* Assume not off hook on CVRS */
10753             res = 0;
10754             par.rxisoffhook = 0;
10755          }
10756          if (res) {
10757             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10758          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
10759             /* When "onhook" that means no battery on the line, and thus
10760               it is out of service..., if it's on a TDM card... If it's a channel
10761               bank, there is no telling... */
10762             if (par.rxbits > -1)
10763                return 1;
10764             if (par.rxisoffhook)
10765                return 1;
10766             else
10767                return 0;
10768          } else if (par.rxisoffhook) {
10769             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10770             /* Not available when the other end is off hook */
10771 #ifdef DAHDI_CHECK_HOOKSTATE
10772             return 0;
10773 #else
10774             return 1;
10775 #endif
10776          }
10777       }
10778       return 1;
10779    }
10780 
10781    /* If it's not an FXO, forget about call wait */
10782    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10783       return 0;
10784 
10785    if (!p->callwaiting) {
10786       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
10787       return 0;
10788    }
10789 
10790    if (p->subs[SUB_CALLWAIT].dfd > -1) {
10791       /* If there is already a call waiting call, then we can't take a second one */
10792       return 0;
10793    }
10794 
10795    if ((p->owner->_state != AST_STATE_UP) &&
10796       ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10797       /* If the current call is not up, then don't allow the call */
10798       return 0;
10799    }
10800    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10801       /* Can't take a call wait when the three way calling hasn't been merged yet. */
10802       return 0;
10803    }
10804    /* We're cool */
10805    return 1;
10806 }
10807 
10808 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
10809    structures; it makes no attempt to safely copy regular channel private
10810    structures that might contain reference-counted object pointers and other
10811    scary bits
10812 */
10813 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10814 {
10815    struct dahdi_pvt *p;
10816    struct dahdi_bufferinfo bi;
10817    int res;
10818 
10819    if ((p = ast_malloc(sizeof(*p)))) {
10820       memcpy(p, src, sizeof(struct dahdi_pvt));
10821       ast_mutex_init(&p->lock);
10822       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10823       if (p->subs[SUB_REAL].dfd < 0) {
10824          ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10825          destroy_dahdi_pvt(&p);
10826          return NULL;
10827       }
10828       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10829       if (!res) {
10830          bi.txbufpolicy = src->buf_policy;
10831          bi.rxbufpolicy = src->buf_policy;
10832          bi.numbufs = src->buf_no;
10833          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10834          if (res < 0) {
10835             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10836          }
10837       } else
10838          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10839    }
10840    p->destroy = 1;
10841    p->next = iflist;
10842    p->prev = NULL;
10843    iflist = p;
10844    if (iflist->next)
10845       iflist->next->prev = p;
10846    return p;
10847 }
10848 
10849 #if defined(HAVE_PRI)
10850 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10851 {
10852    int x;
10853    if (backwards)
10854       x = pri->numchans;
10855    else
10856       x = 0;
10857    for (;;) {
10858       if (backwards && (x < 0))
10859          break;
10860       if (!backwards && (x >= pri->numchans))
10861          break;
10862       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10863          ast_debug(1, "Found empty available channel %d/%d\n",
10864             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10865          return x;
10866       }
10867       if (backwards)
10868          x--;
10869       else
10870          x++;
10871    }
10872    return -1;
10873 }
10874 #endif   /* defined(HAVE_PRI) */
10875 
10876 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10877 {
10878    ast_group_t groupmatch = 0;
10879    int channelmatch = -1;
10880    int roundrobin = 0;
10881    int callwait = 0;
10882    int busy = 0;
10883    struct dahdi_pvt *p;
10884    struct ast_channel *tmp = NULL;
10885    char *dest=NULL;
10886    int x;
10887    char *s;
10888    char opt=0;
10889    int res=0, y=0;
10890    int backwards = 0;
10891 #ifdef HAVE_PRI
10892    int crv;
10893    int bearer = -1;
10894    int trunkgroup;
10895    struct dahdi_pri *pri=NULL;
10896 #endif
10897    struct dahdi_pvt *exitpvt, *start, *end;
10898    ast_mutex_t *lock;
10899    int channelmatched = 0;
10900    int groupmatched = 0;
10901 
10902    /*
10903     * data is ---v
10904     * Dial(DAHDI/pseudo[/extension])
10905     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
10906     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
10907     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
10908     *
10909     * g - channel group allocation search forward
10910     * G - channel group allocation search backward
10911     * r - channel group allocation round robin search forward
10912     * R - channel group allocation round robin search backward
10913     *
10914     * c - Wait for DTMF digit to confirm answer
10915     * r<cadance#> - Set distintive ring cadance number
10916     * d - Force bearer capability for ISDN/SS7 call to digital.
10917     */
10918 
10919    /* Assume we're locking the iflock */
10920    lock = &iflock;
10921    start = iflist;
10922    end = ifend;
10923    if (data) {
10924       dest = ast_strdupa((char *)data);
10925    } else {
10926       ast_log(LOG_WARNING, "Channel requested with no data\n");
10927       return NULL;
10928    }
10929    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10930       /* Retrieve the group number */
10931       char *stringp;
10932 
10933       stringp = dest + 1;
10934       s = strsep(&stringp, "/");
10935       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10936          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10937          return NULL;
10938       }
10939       groupmatch = ((ast_group_t) 1 << x);
10940       if (toupper(dest[0]) == 'G') {
10941          if (dest[0] == 'G') {
10942             backwards = 1;
10943             p = ifend;
10944          } else
10945             p = iflist;
10946       } else {
10947          if (dest[0] == 'R') {
10948             backwards = 1;
10949             p = round_robin[x]?round_robin[x]->prev:ifend;
10950             if (!p)
10951                p = ifend;
10952          } else {
10953             p = round_robin[x]?round_robin[x]->next:iflist;
10954             if (!p)
10955                p = iflist;
10956          }
10957          roundrobin = 1;
10958       }
10959    } else {
10960       char *stringp;
10961 
10962       stringp = dest;
10963       s = strsep(&stringp, "/");
10964       p = iflist;
10965       if (!strcasecmp(s, "pseudo")) {
10966          /* Special case for pseudo */
10967          x = CHAN_PSEUDO;
10968          channelmatch = x;
10969       }
10970 #ifdef HAVE_PRI
10971       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10972          if ((trunkgroup < 1) || (crv < 1)) {
10973             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10974             return NULL;
10975          }
10976          res--;
10977          for (x = 0; x < NUM_SPANS; x++) {
10978             if (pris[x].trunkgroup == trunkgroup) {
10979                pri = pris + x;
10980                lock = &pri->lock;
10981                start = pri->crvs;
10982                end = pri->crvend;
10983                break;
10984             }
10985          }
10986          if (!pri) {
10987             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10988             return NULL;
10989          }
10990          channelmatch = crv;
10991          p = pris[x].crvs;
10992       }
10993 #endif
10994       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10995          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10996          return NULL;
10997       } else {
10998          channelmatch = x;
10999       }
11000    }
11001    /* Search for an unowned channel */
11002    ast_mutex_lock(lock);
11003    exitpvt = p;
11004    while (p && !tmp) {
11005       if (roundrobin)
11006          round_robin[x] = p;
11007 #if 0
11008       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11009 #endif
11010 
11011       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11012          ast_debug(1, "Using channel %d\n", p->channel);
11013          if (p->inalarm)
11014             goto next;
11015 
11016          callwait = (p->owner != NULL);
11017 #ifdef HAVE_PRI
11018          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11019             if (p->sig != SIG_FXSKS) {
11020                /* Gotta find an actual channel to use for this
11021                   CRV if this isn't a callwait */
11022                bearer = pri_find_empty_chan(pri, 0);
11023                if (bearer < 0) {
11024                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11025                   p = NULL;
11026                   break;
11027                }
11028                pri_assign_bearer(p, pri, pri->pvts[bearer]);
11029             } else {
11030                if (alloc_sub(p, 0)) {
11031                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11032                   p = NULL;
11033                   break;
11034                } else
11035                   ast_debug(1, "Allocated placeholder pseudo channel\n");
11036 
11037                p->pri = pri;
11038             }
11039          }
11040 #endif
11041 #ifdef HAVE_OPENR2
11042          if (p->mfcr2) {
11043             ast_mutex_lock(&p->lock);
11044             if (p->mfcr2call) {
11045                ast_mutex_unlock(&p->lock);
11046                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11047                goto next;
11048             }
11049             p->mfcr2call = 1;
11050             ast_mutex_unlock(&p->lock);
11051          }
11052 #endif
11053          if (p->channel == CHAN_PSEUDO) {
11054             p = duplicate_pseudo(p);
11055             if (!p) {
11056                break;
11057             }
11058          }
11059          if (p->owner) {
11060             if (alloc_sub(p, SUB_CALLWAIT)) {
11061                p = NULL;
11062                break;
11063             }
11064          }
11065          p->outgoing = 1;
11066          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11067          if (!tmp) {
11068             p->outgoing = 0;
11069          }
11070 #ifdef HAVE_PRI
11071          if (p->bearer) {
11072             /* Log owner to bearer channel, too */
11073             p->bearer->owner = tmp;
11074          }
11075 #endif
11076          /* Make special notes */
11077          if (res > 1) {
11078             if (opt == 'c') {
11079                /* Confirm answer */
11080                p->confirmanswer = 1;
11081             } else if (opt == 'r') {
11082                /* Distinctive ring */
11083                if (res < 3)
11084                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11085                else
11086                   p->distinctivering = y;
11087             } else if (opt == 'd') {
11088                /* If this is an ISDN call, make it digital */
11089                p->digital = 1;
11090                if (tmp)
11091                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11092             } else {
11093                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11094             }
11095          }
11096          /* Note if the call is a call waiting call */
11097          if (tmp && callwait)
11098             tmp->cdrflags |= AST_CDR_CALLWAIT;
11099          break;
11100       }
11101 next:
11102       if (backwards) {
11103          p = p->prev;
11104          if (!p)
11105             p = end;
11106       } else {
11107          p = p->next;
11108          if (!p)
11109             p = start;
11110       }
11111       /* stop when you roll to the one that we started from */
11112       if (p == exitpvt)
11113          break;
11114    }
11115    ast_mutex_unlock(lock);
11116    restart_monitor();
11117    if (callwait)
11118       *cause = AST_CAUSE_BUSY;
11119    else if (!tmp) {
11120       if (channelmatched) {
11121          if (busy)
11122             *cause = AST_CAUSE_BUSY;
11123       } else if (groupmatched) {
11124          *cause = AST_CAUSE_CONGESTION;
11125       }
11126    }
11127 
11128    return tmp;
11129 }
11130 
11131 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11132 static int dahdi_setlaw(int dfd, int law)
11133 {
11134    return ioctl(dfd, DAHDI_SETLAW, &law);
11135 }
11136 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
11137 
11138 #if defined(HAVE_SS7)
11139 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11140 {
11141    int i;
11142    int winner = -1;
11143    for (i = 0; i < linkset->numchans; i++) {
11144       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11145          winner = i;
11146          break;
11147       }
11148    }
11149    return winner;
11150 }
11151 #endif   /* defined(HAVE_SS7) */
11152 
11153 #if defined(HAVE_SS7)
11154 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11155 {
11156    unsigned char status[32];
11157    struct dahdi_pvt *p = NULL;
11158    int i, offset;
11159 
11160    for (i = 0; i < linkset->numchans; i++) {
11161       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11162          p = linkset->pvts[i];
11163          offset = p->cic - startcic;
11164          status[offset] = 0;
11165          if (p->locallyblocked)
11166             status[offset] |= (1 << 0) | (1 << 4);
11167          if (p->remotelyblocked)
11168             status[offset] |= (1 << 1) | (1 << 5);
11169          if (p->ss7call) {
11170             if (p->outgoing)
11171                status[offset] |= (1 << 3);
11172             else
11173                status[offset] |= (1 << 2);
11174          } else
11175             status[offset] |= 0x3 << 2;
11176       }
11177    }
11178 
11179    if (p)
11180       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11181    else
11182       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11183 
11184 }
11185 #endif   /* defined(HAVE_SS7) */
11186 
11187 #if defined(HAVE_SS7)
11188 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11189 {
11190    int i;
11191 
11192    for (i = 0; i < linkset->numchans; i++) {
11193       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11194          ast_mutex_lock(&linkset->pvts[i]->lock);
11195          if (linkset->pvts[i]->owner)
11196             linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11197          ast_mutex_unlock(&linkset->pvts[i]->lock);
11198       }
11199    }
11200 }
11201 #endif   /* defined(HAVE_SS7) */
11202 
11203 #if defined(HAVE_SS7)
11204 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11205 {
11206    int i;
11207 
11208    for (i = 0; i < linkset->numchans; i++) {
11209       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11210          if (state) {
11211             if (state[i])
11212                linkset->pvts[i]->remotelyblocked = block;
11213          } else
11214             linkset->pvts[i]->remotelyblocked = block;
11215       }
11216    }
11217 }
11218 #endif   /* defined(HAVE_SS7) */
11219 
11220 #if defined(HAVE_SS7)
11221 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11222 {
11223    int i;
11224 
11225    for (i = 0; i < linkset->numchans; i++) {
11226       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11227          linkset->pvts[i]->inservice = 1;
11228    }
11229 }
11230 #endif   /* defined(HAVE_SS7) */
11231 
11232 #if defined(HAVE_SS7)
11233 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11234 {
11235    int i, startcic = -1, endcic, dpc;
11236 
11237    if (linkset->numchans <= 0)
11238       return;
11239 
11240    startcic = linkset->pvts[0]->cic;
11241    /* DB: CIC's DPC fix */
11242    dpc = linkset->pvts[0]->dpc;
11243 
11244    for (i = 0; i < linkset->numchans; i++) {
11245       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)) {
11246          continue;
11247       } else {
11248          endcic = linkset->pvts[i]->cic;
11249          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11250          isup_grs(linkset->ss7, startcic, endcic, dpc);
11251 
11252          /* DB: CIC's DPC fix */
11253          if (linkset->pvts[i+1]) {
11254             startcic = linkset->pvts[i+1]->cic;
11255             dpc = linkset->pvts[i+1]->dpc;
11256          }
11257       }
11258    }
11259 }
11260 #endif   /* defined(HAVE_SS7) */
11261 
11262 #if defined(HAVE_SS7)
11263 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11264 {
11265    if (p->loopedback != enable) {
11266       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11267          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11268          return;
11269       }
11270       p->loopedback = enable;
11271    }
11272 }
11273 #endif   /* defined(HAVE_SS7) */
11274 
11275 #if defined(HAVE_SS7)
11276 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
11277 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11278 {
11279    struct ss7 *ss7 = linkset->ss7;
11280    int res;
11281    int law = 1;
11282    struct ast_channel *c;
11283    char tmp[256];
11284 
11285    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11286       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11287 
11288    if (linkset->type == SS7_ITU)
11289       law = DAHDI_LAW_ALAW;
11290    else
11291       law = DAHDI_LAW_MULAW;
11292 
11293    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11294    if (res < 0)
11295       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11296 
11297    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11298       p->proceeding = 1;
11299       isup_acm(ss7, p->ss7call);
11300    }
11301 
11302    ast_mutex_unlock(&linkset->lock);
11303    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11304 
11305    if (!c) {
11306       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11307       /* Holding this lock is assumed entering the function */
11308       ast_mutex_lock(&linkset->lock);
11309       return;
11310    } else
11311       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11312 
11313    dahdi_enable_ec(p);
11314 
11315    /* We only reference these variables in the context of the ss7_linkset function
11316     * when receiving either and IAM or a COT message.  Since they are only accessed
11317     * from this context, we should be safe to unlock around them */
11318 
11319    ast_mutex_unlock(&p->lock);
11320 
11321    if (!ast_strlen_zero(p->charge_number)) {
11322       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11323       /* Clear this after we set it */
11324       p->charge_number[0] = 0;
11325    }
11326    if (!ast_strlen_zero(p->gen_add_number)) {
11327       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11328       /* Clear this after we set it */
11329       p->gen_add_number[0] = 0;
11330    }
11331    if (!ast_strlen_zero(p->jip_number)) {
11332       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11333       /* Clear this after we set it */
11334       p->jip_number[0] = 0;
11335    }
11336    if (!ast_strlen_zero(p->gen_dig_number)) {
11337       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11338       /* Clear this after we set it */
11339       p->gen_dig_number[0] = 0;
11340    }
11341    if (!ast_strlen_zero(p->orig_called_num)) {
11342       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11343       /* Clear this after we set it */
11344       p->orig_called_num[0] = 0;
11345    }
11346 
11347    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11348    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11349    /* Clear this after we set it */
11350    p->gen_dig_type = 0;
11351 
11352    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11353    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11354    /* Clear this after we set it */
11355    p->gen_dig_scheme = 0;
11356 
11357    if (!ast_strlen_zero(p->lspi_ident)) {
11358       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11359       /* Clear this after we set it */
11360       p->lspi_ident[0] = 0;
11361    }
11362 
11363    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11364    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11365    /* Clear this after we set it */
11366    p->call_ref_ident = 0;
11367 
11368    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11369    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11370    /* Clear this after we set it */
11371    p->call_ref_pc = 0;
11372 
11373    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11374    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11375    /* Clear this after we set it */
11376    p->calling_party_cat = 0;
11377 
11378    if (!ast_strlen_zero(p->redirecting_num)) {
11379       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11380       /* Clear this after we set it */
11381       p->redirecting_num[0] = 0;
11382    }
11383    if (!ast_strlen_zero(p->generic_name)) {
11384       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11385       /* Clear this after we set it */
11386       p->generic_name[0] = 0;
11387    }
11388 
11389    ast_mutex_lock(&p->lock);
11390    ast_mutex_lock(&linkset->lock);
11391 }
11392 #endif   /* defined(HAVE_SS7) */
11393 
11394 #if defined(HAVE_SS7)
11395 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11396 {
11397    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
11398       if (size) {
11399          *buf = '\0';
11400       }
11401       return;
11402    }
11403    switch (nai) {
11404    case SS7_NAI_INTERNATIONAL:
11405       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11406       break;
11407    case SS7_NAI_NATIONAL:
11408       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11409       break;
11410    case SS7_NAI_SUBSCRIBER:
11411       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11412       break;
11413    case SS7_NAI_UNKNOWN:
11414       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11415       break;
11416    default:
11417       snprintf(buf, size, "%s", number);
11418       break;
11419    }
11420 }
11421 #endif   /* defined(HAVE_SS7) */
11422 
11423 #if defined(HAVE_SS7)
11424 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11425 {
11426    return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11427 }
11428 #endif   /* defined(HAVE_SS7) */
11429 
11430 #if defined(HAVE_SS7)
11431 static void *ss7_linkset(void *data)
11432 {
11433    int res, i;
11434    struct timeval *next = NULL, tv;
11435    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11436    struct ss7 *ss7 = linkset->ss7;
11437    ss7_event *e = NULL;
11438    struct dahdi_pvt *p;
11439    int chanpos;
11440    struct pollfd pollers[NUM_DCHANS];
11441    int cic;
11442    unsigned int dpc;
11443    int nextms = 0;
11444 
11445    ss7_start(ss7);
11446 
11447    while(1) {
11448       ast_mutex_lock(&linkset->lock);
11449       if ((next = ss7_schedule_next(ss7))) {
11450          tv = ast_tvnow();
11451          tv.tv_sec = next->tv_sec - tv.tv_sec;
11452          tv.tv_usec = next->tv_usec - tv.tv_usec;
11453          if (tv.tv_usec < 0) {
11454             tv.tv_usec += 1000000;
11455             tv.tv_sec -= 1;
11456          }
11457          if (tv.tv_sec < 0) {
11458             tv.tv_sec = 0;
11459             tv.tv_usec = 0;
11460          }
11461          nextms = tv.tv_sec * 1000;
11462          nextms += tv.tv_usec / 1000;
11463       }
11464       ast_mutex_unlock(&linkset->lock);
11465 
11466       for (i = 0; i < linkset->numsigchans; i++) {
11467          pollers[i].fd = linkset->fds[i];
11468          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11469          pollers[i].revents = 0;
11470       }
11471 
11472       res = poll(pollers, linkset->numsigchans, nextms);
11473       if ((res < 0) && (errno != EINTR)) {
11474          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11475       } else if (!res) {
11476          ast_mutex_lock(&linkset->lock);
11477          ss7_schedule_run(ss7);
11478          ast_mutex_unlock(&linkset->lock);
11479          continue;
11480       }
11481 
11482       ast_mutex_lock(&linkset->lock);
11483       for (i = 0; i < linkset->numsigchans; i++) {
11484          if (pollers[i].revents & POLLPRI) {
11485             int x;
11486             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11487                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11488             }
11489             switch (x) {
11490             case DAHDI_EVENT_OVERRUN:
11491                ast_debug(1, "Overrun detected!\n");
11492                break;
11493             case DAHDI_EVENT_BADFCS:
11494                ast_debug(1, "Bad FCS\n");
11495                break;
11496             case DAHDI_EVENT_ABORT:
11497                ast_debug(1, "HDLC Abort\n");
11498                break;
11499             case DAHDI_EVENT_ALARM:
11500                ast_log(LOG_ERROR, "Alarm on link!\n");
11501                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11502                linkset->linkstate[i] &= ~LINKSTATE_UP;
11503                ss7_link_alarm(ss7, pollers[i].fd);
11504                break;
11505             case DAHDI_EVENT_NOALARM:
11506                ast_log(LOG_ERROR, "Alarm cleared on link\n");
11507                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11508                linkset->linkstate[i] |= LINKSTATE_STARTING;
11509                ss7_link_noalarm(ss7, pollers[i].fd);
11510                break;
11511             default:
11512                ast_log(LOG_ERROR, "Got exception %d!\n", x);
11513                break;
11514             }
11515          }
11516 
11517          if (pollers[i].revents & POLLIN) {
11518             res = ss7_read(ss7, pollers[i].fd);
11519          }
11520 
11521          if (pollers[i].revents & POLLOUT) {
11522             res = ss7_write(ss7, pollers[i].fd);
11523             if (res < 0) {
11524                ast_debug(1, "Error in write %s\n", strerror(errno));
11525             }
11526          }
11527       }
11528 
11529       while ((e = ss7_check_event(ss7))) {
11530          switch (e->e) {
11531          case SS7_EVENT_UP:
11532             if (linkset->state != LINKSET_STATE_UP) {
11533                ast_verbose("--- SS7 Up ---\n");
11534                ss7_reset_linkset(linkset);
11535             }
11536             linkset->state = LINKSET_STATE_UP;
11537             break;
11538          case SS7_EVENT_DOWN:
11539             ast_verbose("--- SS7 Down ---\n");
11540             linkset->state = LINKSET_STATE_DOWN;
11541             for (i = 0; i < linkset->numchans; i++) {
11542                struct dahdi_pvt *p = linkset->pvts[i];
11543                if (p)
11544                   p->inalarm = 1;
11545             }
11546             break;
11547          case MTP2_LINK_UP:
11548             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11549             break;
11550          case MTP2_LINK_DOWN:
11551             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11552             break;
11553          case ISUP_EVENT_CPG:
11554             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11555             if (chanpos < 0) {
11556                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11557                break;
11558             }
11559             p = linkset->pvts[chanpos];
11560             ast_mutex_lock(&p->lock);
11561             switch (e->cpg.event) {
11562             case CPG_EVENT_ALERTING:
11563                p->alerting = 1;
11564                p->subs[SUB_REAL].needringing = 1;
11565                break;
11566             case CPG_EVENT_PROGRESS:
11567             case CPG_EVENT_INBANDINFO:
11568                {
11569                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11570                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11571                   dahdi_queue_frame(p, &f, linkset);
11572                   p->progress = 1;
11573                   p->dialing = 0;
11574                   if (p->dsp && p->dsp_features) {
11575                      ast_dsp_set_features(p->dsp, p->dsp_features);
11576                      p->dsp_features = 0;
11577                   }
11578                }
11579                break;
11580             default:
11581                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11582             }
11583 
11584             ast_mutex_unlock(&p->lock);
11585             break;
11586          case ISUP_EVENT_RSC:
11587             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11588             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11589             if (chanpos < 0) {
11590                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11591                break;
11592             }
11593             p = linkset->pvts[chanpos];
11594             ast_mutex_lock(&p->lock);
11595             p->inservice = 1;
11596             p->remotelyblocked = 0;
11597             dpc = p->dpc;
11598             isup_set_call_dpc(e->rsc.call, dpc);
11599             if (p->ss7call)
11600                p->ss7call = NULL;
11601             if (p->owner)
11602                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11603             ast_mutex_unlock(&p->lock);
11604             isup_rlc(ss7, e->rsc.call);
11605             break;
11606          case ISUP_EVENT_GRS:
11607             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11608             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11609             if (chanpos < 0) {
11610                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11611                break;
11612             }
11613             p = linkset->pvts[chanpos];
11614             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11615             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11616             ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11617             break;
11618          case ISUP_EVENT_CQM:
11619             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11620             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11621             break;
11622          case ISUP_EVENT_GRA:
11623             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11624             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11625             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11626             break;
11627          case ISUP_EVENT_IAM:
11628             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);
11629             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11630             if (chanpos < 0) {
11631                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11632                isup_rel(ss7, e->iam.call, -1);
11633                break;
11634             }
11635             p = linkset->pvts[chanpos];
11636             ast_mutex_lock(&p->lock);
11637             if (p->owner) {
11638                if (p->ss7call == e->iam.call) {
11639                   ast_mutex_unlock(&p->lock);
11640                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11641                   break;
11642                } else {
11643                   ast_mutex_unlock(&p->lock);
11644                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11645                   break;
11646                }
11647             }
11648 
11649             dpc = p->dpc;
11650             p->ss7call = e->iam.call;
11651             isup_set_call_dpc(p->ss7call, dpc);
11652 
11653             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11654                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11655                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11656             } else
11657                p->cid_num[0] = 0;
11658 
11659             if (p->immediate) {
11660                p->exten[0] = 's';
11661                p->exten[1] = '\0';
11662             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11663                char *st;
11664                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11665                st = strchr(p->exten, '#');
11666                if (st)
11667                   *st = '\0';
11668                } else
11669                   p->exten[0] = '\0';
11670 
11671             p->cid_ani[0] = '\0';
11672             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11673                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11674             else
11675                p->cid_name[0] = '\0';
11676 
11677             p->cid_ani2 = e->iam.oli_ani2;
11678             p->cid_ton = 0;
11679             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11680             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11681             p->gen_add_type = e->iam.gen_add_type;
11682             p->gen_add_nai = e->iam.gen_add_nai;
11683             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11684             p->gen_add_num_plan = e->iam.gen_add_num_plan;
11685             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11686             p->gen_dig_type = e->iam.gen_dig_type;
11687             p->gen_dig_scheme = e->iam.gen_dig_scheme;
11688             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11689             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11690             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11691             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11692             p->calling_party_cat = e->iam.calling_party_cat;
11693 
11694             /* Set DNID */
11695             if (!ast_strlen_zero(e->iam.called_party_num))
11696                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11697 
11698             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11699 
11700                if (e->iam.cot_check_required) {
11701                   dahdi_loopback(p, 1);
11702                } else
11703                   ss7_start_call(p, linkset);
11704             } else {
11705                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11706                p->alreadyhungup = 1;
11707                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11708             }
11709             ast_mutex_unlock(&p->lock);
11710             break;
11711          case ISUP_EVENT_COT:
11712             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11713             if (chanpos < 0) {
11714                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11715                isup_rel(ss7, e->cot.call, -1);
11716                break;
11717             }
11718             p = linkset->pvts[chanpos];
11719 
11720             ast_mutex_lock(&p->lock);
11721 
11722             if (p->loopedback) {
11723                dahdi_loopback(p, 0);
11724                ss7_start_call(p, linkset);
11725             }
11726 
11727             ast_mutex_unlock(&p->lock);
11728 
11729             break;
11730          case ISUP_EVENT_CCR:
11731             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11732             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11733             if (chanpos < 0) {
11734                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11735                break;
11736             }
11737 
11738             p = linkset->pvts[chanpos];
11739 
11740             ast_mutex_lock(&p->lock);
11741             dahdi_loopback(p, 1);
11742             ast_mutex_unlock(&p->lock);
11743 
11744             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11745             break;
11746          case ISUP_EVENT_CVT:
11747             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11748             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11749             if (chanpos < 0) {
11750                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11751                break;
11752             }
11753 
11754             p = linkset->pvts[chanpos];
11755 
11756             ast_mutex_lock(&p->lock);
11757             dahdi_loopback(p, 1);
11758             ast_mutex_unlock(&p->lock);
11759 
11760             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11761             break;
11762          case ISUP_EVENT_REL:
11763             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11764             if (chanpos < 0) {
11765                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11766                break;
11767             }
11768             p = linkset->pvts[chanpos];
11769             ast_mutex_lock(&p->lock);
11770             if (p->owner) {
11771                p->owner->hangupcause = e->rel.cause;
11772                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11773             } else if (!p->restartpending)
11774                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11775 
11776             /* End the loopback if we have one */
11777             dahdi_loopback(p, 0);
11778 
11779             isup_rlc(ss7, e->rel.call);
11780             p->ss7call = NULL;
11781 
11782             ast_mutex_unlock(&p->lock);
11783             break;
11784          case ISUP_EVENT_ACM:
11785             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11786             if (chanpos < 0) {
11787                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11788                isup_rel(ss7, e->acm.call, -1);
11789                break;
11790             } else {
11791                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11792 
11793                p = linkset->pvts[chanpos];
11794 
11795                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11796 
11797                if (e->acm.call_ref_ident > 0) {
11798                   p->rlt = 1; /* Setting it but not using it here*/
11799                }
11800 
11801                ast_mutex_lock(&p->lock);
11802                dahdi_queue_frame(p, &f, linkset);
11803                p->proceeding = 1;
11804                p->dialing = 0;
11805                /* Send alerting if subscriber is free */
11806                if (e->acm.called_party_status_ind == 1) {
11807                   p->alerting = 1;
11808                   p->subs[SUB_REAL].needringing = 1;
11809                }
11810                ast_mutex_unlock(&p->lock);
11811             }
11812             break;
11813          case ISUP_EVENT_CGB:
11814             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11815             if (chanpos < 0) {
11816                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11817                break;
11818             }
11819             p = linkset->pvts[chanpos];
11820             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11821             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11822             break;
11823          case ISUP_EVENT_CGU:
11824             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11825             if (chanpos < 0) {
11826                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11827                break;
11828             }
11829             p = linkset->pvts[chanpos];
11830             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11831             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11832             break;
11833          case ISUP_EVENT_UCIC:
11834             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11835             if (chanpos < 0) {
11836                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11837                break;
11838             }
11839             p = linkset->pvts[chanpos];
11840             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11841             ast_mutex_lock(&p->lock);
11842             p->remotelyblocked = 1;
11843             p->inservice = 0;
11844             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
11845             break;
11846          case ISUP_EVENT_BLO:
11847             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11848             if (chanpos < 0) {
11849                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11850                break;
11851             }
11852             p = linkset->pvts[chanpos];
11853             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11854             ast_mutex_lock(&p->lock);
11855             p->remotelyblocked = 1;
11856             ast_mutex_unlock(&p->lock);
11857             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11858             break;
11859          case ISUP_EVENT_BLA:
11860             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11861             if (chanpos < 0) {
11862                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11863                break;
11864             }
11865             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11866             p = linkset->pvts[chanpos];
11867             ast_mutex_lock(&p->lock);
11868             p->locallyblocked = 1;
11869             ast_mutex_unlock(&p->lock);
11870             break;
11871          case ISUP_EVENT_UBL:
11872             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11873             if (chanpos < 0) {
11874                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11875                break;
11876             }
11877             p = linkset->pvts[chanpos];
11878             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11879             ast_mutex_lock(&p->lock);
11880             p->remotelyblocked = 0;
11881             ast_mutex_unlock(&p->lock);
11882             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11883             break;
11884          case ISUP_EVENT_UBA:
11885             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11886             if (chanpos < 0) {
11887                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11888                break;
11889             }
11890             p = linkset->pvts[chanpos];
11891             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11892             ast_mutex_lock(&p->lock);
11893             p->locallyblocked = 0;
11894             ast_mutex_unlock(&p->lock);
11895             break;
11896          case ISUP_EVENT_CON:
11897          case ISUP_EVENT_ANM:
11898             if (e->e == ISUP_EVENT_CON)
11899                cic = e->con.cic;
11900             else
11901                cic = e->anm.cic;
11902 
11903             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11904             if (chanpos < 0) {
11905                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11906                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11907                break;
11908             } else {
11909                p = linkset->pvts[chanpos];
11910                ast_mutex_lock(&p->lock);
11911                p->subs[SUB_REAL].needanswer = 1;
11912                if (p->dsp && p->dsp_features) {
11913                   ast_dsp_set_features(p->dsp, p->dsp_features);
11914                   p->dsp_features = 0;
11915                }
11916                dahdi_enable_ec(p);
11917                ast_mutex_unlock(&p->lock);
11918             }
11919             break;
11920          case ISUP_EVENT_RLC:
11921             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
11922             if (chanpos < 0) {
11923                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
11924                break;
11925             } else {
11926                p = linkset->pvts[chanpos];
11927                ast_mutex_lock(&p->lock);
11928                if (p->alreadyhungup)
11929                   p->ss7call = NULL;
11930                else
11931                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
11932                ast_mutex_unlock(&p->lock);
11933                }
11934                break;
11935          case ISUP_EVENT_FAA:
11936             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
11937             if (chanpos < 0) {
11938                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
11939                break;
11940             } else {
11941                p = linkset->pvts[chanpos];
11942                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
11943                ast_mutex_lock(&p->lock);
11944                if (p->alreadyhungup){
11945                   p->ss7call = NULL;
11946                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
11947                }
11948                ast_mutex_unlock(&p->lock);
11949             }
11950             break;
11951          default:
11952             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
11953             break;
11954          }
11955       }
11956       ast_mutex_unlock(&linkset->lock);
11957    }
11958 
11959    return 0;
11960 }
11961 #endif   /* defined(HAVE_SS7) */
11962 
11963 #if defined(HAVE_SS7)
11964 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
11965 {
11966 #if 0
11967    int i;
11968 
11969    for (i = 0; i < NUM_SPANS; i++)
11970       if (linksets[i].ss7 == ss7)
11971          break;
11972 
11973    ast_verbose("[%d] %s", i+1, s);
11974 #else
11975    ast_verbose("%s", s);
11976 #endif
11977 }
11978 #endif   /* defined(HAVE_SS7) */
11979 
11980 #if defined(HAVE_SS7)
11981 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
11982 {
11983 #if 0
11984    int i;
11985 
11986    for (i = 0; i < NUM_SPANS; i++)
11987       if (linksets[i].ss7 == ss7)
11988          break;
11989 
11990 #else
11991    ast_log(LOG_ERROR, "%s", s);
11992 #endif
11993 }
11994 #endif   /* defined(HAVE_SS7) */
11995 
11996 #if defined(HAVE_OPENR2)
11997 static void *mfcr2_monitor(void *data)
11998 {
11999    struct dahdi_mfcr2 *mfcr2 = data;
12000    /* we should be using pthread_key_create
12001       and allocate pollers dynamically.
12002       I think do_monitor() could be leaking, since it
12003       could be cancelled at any time and is not
12004       using thread keys, why?, */
12005    struct pollfd pollers[sizeof(mfcr2->pvts)];
12006    int res = 0;
12007    int i = 0;
12008    int oldstate = 0;
12009    int quit_loop = 0;
12010    int maxsleep = 20;
12011    int was_idle = 0;
12012    int pollsize = 0;
12013    /* now that we're ready to get calls, unblock our side and
12014       get current line state */
12015    for (i = 0; i < mfcr2->numchans; i++) {
12016       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12017       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12018    }
12019    while (1) {
12020       /* we trust here that the mfcr2 channel list will not ever change once
12021          the module is loaded */
12022       pollsize = 0;
12023       for (i = 0; i < mfcr2->numchans; i++) {
12024          pollers[i].revents = 0;
12025          pollers[i].events = 0;
12026          if (mfcr2->pvts[i]->owner) {
12027             continue;
12028          }
12029          if (!mfcr2->pvts[i]->r2chan) {
12030             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12031             quit_loop = 1;
12032             break;
12033          }
12034          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12035          pollers[i].events = POLLIN | POLLPRI;
12036          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12037          pollsize++;
12038       }
12039       if (quit_loop) {
12040          break;
12041       }
12042       if (pollsize == 0) {
12043          if (!was_idle) {
12044             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12045             was_idle = 1;
12046          }
12047          poll(NULL, 0, maxsleep);
12048          continue;
12049       }
12050       was_idle = 0;
12051       /* probably poll() is a valid cancel point, lets just be on the safe side
12052          by calling pthread_testcancel */
12053       pthread_testcancel();
12054       res = poll(pollers, mfcr2->numchans, maxsleep);
12055       pthread_testcancel();
12056       if ((res < 0) && (errno != EINTR)) {
12057          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12058          break;
12059       }
12060       /* do we want to allow to cancel while processing events? */
12061       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12062       for (i = 0; i < mfcr2->numchans; i++) {
12063          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12064             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12065          }
12066       }
12067       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12068    }
12069    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12070    return 0;
12071 }
12072 #endif /* HAVE_OPENR2 */
12073 
12074 #if defined(HAVE_PRI)
12075 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12076 {
12077    struct dahdi_pvt *p;
12078    p = pri->crvs;
12079    while (p) {
12080       if (p->channel == crv)
12081          return p;
12082       p = p->next;
12083    }
12084    return NULL;
12085 }
12086 #endif   /* defined(HAVE_PRI) */
12087 
12088 #if defined(HAVE_PRI)
12089 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12090 {
12091    int x;
12092    int span = PRI_SPAN(channel);
12093    int spanfd;
12094    struct dahdi_params param;
12095    int principle = -1;
12096    int explicit = PRI_EXPLICIT(channel);
12097    channel = PRI_CHANNEL(channel);
12098 
12099    if (!explicit) {
12100       spanfd = pri_active_dchan_fd(pri);
12101       memset(&param, 0, sizeof(param));
12102       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12103          return -1;
12104       span = pris[param.spanno - 1].prilogicalspan;
12105    }
12106 
12107    for (x = 0; x < pri->numchans; x++) {
12108       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12109          principle = x;
12110          break;
12111       }
12112    }
12113 
12114    return principle;
12115 }
12116 #endif   /* defined(HAVE_PRI) */
12117 
12118 #if defined(HAVE_PRI)
12119 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12120 {
12121    int x;
12122    struct dahdi_pvt *crv;
12123    if (!c) {
12124       if (principle < 0)
12125          return -1;
12126       return principle;
12127    }
12128    if ((principle > -1) &&
12129       (principle < pri->numchans) &&
12130       (pri->pvts[principle]) &&
12131       (pri->pvts[principle]->call == c))
12132       return principle;
12133    /* First, check for other bearers */
12134    for (x = 0; x < pri->numchans; x++) {
12135       if (!pri->pvts[x])
12136          continue;
12137       if (pri->pvts[x]->call == c) {
12138          /* Found our call */
12139          if (principle != x) {
12140             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12141 
12142             ast_verb(3, "Moving call from channel %d to channel %d\n",
12143                 old->channel, new->channel);
12144             if (new->owner) {
12145                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12146                   old->channel, new->channel, new->channel);
12147                return -1;
12148             }
12149             /* Fix it all up now */
12150             new->owner = old->owner;
12151             old->owner = NULL;
12152             if (new->owner) {
12153                ast_string_field_build(new->owner, name,
12154                   "DAHDI/%d:%d-%d", pri->trunkgroup,
12155                   new->channel, 1);
12156                new->owner->tech_pvt = new;
12157                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12158                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12159                old->subs[SUB_REAL].owner = NULL;
12160             } else
12161                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);
12162             new->call = old->call;
12163             old->call = NULL;
12164 
12165             /* Copy any DSP that may be present */
12166             new->dsp = old->dsp;
12167             new->dsp_features = old->dsp_features;
12168             old->dsp = NULL;
12169             old->dsp_features = 0;
12170          }
12171          return principle;
12172       }
12173    }
12174    /* Now check for a CRV with no bearer */
12175    crv = pri->crvs;
12176    while (crv) {
12177       if (crv->call == c) {
12178          /* This is our match...  Perform some basic checks */
12179          if (crv->bearer)
12180             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12181          else if (pri->pvts[principle]->owner)
12182             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12183          else {
12184             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
12185                wakeup the potential sleeper */
12186             dahdi_close_sub(crv, SUB_REAL);
12187             pri->pvts[principle]->call = crv->call;
12188             pri_assign_bearer(crv, pri, pri->pvts[principle]);
12189             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12190                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12191                pri->trunkgroup, crv->channel);
12192             wakeup_sub(crv, SUB_REAL, pri);
12193          }
12194          return principle;
12195       }
12196       crv = crv->next;
12197    }
12198    ast_log(LOG_WARNING, "Call specified, but not found?\n");
12199    return -1;
12200 }
12201 #endif   /* defined(HAVE_PRI) */
12202 
12203 #if defined(HAVE_PRI)
12204 static void *do_idle_thread(void *vchan)
12205 {
12206    struct ast_channel *chan = vchan;
12207    struct dahdi_pvt *pvt = chan->tech_pvt;
12208    struct ast_frame *f;
12209    char ex[80];
12210    /* Wait up to 30 seconds for an answer */
12211    int newms, ms = 30000;
12212    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12213    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12214    if (ast_call(chan, ex, 0)) {
12215       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12216       ast_hangup(chan);
12217       return NULL;
12218    }
12219    while ((newms = ast_waitfor(chan, ms)) > 0) {
12220       f = ast_read(chan);
12221       if (!f) {
12222          /* Got hangup */
12223          break;
12224       }
12225       if (f->frametype == AST_FRAME_CONTROL) {
12226          switch (f->subclass) {
12227          case AST_CONTROL_ANSWER:
12228             /* Launch the PBX */
12229             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12230             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12231             chan->priority = 1;
12232             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12233             ast_pbx_run(chan);
12234             /* It's already hungup, return immediately */
12235             return NULL;
12236          case AST_CONTROL_BUSY:
12237             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12238             break;
12239          case AST_CONTROL_CONGESTION:
12240             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12241             break;
12242          };
12243       }
12244       ast_frfree(f);
12245       ms = newms;
12246    }
12247    /* Hangup the channel since nothing happend */
12248    ast_hangup(chan);
12249    return NULL;
12250 }
12251 #endif   /* defined(HAVE_PRI) */
12252 
12253 #if defined(HAVE_PRI)
12254 #ifndef PRI_RESTART
12255 #error "Upgrade your libpri"
12256 #endif
12257 static void dahdi_pri_message(struct pri *pri, char *s)
12258 {
12259    int x, y;
12260    int dchan = -1, span = -1;
12261    int dchancount = 0;
12262 
12263    if (pri) {
12264       for (x = 0; x < NUM_SPANS; x++) {
12265          for (y = 0; y < NUM_DCHANS; y++) {
12266             if (pris[x].dchans[y])
12267                dchancount++;
12268 
12269             if (pris[x].dchans[y] == pri)
12270                dchan = y;
12271          }
12272          if (dchan >= 0) {
12273             span = x;
12274             break;
12275          }
12276          dchancount = 0;
12277       }
12278       if (dchancount > 1 && (span > -1))
12279          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12280       else
12281          ast_verbose("%s", s);
12282    } else
12283       ast_verbose("%s", s);
12284 
12285    ast_mutex_lock(&pridebugfdlock);
12286 
12287    if (pridebugfd >= 0) {
12288       if (write(pridebugfd, s, strlen(s)) < 0) {
12289          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12290       }
12291    }
12292 
12293    ast_mutex_unlock(&pridebugfdlock);
12294 }
12295 #endif   /* defined(HAVE_PRI) */
12296 
12297 #if defined(HAVE_PRI)
12298 static void dahdi_pri_error(struct pri *pri, char *s)
12299 {
12300    int x, y;
12301    int dchan = -1, span = -1;
12302    int dchancount = 0;
12303 
12304    if (pri) {
12305       for (x = 0; x < NUM_SPANS; x++) {
12306          for (y = 0; y < NUM_DCHANS; y++) {
12307             if (pris[x].dchans[y])
12308                dchancount++;
12309 
12310             if (pris[x].dchans[y] == pri)
12311                dchan = y;
12312          }
12313          if (dchan >= 0) {
12314             span = x;
12315             break;
12316          }
12317          dchancount = 0;
12318       }
12319       if ((dchancount > 1) && (span > -1))
12320          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12321       else
12322          ast_log(LOG_ERROR, "%s", s);
12323    } else
12324       ast_log(LOG_ERROR, "%s", s);
12325 
12326    ast_mutex_lock(&pridebugfdlock);
12327 
12328    if (pridebugfd >= 0) {
12329       if (write(pridebugfd, s, strlen(s)) < 0) {
12330          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12331       }
12332    }
12333 
12334    ast_mutex_unlock(&pridebugfdlock);
12335 }
12336 #endif   /* defined(HAVE_PRI) */
12337 
12338 #if defined(HAVE_PRI)
12339 static int pri_check_restart(struct dahdi_pri *pri)
12340 {
12341    do {
12342       pri->resetpos++;
12343    } while ((pri->resetpos < pri->numchans) &&
12344       (!pri->pvts[pri->resetpos] ||
12345       pri->pvts[pri->resetpos]->call ||
12346       pri->pvts[pri->resetpos]->resetting));
12347    if (pri->resetpos < pri->numchans) {
12348       /* Mark the channel as resetting and restart it */
12349       pri->pvts[pri->resetpos]->resetting = 1;
12350       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12351    } else {
12352       pri->resetting = 0;
12353       time(&pri->lastreset);
12354    }
12355    return 0;
12356 }
12357 #endif   /* defined(HAVE_PRI) */
12358 
12359 #if defined(HAVE_PRI)
12360 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12361 {
12362    int x;
12363    int redo;
12364    ast_mutex_unlock(&pri->lock);
12365    ast_mutex_lock(&p->lock);
12366    do {
12367       redo = 0;
12368       for (x = 0; x < 3; x++) {
12369          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12370             redo++;
12371             DEADLOCK_AVOIDANCE(&p->lock);
12372          }
12373          if (p->subs[x].owner) {
12374             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12375             ast_channel_unlock(p->subs[x].owner);
12376          }
12377       }
12378    } while (redo);
12379    ast_mutex_unlock(&p->lock);
12380    ast_mutex_lock(&pri->lock);
12381    return 0;
12382 }
12383 #endif   /* defined(HAVE_PRI) */
12384 
12385 #if defined(HAVE_PRI)
12386 static char * redirectingreason2str(int redirectingreason)
12387 {
12388    switch (redirectingreason) {
12389    case 0:
12390       return "UNKNOWN";
12391    case 1:
12392       return "BUSY";
12393    case 2:
12394       return "NO_REPLY";
12395    case 0xF:
12396       return "UNCONDITIONAL";
12397    default:
12398       return "NOREDIRECT";
12399    }
12400 }
12401 #endif   /* defined(HAVE_PRI) */
12402 
12403 #if defined(HAVE_PRI)
12404 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12405 {
12406    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
12407       snprintf(buf, size, "%s", number);
12408       return;
12409    }
12410    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12411       if (size) {
12412          *buf = '\0';
12413       }
12414       return;
12415    }
12416    switch (plan) {
12417    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
12418       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12419       break;
12420    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
12421       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12422       break;
12423    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
12424       snprintf(buf, size, "%s%s", pri->localprefix, number);
12425       break;
12426    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
12427       snprintf(buf, size, "%s%s", pri->privateprefix, number);
12428       break;
12429    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
12430       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12431       break;
12432    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
12433       snprintf(buf, size, "%s", number);
12434       break;
12435    }
12436 }
12437 #endif   /* defined(HAVE_PRI) */
12438 
12439 #if defined(HAVE_PRI)
12440 static void *pri_dchannel(void *vpri)
12441 {
12442    struct dahdi_pri *pri = vpri;
12443    pri_event *e;
12444    struct pollfd fds[NUM_DCHANS];
12445    int res;
12446    int chanpos = 0;
12447    int x;
12448    int haveidles;
12449    int activeidles;
12450    int nextidle = -1;
12451    struct ast_channel *c;
12452    struct timeval tv, lowest, *next;
12453    struct timeval lastidle = ast_tvnow();
12454    int doidling=0;
12455    char *cc;
12456    char idlen[80];
12457    struct ast_channel *idle;
12458    pthread_t p;
12459    time_t t;
12460    int i, which=-1;
12461    int numdchans;
12462    int cause=0;
12463    struct dahdi_pvt *crv;
12464    pthread_t threadid;
12465    char ani2str[6];
12466    char plancallingnum[256];
12467    char plancallingani[256];
12468    char calledtonstr[10];
12469 
12470    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12471 
12472    gettimeofday(&lastidle, NULL);
12473    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12474       /* Need to do idle dialing, check to be sure though */
12475       cc = strchr(pri->idleext, '@');
12476       if (cc) {
12477          *cc = '\0';
12478          cc++;
12479          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12480 #if 0
12481          /* Extensions may not be loaded yet */
12482          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12483             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12484          else
12485 #endif
12486             doidling = 1;
12487       } else
12488          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12489    }
12490    for (;;) {
12491       for (i = 0; i < NUM_DCHANS; i++) {
12492          if (!pri->dchannels[i])
12493             break;
12494          fds[i].fd = pri->fds[i];
12495          fds[i].events = POLLIN | POLLPRI;
12496          fds[i].revents = 0;
12497       }
12498       numdchans = i;
12499       time(&t);
12500       ast_mutex_lock(&pri->lock);
12501       if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12502          if (pri->resetting && pri_is_up(pri)) {
12503             if (pri->resetpos < 0)
12504                pri_check_restart(pri);
12505          } else {
12506             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
12507                pri->resetting = 1;
12508                pri->resetpos = -1;
12509             }
12510          }
12511       }
12512       /* Look for any idle channels if appropriate */
12513       if (doidling && pri_is_up(pri)) {
12514          nextidle = -1;
12515          haveidles = 0;
12516          activeidles = 0;
12517          for (x = pri->numchans; x >= 0; x--) {
12518             if (pri->pvts[x] && !pri->pvts[x]->owner &&
12519                !pri->pvts[x]->call) {
12520                if (haveidles < pri->minunused) {
12521                   haveidles++;
12522                } else if (!pri->pvts[x]->resetting) {
12523                   nextidle = x;
12524                   break;
12525                }
12526             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12527                activeidles++;
12528          }
12529          if (nextidle > -1) {
12530             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12531                /* Don't create a new idle call more than once per second */
12532                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12533                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12534                if (idle) {
12535                   pri->pvts[nextidle]->isidlecall = 1;
12536                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12537                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12538                      dahdi_hangup(idle);
12539                   }
12540                } else
12541                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12542                lastidle = ast_tvnow();
12543             }
12544          } else if ((haveidles < pri->minunused) &&
12545             (activeidles > pri->minidle)) {
12546             /* Mark something for hangup if there is something
12547                that can be hungup */
12548             for (x = pri->numchans; x >= 0; x--) {
12549                /* find a candidate channel */
12550                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12551                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12552                   haveidles++;
12553                   /* Stop if we have enough idle channels or
12554                     can't spare any more active idle ones */
12555                   if ((haveidles >= pri->minunused) ||
12556                      (activeidles <= pri->minidle))
12557                      break;
12558                }
12559             }
12560          }
12561       }
12562       /* Start with reasonable max */
12563       lowest = ast_tv(60, 0);
12564       for (i = 0; i < NUM_DCHANS; i++) {
12565          /* Find lowest available d-channel */
12566          if (!pri->dchannels[i])
12567             break;
12568          if ((next = pri_schedule_next(pri->dchans[i]))) {
12569             /* We need relative time here */
12570             tv = ast_tvsub(*next, ast_tvnow());
12571             if (tv.tv_sec < 0) {
12572                tv = ast_tv(0,0);
12573             }
12574             if (doidling || pri->resetting) {
12575                if (tv.tv_sec > 1) {
12576                   tv = ast_tv(1, 0);
12577                }
12578             } else {
12579                if (tv.tv_sec > 60) {
12580                   tv = ast_tv(60, 0);
12581                }
12582             }
12583          } else if (doidling || pri->resetting) {
12584             /* Make sure we stop at least once per second if we're
12585                monitoring idle channels */
12586             tv = ast_tv(1,0);
12587          } else {
12588             /* Don't poll for more than 60 seconds */
12589             tv = ast_tv(60, 0);
12590          }
12591          if (!i || ast_tvcmp(tv, lowest) < 0) {
12592             lowest = tv;
12593          }
12594       }
12595       ast_mutex_unlock(&pri->lock);
12596 
12597       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12598       pthread_testcancel();
12599       e = NULL;
12600       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12601       pthread_testcancel();
12602       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12603 
12604       ast_mutex_lock(&pri->lock);
12605       if (!res) {
12606          for (which = 0; which < NUM_DCHANS; which++) {
12607             if (!pri->dchans[which])
12608                break;
12609             /* Just a timeout, run the scheduler */
12610             e = pri_schedule_run(pri->dchans[which]);
12611             if (e)
12612                break;
12613          }
12614       } else if (res > -1) {
12615          for (which = 0; which < NUM_DCHANS; which++) {
12616             if (!pri->dchans[which])
12617                break;
12618             if (fds[which].revents & POLLPRI) {
12619                /* Check for an event */
12620                x = 0;
12621                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12622                if (x) {
12623                   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);
12624                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12625                      "PRIEvent: %s\r\n"
12626                      "PRIEventCode: %d\r\n"
12627                      "D-channel: %s\r\n"
12628                      "Span: %d\r\n",
12629                      event2str(x),
12630                      x,
12631                      pri_order(which),
12632                      pri->span
12633                      );
12634                }
12635                /* Keep track of alarm state */
12636                if (x == DAHDI_EVENT_ALARM) {
12637                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12638                   pri_find_dchan(pri);
12639                } else if (x == DAHDI_EVENT_NOALARM) {
12640                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
12641                   pri_restart(pri->dchans[which]);
12642                }
12643 
12644                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12645             } else if (fds[which].revents & POLLIN) {
12646                e = pri_check_event(pri->dchans[which]);
12647             }
12648             if (e)
12649                break;
12650          }
12651       } else if (errno != EINTR)
12652          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12653 
12654       if (e) {
12655          if (pri->debug)
12656             pri_dump_event(pri->dchans[which], e);
12657 
12658          if (e->e != PRI_EVENT_DCHAN_DOWN) {
12659             if (!(pri->dchanavail[which] & DCHAN_UP)) {
12660                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12661             }
12662             pri->dchanavail[which] |= DCHAN_UP;
12663          } else if (pri->sig != SIG_BRI_PTMP) {
12664             if (pri->dchanavail[which] & DCHAN_UP) {
12665                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12666             }
12667             pri->dchanavail[which] &= ~DCHAN_UP;
12668          }
12669 
12670          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12671             /* Must be an NFAS group that has the secondary dchan active */
12672             pri->pri = pri->dchans[which];
12673 
12674          switch (e->e) {
12675          case PRI_EVENT_DCHAN_UP:
12676             if (!pri->pri) pri_find_dchan(pri);
12677 
12678             /* Note presense of D-channel */
12679             time(&pri->lastreset);
12680 
12681             /* Restart in 5 seconds */
12682             if (pri->resetinterval > -1) {
12683                pri->lastreset -= pri->resetinterval;
12684                pri->lastreset += 5;
12685             }
12686             pri->resetting = 0;
12687             /* Take the channels from inalarm condition */
12688             for (i = 0; i < pri->numchans; i++)
12689                if (pri->pvts[i]) {
12690                   pri->pvts[i]->inalarm = 0;
12691                }
12692             break;
12693          case PRI_EVENT_DCHAN_DOWN:
12694             pri_find_dchan(pri);
12695             if (!pri_is_up(pri)) {
12696                pri->resetting = 0;
12697                /* Hangup active channels and put them in alarm mode */
12698                for (i = 0; i < pri->numchans; i++) {
12699                   struct dahdi_pvt *p = pri->pvts[i];
12700                   if (p) {
12701                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12702                         /* T309 is not enabled : hangup calls when alarm occurs */
12703                         if (p->call) {
12704                            if (p->pri && p->pri->pri) {
12705                               pri_hangup(p->pri->pri, p->call, -1);
12706                               pri_destroycall(p->pri->pri, p->call);
12707                               p->call = NULL;
12708                            } else
12709                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12710                         }
12711                         if (p->realcall) {
12712                            pri_hangup_all(p->realcall, pri);
12713                         } else if (p->owner)
12714                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12715                      }
12716                      /* For PTMP connections with non persistent layer 2 we want
12717                       * to *not* declare inalarm unless there actually is an alarm */
12718                      if (p->sig != SIG_BRI_PTMP) {
12719                         p->inalarm = 1;
12720                      }
12721                   }
12722                }
12723             }
12724             break;
12725          case PRI_EVENT_RESTART:
12726             if (e->restart.channel > -1) {
12727                chanpos = pri_find_principle(pri, e->restart.channel);
12728                if (chanpos < 0)
12729                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12730                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12731                else {
12732                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12733                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12734                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12735                   if (pri->pvts[chanpos]->call) {
12736                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12737                      pri->pvts[chanpos]->call = NULL;
12738                   }
12739                   /* Force soft hangup if appropriate */
12740                   if (pri->pvts[chanpos]->realcall)
12741                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12742                   else if (pri->pvts[chanpos]->owner)
12743                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12744                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12745                }
12746             } else {
12747                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12748                for (x = 0; x < pri->numchans; x++)
12749                   if (pri->pvts[x]) {
12750                      ast_mutex_lock(&pri->pvts[x]->lock);
12751                      if (pri->pvts[x]->call) {
12752                         pri_destroycall(pri->pri, pri->pvts[x]->call);
12753                         pri->pvts[x]->call = NULL;
12754                      }
12755                      if (pri->pvts[x]->realcall)
12756                         pri_hangup_all(pri->pvts[x]->realcall, pri);
12757                      else if (pri->pvts[x]->owner)
12758                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12759                      ast_mutex_unlock(&pri->pvts[x]->lock);
12760                   }
12761             }
12762             break;
12763          case PRI_EVENT_KEYPAD_DIGIT:
12764             chanpos = pri_find_principle(pri, e->digit.channel);
12765             if (chanpos < 0) {
12766                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12767                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12768             } else {
12769                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12770                if (chanpos > -1) {
12771                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12772                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
12773                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12774                      /* how to do that */
12775                      int digitlen = strlen(e->digit.digits);
12776                      char digit;
12777                      int i;
12778                      for (i = 0; i < digitlen; i++) {
12779                         digit = e->digit.digits[i];
12780                         {
12781                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12782                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12783                         }
12784                      }
12785                   }
12786                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12787                }
12788             }
12789             break;
12790 
12791          case PRI_EVENT_INFO_RECEIVED:
12792             chanpos = pri_find_principle(pri, e->ring.channel);
12793             if (chanpos < 0) {
12794                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12795                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12796             } else {
12797                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12798                if (chanpos > -1) {
12799                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12800                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
12801                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12802                      /* how to do that */
12803                      int digitlen = strlen(e->ring.callednum);
12804                      char digit;
12805                      int i;
12806                      for (i = 0; i < digitlen; i++) {
12807                         digit = e->ring.callednum[i];
12808                         {
12809                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12810                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12811                         }
12812                      }
12813                   }
12814                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12815                }
12816             }
12817             break;
12818          case PRI_EVENT_RING:
12819             crv = NULL;
12820             if (e->ring.channel == -1)
12821                chanpos = pri_find_empty_chan(pri, 1);
12822             else
12823                chanpos = pri_find_principle(pri, e->ring.channel);
12824             /* if no channel specified find one empty */
12825             if (chanpos < 0) {
12826                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12827                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12828             } else {
12829                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12830                if (pri->pvts[chanpos]->owner) {
12831                   if (pri->pvts[chanpos]->call == e->ring.call) {
12832                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12833                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12834                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12835                      break;
12836                   } else {
12837                      /* This is where we handle initial glare */
12838                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
12839                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12840                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12841                      chanpos = -1;
12842                   }
12843                }
12844                if (chanpos > -1)
12845                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12846             }
12847             if ((chanpos < 0) && (e->ring.flexible))
12848                chanpos = pri_find_empty_chan(pri, 1);
12849             if (chanpos > -1) {
12850                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12851                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12852                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
12853                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12854                   if (crv)
12855                      ast_mutex_lock(&crv->lock);
12856                   if (!crv || crv->owner) {
12857                      pri->pvts[chanpos]->call = NULL;
12858                      if (crv) {
12859                         if (crv->owner)
12860                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12861                         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);
12862                      } else
12863                         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);
12864                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12865                      if (crv)
12866                         ast_mutex_unlock(&crv->lock);
12867                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12868                      break;
12869                   }
12870                }
12871                pri->pvts[chanpos]->call = e->ring.call;
12872                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12873                if (pri->pvts[chanpos]->use_callerid) {
12874                   ast_shrink_phone_number(plancallingnum);
12875                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12876 #ifdef PRI_ANI
12877                   if (!ast_strlen_zero(e->ring.callingani)) {
12878                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12879                      ast_shrink_phone_number(plancallingani);
12880                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12881                   } else {
12882                      pri->pvts[chanpos]->cid_ani[0] = '\0';
12883                   }
12884 #endif
12885                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12886                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
12887                } else {
12888                   pri->pvts[chanpos]->cid_num[0] = '\0';
12889                   pri->pvts[chanpos]->cid_ani[0] = '\0';
12890                   pri->pvts[chanpos]->cid_name[0] = '\0';
12891                   pri->pvts[chanpos]->cid_ton = 0;
12892                }
12893                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12894                   e->ring.redirectingnum, e->ring.callingplanrdnis);
12895                /* If immediate=yes go to s|1 */
12896                if (pri->pvts[chanpos]->immediate) {
12897                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12898                   pri->pvts[chanpos]->exten[0] = 's';
12899                   pri->pvts[chanpos]->exten[1] = '\0';
12900                }
12901                /* Get called number */
12902                else if (!ast_strlen_zero(e->ring.callednum)) {
12903                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12904                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12905                } else if (pri->overlapdial)
12906                   pri->pvts[chanpos]->exten[0] = '\0';
12907                else {
12908                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
12909                   pri->pvts[chanpos]->exten[0] = 's';
12910                   pri->pvts[chanpos]->exten[1] = '\0';
12911                }
12912                /* Set DNID on all incoming calls -- even immediate */
12913                if (!ast_strlen_zero(e->ring.callednum))
12914                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12915                /* No number yet, but received "sending complete"? */
12916                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
12917                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
12918                   pri->pvts[chanpos]->exten[0] = 's';
12919                   pri->pvts[chanpos]->exten[1] = '\0';
12920                }
12921 
12922                /* Make sure extension exists (or in overlap dial mode, can exist) */
12923                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
12924                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12925                   /* Setup law */
12926                   int law;
12927                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
12928                      /* Set to audio mode at this point */
12929                      law = 1;
12930                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
12931                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
12932                   }
12933                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
12934                      law = DAHDI_LAW_ALAW;
12935                   else
12936                      law = DAHDI_LAW_MULAW;
12937                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
12938                   if (res < 0)
12939                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
12940                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
12941                   if (res < 0)
12942                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
12943                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
12944                      /* Just announce proceeding */
12945                      pri->pvts[chanpos]->proceeding = 1;
12946                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
12947                   } else {
12948                      if (pri->switchtype != PRI_SWITCH_GR303_TMC)
12949                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12950                      else
12951                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12952                   }
12953                   /* Get the use_callingpres state */
12954                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
12955 
12956                   /* Start PBX */
12957                   if (!e->ring.complete
12958                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
12959                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12960                      /*
12961                       * Release the PRI lock while we create the channel
12962                       * so other threads can send D channel messages.
12963                       */
12964                      ast_mutex_unlock(&pri->lock);
12965                      if (crv) {
12966                         /* Set bearer and such */
12967                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
12968                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12969                         pri->pvts[chanpos]->owner = &inuse;
12970                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
12971                      } else {
12972                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12973                      }
12974                      ast_mutex_lock(&pri->lock);
12975                      if (c) {
12976                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12977                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12978                         }
12979                         if (e->ring.ani2 >= 0) {
12980                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12981                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12982                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12983                         }
12984 
12985 #ifdef SUPPORT_USERUSER
12986                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
12987                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12988                         }
12989 #endif
12990 
12991                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
12992                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
12993                         if (e->ring.redirectingreason >= 0)
12994                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
12995                      }
12996                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
12997                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
12998                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
12999                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13000                      } else {
13001                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13002                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13003                         if (c)
13004                            ast_hangup(c);
13005                         else {
13006                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13007                            pri->pvts[chanpos]->call = NULL;
13008                         }
13009                      }
13010                   } else {
13011                      /*
13012                       * Release the PRI lock while we create the channel
13013                       * so other threads can send D channel messages.
13014                       */
13015                      ast_mutex_unlock(&pri->lock);
13016                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13017                      ast_mutex_lock(&pri->lock);
13018                      if (c) {
13019                         /*
13020                          * It is reasonably safe to set the following
13021                          * channel variables while the PRI and DAHDI private
13022                          * structures are locked.  The PBX has not been
13023                          * started yet and it is unlikely that any other task
13024                          * will do anything with the channel we have just
13025                          * created.
13026                          */
13027                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13028                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13029                         }
13030                         if (e->ring.ani2 >= 0) {
13031                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13032                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13033                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13034                         }
13035 
13036 #ifdef SUPPORT_USERUSER
13037                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
13038                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13039                         }
13040 #endif
13041 
13042                         if (e->ring.redirectingreason >= 0)
13043                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13044 
13045                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13046                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13047                      }
13048                      if (c && !ast_pbx_start(c)) {
13049                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13050                            plancallingnum, pri->pvts[chanpos]->exten,
13051                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13052 
13053                         dahdi_enable_ec(pri->pvts[chanpos]);
13054                      } else {
13055                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13056                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13057                         if (c) {
13058                            ast_hangup(c);
13059                         } else {
13060                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13061                            pri->pvts[chanpos]->call = NULL;
13062                         }
13063                      }
13064                   }
13065                } else {
13066                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
13067                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13068                      pri->pvts[chanpos]->prioffset, pri->span);
13069                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13070                   pri->pvts[chanpos]->call = NULL;
13071                   pri->pvts[chanpos]->exten[0] = '\0';
13072                }
13073                if (crv)
13074                   ast_mutex_unlock(&crv->lock);
13075                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13076             } else {
13077                if (e->ring.flexible)
13078                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13079                else
13080                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13081             }
13082             break;
13083          case PRI_EVENT_RINGING:
13084             chanpos = pri_find_principle(pri, e->ringing.channel);
13085             if (chanpos < 0) {
13086                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13087                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13088             } else {
13089                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13090                if (chanpos < 0) {
13091                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13092                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13093                } else {
13094                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13095                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13096                      dahdi_enable_ec(pri->pvts[chanpos]);
13097                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13098                      pri->pvts[chanpos]->alerting = 1;
13099                   } else
13100                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13101 
13102                   if (
13103 #ifdef PRI_PROGRESS_MASK
13104                      e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13105 #else
13106                      e->ringing.progress == 8
13107 #endif
13108                      ) {
13109                      /* Now we can do call progress detection */
13110                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13111                         /* RINGING detection isn't required because we got ALERTING signal */
13112                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13113                         pri->pvts[chanpos]->dsp_features = 0;
13114                      }
13115                   }
13116 
13117 #ifdef SUPPORT_USERUSER
13118                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13119                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13120                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13121                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13122                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13123                   }
13124 #endif
13125 
13126                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13127                }
13128             }
13129             break;
13130          case PRI_EVENT_PROGRESS:
13131             /* Get chan value if e->e is not PRI_EVNT_RINGING */
13132             chanpos = pri_find_principle(pri, e->proceeding.channel);
13133             if (chanpos > -1) {
13134                if ((!pri->pvts[chanpos]->progress)
13135 #ifdef PRI_PROGRESS_MASK
13136                   || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13137 #else
13138                   || (e->proceeding.progress == 8)
13139 #endif
13140                   ) {
13141                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13142 
13143                   if (e->proceeding.cause > -1) {
13144                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13145 
13146                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
13147                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13148                         if (pri->pvts[chanpos]->owner) {
13149                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13150 
13151                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13152                            f.subclass = AST_CONTROL_BUSY;
13153                         }
13154                      }
13155                   }
13156 
13157                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13158                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13159                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13160                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13161                   if (
13162 #ifdef PRI_PROGRESS_MASK
13163                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13164 #else
13165                      e->proceeding.progress == 8
13166 #endif
13167                      ) {
13168                      /* Now we can do call progress detection */
13169                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13170                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13171                         pri->pvts[chanpos]->dsp_features = 0;
13172                      }
13173                      /* Bring voice path up */
13174                      f.subclass = AST_CONTROL_PROGRESS;
13175                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13176                   }
13177                   pri->pvts[chanpos]->progress = 1;
13178                   pri->pvts[chanpos]->dialing = 0;
13179                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13180                }
13181             }
13182             break;
13183          case PRI_EVENT_PROCEEDING:
13184             chanpos = pri_find_principle(pri, e->proceeding.channel);
13185             if (chanpos > -1) {
13186                if (!pri->pvts[chanpos]->proceeding) {
13187                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13188 
13189                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13190                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13191                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13192                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13193                   if (
13194 #ifdef PRI_PROGRESS_MASK
13195                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13196 #else
13197                      e->proceeding.progress == 8
13198 #endif
13199                      ) {
13200                      /* Now we can do call progress detection */
13201                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13202                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13203                         pri->pvts[chanpos]->dsp_features = 0;
13204                      }
13205                      /* Bring voice path up */
13206                      f.subclass = AST_CONTROL_PROGRESS;
13207                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13208                   }
13209                   pri->pvts[chanpos]->proceeding = 1;
13210                   pri->pvts[chanpos]->dialing = 0;
13211                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13212                }
13213             }
13214             break;
13215          case PRI_EVENT_FACNAME:
13216             chanpos = pri_find_principle(pri, e->facname.channel);
13217             if (chanpos < 0) {
13218                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13219                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13220             } else {
13221                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13222                if (chanpos < 0) {
13223                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13224                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13225                } else {
13226                   /* Re-use *69 field for PRI */
13227                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13228                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13229                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13230                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
13231                   dahdi_enable_ec(pri->pvts[chanpos]);
13232                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13233                }
13234             }
13235             break;
13236          case PRI_EVENT_ANSWER:
13237             chanpos = pri_find_principle(pri, e->answer.channel);
13238             if (chanpos < 0) {
13239                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13240                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13241             } else {
13242                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13243                if (chanpos < 0) {
13244                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13245                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13246                } else {
13247                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13248                   /* Now we can do call progress detection */
13249 
13250                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
13251                    * By this time, we need DTMF detection and other features that were previously disabled
13252                    * -- Matt F */
13253                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13254                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13255                      pri->pvts[chanpos]->dsp_features = 0;
13256                   }
13257                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13258                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13259                      x = DAHDI_START;
13260                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13261                      if (res < 0) {
13262                         if (errno != EINPROGRESS) {
13263                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13264                         }
13265                      }
13266                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13267                      pri->pvts[chanpos]->dialing = 1;
13268                      /* Send any "w" waited stuff */
13269                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13270                      if (res < 0) {
13271                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13272                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13273                      } else
13274                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13275 
13276                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13277                   } else if (pri->pvts[chanpos]->confirmanswer) {
13278                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13279                   } else {
13280                      pri->pvts[chanpos]->dialing = 0;
13281                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13282                      /* Enable echo cancellation if it's not on already */
13283                      dahdi_enable_ec(pri->pvts[chanpos]);
13284                   }
13285 
13286 #ifdef SUPPORT_USERUSER
13287                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
13288                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13289                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13290                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13291                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13292                   }
13293 #endif
13294 
13295                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13296                }
13297             }
13298             break;
13299          case PRI_EVENT_HANGUP:
13300             chanpos = pri_find_principle(pri, e->hangup.channel);
13301             if (chanpos < 0) {
13302                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13303                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13304             } else {
13305                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13306                if (chanpos > -1) {
13307                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13308                   if (!pri->pvts[chanpos]->alreadyhungup) {
13309                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
13310                      pri->pvts[chanpos]->alreadyhungup = 1;
13311                      if (pri->pvts[chanpos]->realcall)
13312                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13313                      else if (pri->pvts[chanpos]->owner) {
13314                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
13315                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13316                         switch (pri->pvts[chanpos]->owner->_state) {
13317                         case AST_STATE_BUSY:
13318                         case AST_STATE_UP:
13319                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13320                            break;
13321                         default:
13322                            switch (e->hangup.cause) {
13323                            case PRI_CAUSE_USER_BUSY:
13324                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13325                               break;
13326                            case PRI_CAUSE_CALL_REJECTED:
13327                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13328                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13329                            case PRI_CAUSE_SWITCH_CONGESTION:
13330                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13331                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13332                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13333                               break;
13334                            default:
13335                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13336                            }
13337                            break;
13338                         }
13339                      }
13340                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13341                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13342                   } else {
13343                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13344                      pri->pvts[chanpos]->call = NULL;
13345                   }
13346                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13347                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13348                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13349                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13350                      pri->pvts[chanpos]->resetting = 1;
13351                   }
13352                   if (e->hangup.aoc_units > -1)
13353                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13354                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13355 
13356 #ifdef SUPPORT_USERUSER
13357                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13358                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13359                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13360                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13361                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13362                   }
13363 #endif
13364 
13365                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13366                } else {
13367                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13368                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13369                }
13370             }
13371             break;
13372 #ifndef PRI_EVENT_HANGUP_REQ
13373 #error please update libpri
13374 #endif
13375          case PRI_EVENT_HANGUP_REQ:
13376             chanpos = pri_find_principle(pri, e->hangup.channel);
13377             if (chanpos < 0) {
13378                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13379                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13380             } else {
13381                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13382                if (chanpos > -1) {
13383                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13384                   if (pri->pvts[chanpos]->realcall)
13385                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13386                   else if (pri->pvts[chanpos]->owner) {
13387                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13388                      switch (pri->pvts[chanpos]->owner->_state) {
13389                      case AST_STATE_BUSY:
13390                      case AST_STATE_UP:
13391                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13392                         break;
13393                      default:
13394                         switch (e->hangup.cause) {
13395                         case PRI_CAUSE_USER_BUSY:
13396                            pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13397                            break;
13398                         case PRI_CAUSE_CALL_REJECTED:
13399                         case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13400                         case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13401                         case PRI_CAUSE_SWITCH_CONGESTION:
13402                         case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13403                         case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13404                            pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13405                            break;
13406                         default:
13407                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13408                            break;
13409                         }
13410                         break;
13411                      }
13412                      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);
13413                      if (e->hangup.aoc_units > -1)
13414                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13415                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13416                   } else {
13417                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13418                      pri->pvts[chanpos]->call = NULL;
13419                   }
13420                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13421                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13422                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13423                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13424                      pri->pvts[chanpos]->resetting = 1;
13425                   }
13426 
13427 #ifdef SUPPORT_USERUSER
13428                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13429                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13430                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13431                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13432                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13433                   }
13434 #endif
13435 
13436                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13437                } else {
13438                   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);
13439                }
13440             }
13441             break;
13442          case PRI_EVENT_HANGUP_ACK:
13443             chanpos = pri_find_principle(pri, e->hangup.channel);
13444             if (chanpos < 0) {
13445                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13446                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13447             } else {
13448                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13449                if (chanpos > -1) {
13450                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13451                   pri->pvts[chanpos]->call = NULL;
13452                   pri->pvts[chanpos]->resetting = 0;
13453                   if (pri->pvts[chanpos]->owner) {
13454                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13455                   }
13456 
13457 #ifdef SUPPORT_USERUSER
13458                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13459                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13460                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13461                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13462                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13463                   }
13464 #endif
13465 
13466                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13467                }
13468             }
13469             break;
13470          case PRI_EVENT_CONFIG_ERR:
13471             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
13472             break;
13473          case PRI_EVENT_RESTART_ACK:
13474             chanpos = pri_find_principle(pri, e->restartack.channel);
13475             if (chanpos < 0) {
13476                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
13477                   channel number, so we have to figure it out...  This must be why
13478                   everybody resets exactly a channel at a time. */
13479                for (x = 0; x < pri->numchans; x++) {
13480                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
13481                      chanpos = x;
13482                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13483                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13484                         pri->pvts[chanpos]->prioffset, pri->span);
13485                      if (pri->pvts[chanpos]->realcall)
13486                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13487                      else if (pri->pvts[chanpos]->owner) {
13488                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13489                            pri->pvts[chanpos]->prioffset, pri->span);
13490                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13491                      }
13492                      pri->pvts[chanpos]->resetting = 0;
13493                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13494                            pri->pvts[chanpos]->prioffset, pri->span);
13495                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13496                      if (pri->resetting)
13497                         pri_check_restart(pri);
13498                      break;
13499                   }
13500                }
13501                if (chanpos < 0) {
13502                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13503                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13504                }
13505             } else {
13506                if (pri->pvts[chanpos]) {
13507                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13508                   if (pri->pvts[chanpos]->realcall)
13509                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13510                   else if (pri->pvts[chanpos]->owner) {
13511                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13512                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13513                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13514                   }
13515                   pri->pvts[chanpos]->resetting = 0;
13516                   pri->pvts[chanpos]->inservice = 1;
13517                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13518                            pri->pvts[chanpos]->prioffset, pri->span);
13519                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13520                   if (pri->resetting)
13521                      pri_check_restart(pri);
13522                }
13523             }
13524             break;
13525          case PRI_EVENT_SETUP_ACK:
13526             chanpos = pri_find_principle(pri, e->setup_ack.channel);
13527             if (chanpos < 0) {
13528                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13529                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13530             } else {
13531                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13532                if (chanpos > -1) {
13533                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13534                   pri->pvts[chanpos]->setup_ack = 1;
13535                   /* Send any queued digits */
13536                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13537                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13538                      pri_information(pri->pri, pri->pvts[chanpos]->call,
13539                         pri->pvts[chanpos]->dialdest[x]);
13540                   }
13541                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13542                } else
13543                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13544             }
13545             break;
13546          case PRI_EVENT_NOTIFY:
13547             chanpos = pri_find_principle(pri, e->notify.channel);
13548             if (chanpos < 0) {
13549                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13550                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13551             } else if (!pri->discardremoteholdretrieval) {
13552                struct ast_frame f = { AST_FRAME_CONTROL, };
13553                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13554                switch (e->notify.info) {
13555                case PRI_NOTIFY_REMOTE_HOLD:
13556                   f.subclass = AST_CONTROL_HOLD;
13557                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13558                   break;
13559                case PRI_NOTIFY_REMOTE_RETRIEVAL:
13560                   f.subclass = AST_CONTROL_UNHOLD;
13561                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13562                   break;
13563                }
13564                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13565             }
13566             break;
13567          default:
13568             ast_debug(1, "Event: %d\n", e->e);
13569          }
13570       }
13571       ast_mutex_unlock(&pri->lock);
13572    }
13573    /* Never reached */
13574    return NULL;
13575 }
13576 #endif   /* defined(HAVE_PRI) */
13577 
13578 #if defined(HAVE_PRI)
13579 static int start_pri(struct dahdi_pri *pri)
13580 {
13581    int res, x;
13582    struct dahdi_params p;
13583    struct dahdi_bufferinfo bi;
13584    struct dahdi_spaninfo si;
13585    int i;
13586 
13587    for (i = 0; i < NUM_DCHANS; i++) {
13588       if (!pri->dchannels[i])
13589          break;
13590       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13591       x = pri->dchannels[i];
13592       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13593          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13594          return -1;
13595       }
13596       memset(&p, 0, sizeof(p));
13597       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13598       if (res) {
13599          dahdi_close_pri_fd(pri, i);
13600          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13601          return -1;
13602       }
13603       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13604          dahdi_close_pri_fd(pri, i);
13605          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13606          return -1;
13607       }
13608       memset(&si, 0, sizeof(si));
13609       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13610       if (res) {
13611          dahdi_close_pri_fd(pri, i);
13612          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13613       }
13614       if (!si.alarms)
13615          pri->dchanavail[i] |= DCHAN_NOTINALARM;
13616       else
13617          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13618       memset(&bi, 0, sizeof(bi));
13619       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13620       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13621       bi.numbufs = 32;
13622       bi.bufsize = 1024;
13623       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13624          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13625          dahdi_close_pri_fd(pri, i);
13626          return -1;
13627       }
13628       switch (pri->sig) {
13629       case SIG_BRI:
13630          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13631          break;
13632       case SIG_BRI_PTMP:
13633          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13634          break;
13635       default:
13636          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13637          break;
13638       }
13639       /* Force overlap dial if we're doing GR-303! */
13640       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13641          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13642       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13643 #ifdef HAVE_PRI_PROG_W_CAUSE
13644       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13645 #endif
13646 #ifdef HAVE_PRI_INBANDDISCONNECT
13647       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13648 #endif
13649       /* Enslave to master if appropriate */
13650       if (i)
13651          pri_enslave(pri->dchans[0], pri->dchans[i]);
13652       if (!pri->dchans[i]) {
13653          dahdi_close_pri_fd(pri, i);
13654          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13655          return -1;
13656       }
13657       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13658       pri_set_nsf(pri->dchans[i], pri->nsf);
13659 #ifdef PRI_GETSET_TIMERS
13660       for (x = 0; x < PRI_MAX_TIMERS; x++) {
13661          if (pritimers[x] != 0)
13662             pri_set_timer(pri->dchans[i], x, pritimers[x]);
13663       }
13664 #endif
13665    }
13666    /* Assume primary is the one we use */
13667    pri->pri = pri->dchans[0];
13668    pri->resetpos = -1;
13669    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13670       for (i = 0; i < NUM_DCHANS; i++) {
13671          if (!pri->dchannels[i])
13672             break;
13673          dahdi_close_pri_fd(pri, i);
13674       }
13675       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13676       return -1;
13677    }
13678    return 0;
13679 }
13680 #endif   /* defined(HAVE_PRI) */
13681 
13682 #if defined(HAVE_PRI)
13683 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13684 {
13685    int which, span;
13686    char *ret = NULL;
13687 
13688    if (pos != rpos)
13689       return ret;
13690 
13691    for (which = span = 0; span < NUM_SPANS; span++) {
13692       if (pris[span].pri && ++which > state) {
13693          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13694             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13695          }
13696          break;
13697       }
13698    }
13699    return ret;
13700 }
13701 #endif   /* defined(HAVE_PRI) */
13702 
13703 #if defined(HAVE_PRI)
13704 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13705 {
13706    return complete_span_helper(line,word,pos,state,3);
13707 }
13708 #endif   /* defined(HAVE_PRI) */
13709 
13710 #if defined(HAVE_PRI)
13711 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13712 {
13713    int myfd;
13714    switch (cmd) {
13715    case CLI_INIT:
13716       e->command = "pri set debug file";
13717       e->usage = "Usage: pri set debug file [output-file]\n"
13718          "       Sends PRI debug output to the specified output file\n";
13719       return NULL;
13720    case CLI_GENERATE:
13721       return NULL;
13722    }
13723    if (a->argc < 5)
13724       return CLI_SHOWUSAGE;
13725 
13726    if (ast_strlen_zero(a->argv[4]))
13727       return CLI_SHOWUSAGE;
13728 
13729    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13730    if (myfd < 0) {
13731       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13732       return CLI_SUCCESS;
13733    }
13734 
13735    ast_mutex_lock(&pridebugfdlock);
13736 
13737    if (pridebugfd >= 0)
13738       close(pridebugfd);
13739 
13740    pridebugfd = myfd;
13741    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13742    ast_mutex_unlock(&pridebugfdlock);
13743    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13744    return CLI_SUCCESS;
13745 }
13746 #endif   /* defined(HAVE_PRI) */
13747 
13748 #if defined(HAVE_PRI)
13749 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13750 {
13751    int span;
13752    int x;
13753    int level = 0;
13754    switch (cmd) {
13755    case CLI_INIT:
13756       e->command = "pri set debug {on|off|0|1|2} span";
13757       e->usage =
13758          "Usage: pri set debug {<level>|on|off} span <span>\n"
13759          "       Enables debugging on a given PRI span\n";
13760       return NULL;
13761    case CLI_GENERATE:
13762       return complete_span_4(a->line, a->word, a->pos, a->n);
13763    }
13764    if (a->argc < 6) {
13765       return CLI_SHOWUSAGE;
13766    }
13767 
13768    if (!strcasecmp(a->argv[3], "on")) {
13769       level = 1;
13770    } else if (!strcasecmp(a->argv[3], "off")) {
13771       level = 0;
13772    } else {
13773       level = atoi(a->argv[3]);
13774    }
13775    span = atoi(a->argv[5]);
13776    if ((span < 1) || (span > NUM_SPANS)) {
13777       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13778       return CLI_SUCCESS;
13779    }
13780    if (!pris[span-1].pri) {
13781       ast_cli(a->fd, "No PRI running on span %d\n", span);
13782       return CLI_SUCCESS;
13783    }
13784    for (x = 0; x < NUM_DCHANS; x++) {
13785       if (pris[span-1].dchans[x]) {
13786          if (level == 1) {
13787             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13788                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13789                PRI_DEBUG_Q921_STATE);
13790             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13791          } else if (level == 0) {
13792             pri_set_debug(pris[span-1].dchans[x], 0);
13793             //close the file if it's set
13794             ast_mutex_lock(&pridebugfdlock);
13795             close(pridebugfd);
13796             pridebugfd = -1;
13797             ast_cli(a->fd, "PRI debug output to file disabled\n");
13798             ast_mutex_unlock(&pridebugfdlock);
13799          } else {
13800             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13801                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13802                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13803             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13804          }
13805       }
13806    }
13807    return CLI_SUCCESS;
13808 }
13809 #endif   /* defined(HAVE_PRI) */
13810 
13811 #if defined(HAVE_PRI)
13812 static void build_status(char *s, size_t len, int status, int active)
13813 {
13814    if (!s || len < 1) {
13815       return;
13816    }
13817    s[0] = '\0';
13818    if (status & DCHAN_PROVISIONED)
13819       strncat(s, "Provisioned, ", len - strlen(s) - 1);
13820    if (!(status & DCHAN_NOTINALARM))
13821       strncat(s, "In Alarm, ", len - strlen(s) - 1);
13822    if (status & DCHAN_UP)
13823       strncat(s, "Up", len - strlen(s) - 1);
13824    else
13825       strncat(s, "Down", len - strlen(s) - 1);
13826    if (active)
13827       strncat(s, ", Active", len - strlen(s) - 1);
13828    else
13829       strncat(s, ", Standby", len - strlen(s) - 1);
13830    s[len - 1] = '\0';
13831 }
13832 #endif   /* defined(HAVE_PRI) */
13833 
13834 #if defined(HAVE_PRI)
13835 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837    int span;
13838    int x;
13839    char status[256];
13840 
13841    switch (cmd) {
13842    case CLI_INIT:
13843       e->command = "pri show spans";
13844       e->usage =
13845          "Usage: pri show spans\n"
13846          "       Displays PRI Information\n";
13847       return NULL;
13848    case CLI_GENERATE:
13849       return NULL;
13850    }
13851 
13852    if (a->argc != 3)
13853       return CLI_SHOWUSAGE;
13854 
13855    for (span = 0; span < NUM_SPANS; span++) {
13856       if (pris[span].pri) {
13857          for (x = 0; x < NUM_DCHANS; x++) {
13858             if (pris[span].dchannels[x]) {
13859                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13860                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13861             }
13862          }
13863       }
13864    }
13865    return CLI_SUCCESS;
13866 }
13867 #endif   /* defined(HAVE_PRI) */
13868 
13869 #if defined(HAVE_PRI)
13870 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13871 {
13872    int span;
13873    int x;
13874    char status[256];
13875    switch (cmd) {
13876    case CLI_INIT:
13877       e->command = "pri show span";
13878       e->usage =
13879          "Usage: pri show span <span>\n"
13880          "       Displays PRI Information on a given PRI span\n";
13881       return NULL;
13882    case CLI_GENERATE:
13883       return complete_span_4(a->line, a->word, a->pos, a->n);
13884    }
13885 
13886    if (a->argc < 4)
13887       return CLI_SHOWUSAGE;
13888    span = atoi(a->argv[3]);
13889    if ((span < 1) || (span > NUM_SPANS)) {
13890       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13891       return CLI_SUCCESS;
13892    }
13893    if (!pris[span-1].pri) {
13894       ast_cli(a->fd, "No PRI running on span %d\n", span);
13895       return CLI_SUCCESS;
13896    }
13897    for (x = 0; x < NUM_DCHANS; x++) {
13898       if (pris[span-1].dchannels[x]) {
13899 #ifdef PRI_DUMP_INFO_STR
13900          char *info_str = NULL;
13901 #endif
13902          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13903          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13904          ast_cli(a->fd, "Status: %s\n", status);
13905 #ifdef PRI_DUMP_INFO_STR
13906          info_str = pri_dump_info_str(pris[span-1].pri);
13907          if (info_str) {
13908             ast_cli(a->fd, "%s", info_str);
13909             ast_free(info_str);
13910          }
13911 #else
13912          pri_dump_info(pris[span-1].pri);
13913 #endif
13914          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13915       }
13916    }
13917    return CLI_SUCCESS;
13918 }
13919 #endif   /* defined(HAVE_PRI) */
13920 
13921 #if defined(HAVE_PRI)
13922 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13923 {
13924    int x;
13925    int span;
13926    int count=0;
13927    int debug=0;
13928 
13929    switch (cmd) {
13930    case CLI_INIT:
13931       e->command = "pri show debug";
13932       e->usage =
13933          "Usage: pri show debug\n"
13934          "  Show the debug state of pri spans\n";
13935       return NULL;
13936    case CLI_GENERATE:
13937       return NULL;
13938    }
13939 
13940    for (span = 0; span < NUM_SPANS; span++) {
13941       if (pris[span].pri) {
13942          for (x = 0; x < NUM_DCHANS; x++) {
13943             debug = 0;
13944             if (pris[span].dchans[x]) {
13945                debug = pri_get_debug(pris[span].dchans[x]);
13946                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" );
13947                count++;
13948             }
13949          }
13950       }
13951 
13952    }
13953    ast_mutex_lock(&pridebugfdlock);
13954    if (pridebugfd >= 0)
13955       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
13956    ast_mutex_unlock(&pridebugfdlock);
13957 
13958    if (!count)
13959       ast_cli(a->fd, "No debug set or no PRI running\n");
13960    return CLI_SUCCESS;
13961 }
13962 #endif   /* defined(HAVE_PRI) */
13963 
13964 #if defined(HAVE_PRI)
13965 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13966 {
13967    switch (cmd) {
13968    case CLI_INIT:
13969       e->command = "pri show version";
13970       e->usage =
13971          "Usage: pri show version\n"
13972          "Show libpri version information\n";
13973       return NULL;
13974    case CLI_GENERATE:
13975       return NULL;
13976    }
13977 
13978    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
13979 
13980    return CLI_SUCCESS;
13981 }
13982 #endif   /* defined(HAVE_PRI) */
13983 
13984 #if defined(HAVE_PRI)
13985 static struct ast_cli_entry dahdi_pri_cli[] = {
13986    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
13987    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
13988    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
13989    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
13990    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
13991    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
13992 };
13993 #endif   /* defined(HAVE_PRI) */
13994 
13995 #ifdef HAVE_OPENR2
13996 
13997 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13998 {
13999    switch (cmd) {
14000    case CLI_INIT:
14001       e->command = "mfcr2 show version";
14002       e->usage =
14003          "Usage: mfcr2 show version\n"
14004          "       Shows the version of the OpenR2 library being used.\n";
14005       return NULL;
14006    case CLI_GENERATE:
14007       return NULL;
14008    }
14009    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14010    return CLI_SUCCESS;
14011 }
14012 
14013 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14014 {
14015 #define FORMAT "%4s %40s\n"
14016    int i = 0;
14017    int numvariants = 0;
14018    const openr2_variant_entry_t *variants;
14019    switch (cmd) {
14020    case CLI_INIT:
14021       e->command = "mfcr2 show variants";
14022       e->usage =
14023          "Usage: mfcr2 show variants\n"
14024          "       Shows the list of MFC/R2 variants supported.\n";
14025       return NULL;
14026    case CLI_GENERATE:
14027       return NULL;
14028    }
14029    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14030       ast_cli(a->fd, "Failed to get list of variants.\n");
14031       return CLI_FAILURE;
14032    }
14033    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14034    for (i = 0; i < numvariants; i++) {
14035       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14036    }
14037    return CLI_SUCCESS;
14038 #undef FORMAT
14039 }
14040 
14041 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14042 {
14043 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14044    int filtertype = 0;
14045    int targetnum = 0;
14046    char channo[5];
14047    char anino[5];
14048    char dnisno[5];
14049    struct dahdi_pvt *p;
14050    openr2_context_t *r2context;
14051    openr2_variant_t r2variant;
14052    switch (cmd) {
14053    case CLI_INIT:
14054       e->command = "mfcr2 show channels [group|context]";
14055       e->usage =
14056          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14057          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14058       return NULL;
14059    case CLI_GENERATE:
14060       return NULL;
14061    }
14062    if (!((a->argc == 3) || (a->argc == 5))) {
14063       return CLI_SHOWUSAGE;
14064    }
14065    if (a->argc == 5) {
14066       if (!strcasecmp(a->argv[3], "group")) {
14067          targetnum = atoi(a->argv[4]);
14068          if ((targetnum < 0) || (targetnum > 63))
14069             return CLI_SHOWUSAGE;
14070          targetnum = 1 << targetnum;
14071          filtertype = 1;
14072       } else if (!strcasecmp(a->argv[3], "context")) {
14073          filtertype = 2;
14074       } else {
14075          return CLI_SHOWUSAGE;
14076       }
14077    }
14078    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14079    ast_mutex_lock(&iflock);
14080    p = iflist;
14081    for (p = iflist; p; p = p->next) {
14082       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14083          continue;
14084       }
14085       if (filtertype) {
14086          switch(filtertype) {
14087          case 1: /* mfcr2 show channels group <group> */
14088             if (p->group != targetnum) {
14089                continue;
14090             }
14091             break;
14092          case 2: /* mfcr2 show channels context <context> */
14093             if (strcasecmp(p->context, a->argv[4])) {
14094                continue;
14095             }
14096             break;
14097          default:
14098             ;
14099          }
14100       }
14101       r2context = openr2_chan_get_context(p->r2chan);
14102       r2variant = openr2_context_get_variant(r2context);
14103       snprintf(channo, sizeof(channo), "%d", p->channel);
14104       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14105       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14106       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14107             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14108             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14109             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14110    }
14111    ast_mutex_unlock(&iflock);
14112    return CLI_SUCCESS;
14113 #undef FORMAT
14114 }
14115 
14116 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14117 {
14118    struct dahdi_pvt *p = NULL;
14119    int channo = 0;
14120    char *toklevel = NULL;
14121    char *saveptr = NULL;
14122    char *logval = NULL;
14123    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14124    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14125    switch (cmd) {
14126    case CLI_INIT:
14127       e->command = "mfcr2 set debug";
14128       e->usage =
14129          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14130          "       Set a new logging level for the specified channel.\n"
14131          "       If no channel is specified the logging level will be applied to all channels.\n";
14132       return NULL;
14133    case CLI_GENERATE:
14134       return NULL;
14135    }
14136    if (a->argc < 4) {
14137       return CLI_SHOWUSAGE;
14138    }
14139    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14140    logval = ast_strdupa(a->argv[3]);
14141    toklevel = strtok_r(logval, ",", &saveptr);
14142    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14143       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14144       return CLI_FAILURE;
14145    } else if (OR2_LOG_NOTHING == tmplevel) {
14146       loglevel = tmplevel;
14147    } else {
14148       loglevel |= tmplevel;
14149       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14150          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14151             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14152             continue;
14153          }
14154          loglevel |= tmplevel;
14155       }
14156    }
14157    ast_mutex_lock(&iflock);
14158    for (p = iflist; p; p = p->next) {
14159       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14160          continue;
14161       }
14162       if ((channo != -1) && (p->channel != channo )) {
14163          continue;
14164       }
14165       openr2_chan_set_log_level(p->r2chan, loglevel);
14166       if (channo != -1) {
14167          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14168          break;
14169       }
14170    }
14171    if ((channo != -1) && !p) {
14172       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14173    }
14174    if (channo == -1) {
14175       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14176    }
14177    ast_mutex_unlock(&iflock);
14178    return CLI_SUCCESS;
14179 }
14180 
14181 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14182 {
14183    struct dahdi_pvt *p = NULL;
14184    int channo = 0;
14185    switch (cmd) {
14186    case CLI_INIT:
14187       e->command = "mfcr2 call files [on|off]";
14188       e->usage =
14189          "Usage: mfcr2 call files [on|off] <channel>\n"
14190          "       Enable call files creation on the specified channel.\n"
14191          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14192       return NULL;
14193    case CLI_GENERATE:
14194       return NULL;
14195    }
14196    if (a->argc < 4) {
14197       return CLI_SHOWUSAGE;
14198    }
14199    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14200    ast_mutex_lock(&iflock);
14201    for (p = iflist; p; p = p->next) {
14202       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14203          continue;
14204       }
14205       if ((channo != -1) && (p->channel != channo )) {
14206          continue;
14207       }
14208       if (ast_true(a->argv[3])) {
14209          openr2_chan_enable_call_files(p->r2chan);
14210       } else {
14211          openr2_chan_disable_call_files(p->r2chan);
14212       }
14213       if (channo != -1) {
14214          if (ast_true(a->argv[3])) {
14215             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14216          } else {
14217             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14218          }
14219          break;
14220       }
14221    }
14222    if ((channo != -1) && !p) {
14223       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14224    }
14225    if (channo == -1) {
14226       if (ast_true(a->argv[3])) {
14227          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14228       } else {
14229          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14230       }
14231    }
14232    ast_mutex_unlock(&iflock);
14233    return CLI_SUCCESS;
14234 }
14235 
14236 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14237 {
14238    struct dahdi_pvt *p = NULL;
14239    int channo = 0;
14240    switch (cmd) {
14241    case CLI_INIT:
14242       e->command = "mfcr2 set idle";
14243       e->usage =
14244          "Usage: mfcr2 set idle <channel>\n"
14245          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14246          "       Force the given channel into IDLE state.\n"
14247          "       If no channel is specified, all channels will be set to IDLE.\n";
14248       return NULL;
14249    case CLI_GENERATE:
14250       return NULL;
14251    }
14252    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14253    ast_mutex_lock(&iflock);
14254    for (p = iflist; p; p = p->next) {
14255       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14256          continue;
14257       }
14258       if ((channo != -1) && (p->channel != channo )) {
14259          continue;
14260       }
14261       openr2_chan_set_idle(p->r2chan);
14262       ast_mutex_lock(&p->lock);
14263       p->locallyblocked = 0;
14264       p->mfcr2call = 0;
14265       ast_mutex_unlock(&p->lock);
14266       if (channo != -1) {
14267          break;
14268       }
14269    }
14270    if ((channo != -1) && !p) {
14271       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14272    }
14273    ast_mutex_unlock(&iflock);
14274    return CLI_SUCCESS;
14275 }
14276 
14277 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14278 {
14279    struct dahdi_pvt *p = NULL;
14280    int channo = 0;
14281    switch (cmd) {
14282    case CLI_INIT:
14283       e->command = "mfcr2 set blocked";
14284       e->usage =
14285          "Usage: mfcr2 set blocked <channel>\n"
14286          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14287          "       Force the given channel into BLOCKED state.\n"
14288          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14289       return NULL;
14290    case CLI_GENERATE:
14291       return NULL;
14292    }
14293    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14294    ast_mutex_lock(&iflock);
14295    for (p = iflist; p; p = p->next) {
14296       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14297          continue;
14298       }
14299       if ((channo != -1) && (p->channel != channo )) {
14300          continue;
14301       }
14302       openr2_chan_set_blocked(p->r2chan);
14303       ast_mutex_lock(&p->lock);
14304       p->locallyblocked = 1;
14305       ast_mutex_unlock(&p->lock);
14306       if (channo != -1) {
14307          break;
14308       }
14309    }
14310    if ((channo != -1) && !p) {
14311       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14312    }
14313    ast_mutex_unlock(&iflock);
14314    return CLI_SUCCESS;
14315 }
14316 
14317 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14318    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14319    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14320    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14321    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14322    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14323    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14324    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14325 };
14326 
14327 #endif /* HAVE_OPENR2 */
14328 
14329 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14330 {
14331    int channel;
14332    int ret;
14333    switch (cmd) {
14334    case CLI_INIT:
14335       e->command = "dahdi destroy channel";
14336       e->usage =
14337          "Usage: dahdi destroy channel <chan num>\n"
14338          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14339       return NULL;
14340    case CLI_GENERATE:
14341       return NULL;
14342    }
14343    if (a->argc != 4)
14344       return CLI_SHOWUSAGE;
14345 
14346    channel = atoi(a->argv[3]);
14347    ret = dahdi_destroy_channel_bynum(channel);
14348    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14349 }
14350 
14351 static void dahdi_softhangup_all(void)
14352 {
14353    struct dahdi_pvt *p;
14354 retry:
14355    ast_mutex_lock(&iflock);
14356    for (p = iflist; p; p = p->next) {
14357       ast_mutex_lock(&p->lock);
14358       if (p->owner && !p->restartpending) {
14359          if (ast_channel_trylock(p->owner)) {
14360             if (option_debug > 2)
14361                ast_verbose("Avoiding deadlock\n");
14362             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14363             ast_mutex_unlock(&p->lock);
14364             ast_mutex_unlock(&iflock);
14365             goto retry;
14366          }
14367          if (option_debug > 2)
14368             ast_verbose("Softhanging up on %s\n", p->owner->name);
14369          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14370          p->restartpending = 1;
14371          num_restart_pending++;
14372          ast_channel_unlock(p->owner);
14373       }
14374       ast_mutex_unlock(&p->lock);
14375    }
14376    ast_mutex_unlock(&iflock);
14377 }
14378 
14379 static int setup_dahdi(int reload);
14380 static int dahdi_restart(void)
14381 {
14382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14383    int i, j;
14384 #endif
14385    int cancel_code;
14386    struct dahdi_pvt *p;
14387 
14388    ast_mutex_lock(&restart_lock);
14389    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14390    dahdi_softhangup_all();
14391    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14392 #ifdef HAVE_OPENR2
14393    dahdi_r2_destroy_links();
14394 #endif
14395 
14396 #if defined(HAVE_PRI)
14397    for (i = 0; i < NUM_SPANS; i++) {
14398       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14399          cancel_code = pthread_cancel(pris[i].master);
14400          pthread_kill(pris[i].master, SIGURG);
14401          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14402          pthread_join(pris[i].master, NULL);
14403          ast_debug(4, "Joined thread of span %d\n", i);
14404       }
14405    }
14406 #endif
14407 
14408 #if defined(HAVE_SS7)
14409    for (i = 0; i < NUM_SPANS; i++) {
14410       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14411          cancel_code = pthread_cancel(linksets[i].master);
14412          pthread_kill(linksets[i].master, SIGURG);
14413          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14414          pthread_join(linksets[i].master, NULL);
14415          ast_debug(4, "Joined thread of span %d\n", i);
14416       }
14417    }
14418 #endif
14419 
14420    ast_mutex_lock(&monlock);
14421    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14422       cancel_code = pthread_cancel(monitor_thread);
14423       pthread_kill(monitor_thread, SIGURG);
14424       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14425       pthread_join(monitor_thread, NULL);
14426       ast_debug(4, "Joined monitor thread\n");
14427    }
14428    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14429 
14430    ast_mutex_lock(&ss_thread_lock);
14431    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14432       int x = DAHDI_FLASH;
14433       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14434 
14435       for (p = iflist; p; p = p->next) {
14436          if (p->owner)
14437             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 */
14438          }
14439          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14440       }
14441 
14442    /* ensure any created channels before monitor threads were stopped are hungup */
14443    dahdi_softhangup_all();
14444    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14445    destroy_all_channels();
14446    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14447 
14448    ast_mutex_unlock(&monlock);
14449 
14450 #ifdef HAVE_PRI
14451    for (i = 0; i < NUM_SPANS; i++) {
14452       for (j = 0; j < NUM_DCHANS; j++)
14453          dahdi_close_pri_fd(&(pris[i]), j);
14454    }
14455 
14456    memset(pris, 0, sizeof(pris));
14457    for (i = 0; i < NUM_SPANS; i++) {
14458       ast_mutex_init(&pris[i].lock);
14459       pris[i].offset = -1;
14460       pris[i].master = AST_PTHREADT_NULL;
14461       for (j = 0; j < NUM_DCHANS; j++)
14462          pris[i].fds[j] = -1;
14463       }
14464    pri_set_error(dahdi_pri_error);
14465    pri_set_message(dahdi_pri_message);
14466 #endif
14467 #ifdef HAVE_SS7
14468    for (i = 0; i < NUM_SPANS; i++) {
14469       for (j = 0; j < NUM_DCHANS; j++)
14470          dahdi_close_ss7_fd(&(linksets[i]), j);
14471    }
14472 
14473    memset(linksets, 0, sizeof(linksets));
14474    for (i = 0; i < NUM_SPANS; i++) {
14475       ast_mutex_init(&linksets[i].lock);
14476       linksets[i].master = AST_PTHREADT_NULL;
14477       for (j = 0; j < NUM_DCHANS; j++)
14478          linksets[i].fds[j] = -1;
14479    }
14480    ss7_set_error(dahdi_ss7_error);
14481    ss7_set_message(dahdi_ss7_message);
14482 #endif
14483 
14484    if (setup_dahdi(2) != 0) {
14485       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14486       ast_mutex_unlock(&ss_thread_lock);
14487       return 1;
14488    }
14489    ast_mutex_unlock(&ss_thread_lock);
14490    ast_mutex_unlock(&restart_lock);
14491    return 0;
14492 }
14493 
14494 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14495 {
14496    switch (cmd) {
14497    case CLI_INIT:
14498       e->command = "dahdi restart";
14499       e->usage =
14500          "Usage: dahdi restart\n"
14501          "  Restarts the DAHDI channels: destroys them all and then\n"
14502          "  re-reads them from chan_dahdi.conf.\n"
14503          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14504          "";
14505       return NULL;
14506    case CLI_GENERATE:
14507       return NULL;
14508    }
14509    if (a->argc != 2)
14510       return CLI_SHOWUSAGE;
14511 
14512    if (dahdi_restart() != 0)
14513       return CLI_FAILURE;
14514    return CLI_SUCCESS;
14515 }
14516 
14517 static int action_dahdirestart(struct mansession *s, const struct message *m)
14518 {
14519    if (dahdi_restart() != 0) {
14520       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14521       return 1;
14522    }
14523    astman_send_ack(s, m, "DAHDIRestart: Success");
14524    return 0;
14525 }
14526 
14527 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14528 {
14529 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14530 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14531    unsigned int targetnum = 0;
14532    int filtertype = 0;
14533    struct dahdi_pvt *tmp = NULL;
14534    char tmps[20] = "";
14535    char statestr[20] = "";
14536    char blockstr[20] = "";
14537    ast_mutex_t *lock;
14538    struct dahdi_pvt *start;
14539 #ifdef HAVE_PRI
14540    int trunkgroup;
14541    struct dahdi_pri *pri = NULL;
14542    int x;
14543 #endif
14544    switch (cmd) {
14545    case CLI_INIT:
14546       e->command = "dahdi show channels [trunkgroup|group|context]";
14547       e->usage =
14548          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14549          "  Shows a list of available channels with optional filtering\n"
14550          "  <group> must be a number between 0 and 63\n";
14551       return NULL;
14552    case CLI_GENERATE:
14553       return NULL;
14554    }
14555 
14556    lock = &iflock;
14557    start = iflist;
14558 
14559    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
14560 
14561    if (!((a->argc == 3) || (a->argc == 5)))
14562       return CLI_SHOWUSAGE;
14563 
14564    if (a->argc == 5) {
14565 #ifdef HAVE_PRI
14566       if (!strcasecmp(a->argv[3], "trunkgroup")) {
14567          /* this option requires no special handling, so leave filtertype to zero */
14568          if ((trunkgroup = atoi(a->argv[4])) < 1)
14569             return CLI_SHOWUSAGE;
14570          for (x = 0; x < NUM_SPANS; x++) {
14571             if (pris[x].trunkgroup == trunkgroup) {
14572                pri = pris + x;
14573                break;
14574             }
14575          }
14576          if (pri) {
14577             start = pri->crvs;
14578             lock = &pri->lock;
14579          } else {
14580             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14581             return CLI_FAILURE;
14582          }
14583       } else
14584 #endif
14585       if (!strcasecmp(a->argv[3], "group")) {
14586          targetnum = atoi(a->argv[4]);
14587          if ((targetnum < 0) || (targetnum > 63))
14588             return CLI_SHOWUSAGE;
14589          targetnum = 1 << targetnum;
14590          filtertype = 1;
14591       } else if (!strcasecmp(a->argv[3], "context")) {
14592          filtertype = 2;
14593       }
14594    }
14595 
14596    ast_mutex_lock(lock);
14597 #ifdef HAVE_PRI
14598    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14599 #else
14600    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14601 #endif
14602 
14603    tmp = start;
14604    while (tmp) {
14605       if (filtertype) {
14606          switch(filtertype) {
14607          case 1: /* dahdi show channels group <group> */
14608             if (!(tmp->group & targetnum)) {
14609                tmp = tmp->next;
14610                continue;
14611             }
14612             break;
14613          case 2: /* dahdi show channels context <context> */
14614             if (strcasecmp(tmp->context, a->argv[4])) {
14615                tmp = tmp->next;
14616                continue;
14617             }
14618             break;
14619          default:
14620             ;
14621          }
14622       }
14623       if (tmp->channel > 0) {
14624          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14625       } else
14626          ast_copy_string(tmps, "pseudo", sizeof(tmps));
14627 
14628       if (tmp->locallyblocked)
14629          blockstr[0] = 'L';
14630       else
14631          blockstr[0] = ' ';
14632 
14633       if (tmp->remotelyblocked)
14634          blockstr[1] = 'R';
14635       else
14636          blockstr[1] = ' ';
14637 
14638       blockstr[2] = '\0';
14639 
14640       snprintf(statestr, sizeof(statestr), "%s", "In Service");
14641 
14642       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14643       tmp = tmp->next;
14644    }
14645    ast_mutex_unlock(lock);
14646    return CLI_SUCCESS;
14647 #undef FORMAT
14648 #undef FORMAT2
14649 }
14650 
14651 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14652 {
14653    int channel;
14654    struct dahdi_pvt *tmp = NULL;
14655    struct dahdi_confinfo ci;
14656    struct dahdi_params ps;
14657    int x;
14658    ast_mutex_t *lock;
14659    struct dahdi_pvt *start;
14660 #ifdef HAVE_PRI
14661    char *c;
14662    int trunkgroup;
14663    struct dahdi_pri *pri=NULL;
14664 #endif
14665    switch (cmd) {
14666    case CLI_INIT:
14667       e->command = "dahdi show channel";
14668       e->usage =
14669          "Usage: dahdi show channel <chan num>\n"
14670          "  Detailed information about a given channel\n";
14671       return NULL;
14672    case CLI_GENERATE:
14673       return NULL;
14674    }
14675 
14676    lock = &iflock;
14677    start = iflist;
14678 
14679    if (a->argc != 4)
14680       return CLI_SHOWUSAGE;
14681 #ifdef HAVE_PRI
14682    if ((c = strchr(a->argv[3], ':'))) {
14683       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14684          return CLI_SHOWUSAGE;
14685       if ((trunkgroup < 1) || (channel < 1))
14686          return CLI_SHOWUSAGE;
14687       for (x = 0; x < NUM_SPANS; x++) {
14688          if (pris[x].trunkgroup == trunkgroup) {
14689             pri = pris + x;
14690             break;
14691          }
14692       }
14693       if (pri) {
14694          start = pri->crvs;
14695          lock = &pri->lock;
14696       } else {
14697          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14698          return CLI_FAILURE;
14699       }
14700    } else
14701 #endif
14702       channel = atoi(a->argv[3]);
14703 
14704    ast_mutex_lock(lock);
14705    tmp = start;
14706    while (tmp) {
14707       if (tmp->channel == channel) {
14708 #ifdef HAVE_PRI
14709          if (pri)
14710             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14711          else
14712 #endif
14713          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14714          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14715          ast_cli(a->fd, "Span: %d\n", tmp->span);
14716          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14717          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14718          ast_cli(a->fd, "Context: %s\n", tmp->context);
14719          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14720          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14721          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14722          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14723          if (tmp->vars) {
14724             struct ast_variable *v;
14725             ast_cli(a->fd, "Variables:\n");
14726             for (v = tmp->vars ; v ; v = v->next)
14727                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14728          }
14729          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14730          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14731          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14732          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14733          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14734          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)" : "");
14735          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)" : "");
14736          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)" : "");
14737          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14738          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14739          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14740          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14741          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14742          if (tmp->busydetect) {
14743 #if defined(BUSYDETECT_TONEONLY)
14744             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14745 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14746             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14747 #endif
14748 #ifdef BUSYDETECT_DEBUG
14749             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14750 #endif
14751             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14752             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14753          }
14754          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14755          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14756          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14757          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14758          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14759          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14760          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14761          ast_cli(a->fd, "Echo Cancellation:\n");
14762 
14763          if (tmp->echocancel.head.tap_length) {
14764             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14765             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14766                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14767             }
14768             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14769          } else {
14770             ast_cli(a->fd, "\tnone\n");
14771          }
14772          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14773          if (tmp->master)
14774             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14775          for (x = 0; x < MAX_SLAVES; x++) {
14776             if (tmp->slaves[x])
14777                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14778          }
14779 #ifdef HAVE_OPENR2
14780          if (tmp->mfcr2) {
14781             char calldir[OR2_MAX_PATH];
14782             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14783             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14784             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14785             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14786             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14787             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14788             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14789             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14790             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14791             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14792             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14793 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14794             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14795 #endif
14796             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14797             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14798             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14799             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14800             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14801             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14802             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14803             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14804             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14805             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14806             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14807             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14808          }
14809 #endif
14810 #ifdef HAVE_SS7
14811          if (tmp->ss7) {
14812             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14813          }
14814 #endif
14815 #ifdef HAVE_PRI
14816          if (tmp->pri) {
14817             ast_cli(a->fd, "PRI Flags: ");
14818             if (tmp->resetting)
14819                ast_cli(a->fd, "Resetting ");
14820             if (tmp->call)
14821                ast_cli(a->fd, "Call ");
14822             if (tmp->bearer)
14823                ast_cli(a->fd, "Bearer ");
14824             ast_cli(a->fd, "\n");
14825             if (tmp->logicalspan)
14826                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14827             else
14828                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14829          }
14830 #endif
14831          memset(&ci, 0, sizeof(ci));
14832          ps.channo = tmp->channel;
14833          if (tmp->subs[SUB_REAL].dfd > -1) {
14834             memset(&ci, 0, sizeof(ci));
14835             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14836                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14837             }
14838             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14839                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14840             }
14841             memset(&ps, 0, sizeof(ps));
14842             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14843                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14844             } else {
14845                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14846             }
14847          }
14848          ast_mutex_unlock(lock);
14849          return CLI_SUCCESS;
14850       }
14851       tmp = tmp->next;
14852    }
14853 
14854    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14855    ast_mutex_unlock(lock);
14856    return CLI_FAILURE;
14857 }
14858 
14859 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14860 {
14861    int i, j;
14862    switch (cmd) {
14863    case CLI_INIT:
14864       e->command = "dahdi show cadences";
14865       e->usage =
14866          "Usage: dahdi show cadences\n"
14867          "       Shows all cadences currently defined\n";
14868       return NULL;
14869    case CLI_GENERATE:
14870       return NULL;
14871    }
14872    for (i = 0; i < num_cadence; i++) {
14873       char output[1024];
14874       char tmp[16], tmp2[64];
14875       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14876       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14877 
14878       for (j = 0; j < 16; j++) {
14879          if (cadences[i].ringcadence[j] == 0)
14880             break;
14881          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14882          if (cidrings[i] * 2 - 1 == j)
14883             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14884          else
14885             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14886          if (j != 0)
14887             strncat(output, ",", sizeof(output) - strlen(output) - 1);
14888          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14889       }
14890       ast_cli(a->fd,"%s\n",output);
14891    }
14892    return CLI_SUCCESS;
14893 }
14894 
14895 /* Based on irqmiss.c */
14896 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14897 {
14898    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14899    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14900    int span;
14901    int res;
14902    char alarmstr[50];
14903 
14904    int ctl;
14905    struct dahdi_spaninfo s;
14906 
14907    switch (cmd) {
14908    case CLI_INIT:
14909       e->command = "dahdi show status";
14910       e->usage =
14911          "Usage: dahdi show status\n"
14912          "       Shows a list of DAHDI cards with status\n";
14913       return NULL;
14914    case CLI_GENERATE:
14915       return NULL;
14916    }
14917    ctl = open("/dev/dahdi/ctl", O_RDWR);
14918    if (ctl < 0) {
14919       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
14920       return CLI_FAILURE;
14921    }
14922    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
14923 
14924    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
14925       s.spanno = span;
14926       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
14927       if (res) {
14928          continue;
14929       }
14930       alarmstr[0] = '\0';
14931       if (s.alarms > 0) {
14932          if (s.alarms & DAHDI_ALARM_BLUE)
14933             strcat(alarmstr, "BLU/");
14934          if (s.alarms & DAHDI_ALARM_YELLOW)
14935             strcat(alarmstr, "YEL/");
14936          if (s.alarms & DAHDI_ALARM_RED)
14937             strcat(alarmstr, "RED/");
14938          if (s.alarms & DAHDI_ALARM_LOOPBACK)
14939             strcat(alarmstr, "LB/");
14940          if (s.alarms & DAHDI_ALARM_RECOVER)
14941             strcat(alarmstr, "REC/");
14942          if (s.alarms & DAHDI_ALARM_NOTOPEN)
14943             strcat(alarmstr, "NOP/");
14944          if (!strlen(alarmstr))
14945             strcat(alarmstr, "UUU/");
14946          if (strlen(alarmstr)) {
14947             /* Strip trailing / */
14948             alarmstr[strlen(alarmstr) - 1] = '\0';
14949          }
14950       } else {
14951          if (s.numchans)
14952             strcpy(alarmstr, "OK");
14953          else
14954             strcpy(alarmstr, "UNCONFIGURED");
14955       }
14956 
14957       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
14958          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
14959          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
14960          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
14961          "CAS",
14962          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
14963          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
14964          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
14965          "Unk",
14966          s.lineconfig & DAHDI_CONFIG_CRC4 ?
14967          s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL",
14968          lbostr[s.lbo]
14969          );
14970    }
14971    close(ctl);
14972 
14973    return CLI_SUCCESS;
14974 #undef FORMAT
14975 #undef FORMAT2
14976 }
14977 
14978 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14979 {
14980    int pseudo_fd = -1;
14981    struct dahdi_versioninfo vi;
14982 
14983    switch (cmd) {
14984    case CLI_INIT:
14985       e->command = "dahdi show version";
14986       e->usage =
14987          "Usage: dahdi show version\n"
14988          "       Shows the DAHDI version in use\n";
14989       return NULL;
14990    case CLI_GENERATE:
14991       return NULL;
14992    }
14993    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
14994       ast_cli(a->fd, "Failed to open control file to get version.\n");
14995       return CLI_SUCCESS;
14996    }
14997 
14998    strcpy(vi.version, "Unknown");
14999    strcpy(vi.echo_canceller, "Unknown");
15000 
15001    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15002       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15003    else
15004       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15005 
15006    close(pseudo_fd);
15007 
15008    return CLI_SUCCESS;
15009 }
15010 
15011 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15012 {
15013    int channel;
15014    int gain;
15015    int tx;
15016    struct dahdi_hwgain hwgain;
15017    struct dahdi_pvt *tmp = NULL;
15018 
15019    switch (cmd) {
15020    case CLI_INIT:
15021       e->command = "dahdi set hwgain";
15022       e->usage =
15023          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15024          "  Sets the hardware gain on a a given channel, overriding the\n"
15025          "   value provided at module loadtime, whether the channel is in\n"
15026          "   use or not.  Changes take effect immediately.\n"
15027          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15028          "   <chan num> is the channel number relative to the device\n"
15029          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15030       return NULL;
15031    case CLI_GENERATE:
15032       return NULL;
15033    }
15034 
15035    if (a->argc != 6)
15036       return CLI_SHOWUSAGE;
15037 
15038    if (!strcasecmp("rx", a->argv[3]))
15039       tx = 0; /* rx */
15040    else if (!strcasecmp("tx", a->argv[3]))
15041       tx = 1; /* tx */
15042    else
15043       return CLI_SHOWUSAGE;
15044 
15045    channel = atoi(a->argv[4]);
15046    gain = atof(a->argv[5])*10.0;
15047 
15048    ast_mutex_lock(&iflock);
15049 
15050    for (tmp = iflist; tmp; tmp = tmp->next) {
15051 
15052       if (tmp->channel != channel)
15053          continue;
15054 
15055       if (tmp->subs[SUB_REAL].dfd == -1)
15056          break;
15057 
15058       hwgain.newgain = gain;
15059       hwgain.tx = tx;
15060       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15061          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15062          ast_mutex_unlock(&iflock);
15063          return CLI_FAILURE;
15064       }
15065       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15066          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15067       break;
15068    }
15069 
15070    ast_mutex_unlock(&iflock);
15071 
15072    if (tmp)
15073       return CLI_SUCCESS;
15074 
15075    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15076    return CLI_FAILURE;
15077 
15078 }
15079 
15080 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15081 {
15082    int channel;
15083    float gain;
15084    int tx;
15085    int res;
15086    ast_mutex_t *lock;
15087    struct dahdi_pvt *tmp = NULL;
15088 
15089    switch (cmd) {
15090    case CLI_INIT:
15091       e->command = "dahdi set swgain";
15092       e->usage =
15093          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15094          "  Sets the software gain on a a given channel, overriding the\n"
15095          "   value provided at module loadtime, whether the channel is in\n"
15096          "   use or not.  Changes take effect immediately.\n"
15097          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15098          "   <chan num> is the channel number relative to the device\n"
15099          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15100       return NULL;
15101    case CLI_GENERATE:
15102       return NULL;
15103    }
15104 
15105    lock = &iflock;
15106 
15107    if (a->argc != 6)
15108       return CLI_SHOWUSAGE;
15109 
15110    if (!strcasecmp("rx", a->argv[3]))
15111       tx = 0; /* rx */
15112    else if (!strcasecmp("tx", a->argv[3]))
15113       tx = 1; /* tx */
15114    else
15115       return CLI_SHOWUSAGE;
15116 
15117    channel = atoi(a->argv[4]);
15118    gain = atof(a->argv[5]);
15119 
15120    ast_mutex_lock(lock);
15121    for (tmp = iflist; tmp; tmp = tmp->next) {
15122 
15123       if (tmp->channel != channel)
15124          continue;
15125 
15126       if (tmp->subs[SUB_REAL].dfd == -1)
15127          break;
15128 
15129       if (tx)
15130          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15131       else
15132          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15133 
15134       if (res) {
15135          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15136          ast_mutex_unlock(lock);
15137          return CLI_FAILURE;
15138       }
15139 
15140       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15141          tx ? "tx" : "rx", gain, channel);
15142       break;
15143    }
15144    ast_mutex_unlock(lock);
15145 
15146    if (tmp)
15147       return CLI_SUCCESS;
15148 
15149    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15150    return CLI_FAILURE;
15151 
15152 }
15153 
15154 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15155 {
15156    int channel;
15157    int on;
15158    struct dahdi_pvt *dahdi_chan = NULL;
15159 
15160    switch (cmd) {
15161    case CLI_INIT:
15162       e->command = "dahdi set dnd";
15163       e->usage =
15164          "Usage: dahdi set dnd <chan#> <on|off>\n"
15165          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15166          "  Changes take effect immediately.\n"
15167          "  <chan num> is the channel number\n"
15168          "  <on|off> Enable or disable DND mode?\n"
15169          ;
15170       return NULL;
15171    case CLI_GENERATE:
15172       return NULL;
15173    }
15174 
15175    if (a->argc != 5)
15176       return CLI_SHOWUSAGE;
15177 
15178    if ((channel = atoi(a->argv[3])) <= 0) {
15179       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15180       return CLI_SHOWUSAGE;
15181    }
15182 
15183    if (ast_true(a->argv[4]))
15184       on = 1;
15185    else if (ast_false(a->argv[4]))
15186       on = 0;
15187    else {
15188       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15189       return CLI_SHOWUSAGE;
15190    }
15191 
15192    ast_mutex_lock(&iflock);
15193    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15194       if (dahdi_chan->channel != channel)
15195          continue;
15196 
15197       /* Found the channel. Actually set it */
15198       dahdi_dnd(dahdi_chan, on);
15199       break;
15200    }
15201    ast_mutex_unlock(&iflock);
15202 
15203    if (!dahdi_chan) {
15204       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15205       return CLI_FAILURE;
15206    }
15207 
15208    return CLI_SUCCESS;
15209 }
15210 
15211 static struct ast_cli_entry dahdi_cli[] = {
15212    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15213    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15214    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15215    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15216    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15217    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15218    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15219    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15220    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15221    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15222 };
15223 
15224 #define TRANSFER  0
15225 #define HANGUP    1
15226 
15227 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15228 {
15229    if (p) {
15230       switch (mode) {
15231          case TRANSFER:
15232             p->fake_event = DAHDI_EVENT_WINKFLASH;
15233             break;
15234          case HANGUP:
15235             p->fake_event = DAHDI_EVENT_ONHOOK;
15236             break;
15237          default:
15238             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15239       }
15240    }
15241    return 0;
15242 }
15243 static struct dahdi_pvt *find_channel(int channel)
15244 {
15245    struct dahdi_pvt *p = iflist;
15246    while (p) {
15247       if (p->channel == channel) {
15248          break;
15249       }
15250       p = p->next;
15251    }
15252    return p;
15253 }
15254 
15255 static int action_dahdidndon(struct mansession *s, const struct message *m)
15256 {
15257    struct dahdi_pvt *p = NULL;
15258    const char *channel = astman_get_header(m, "DAHDIChannel");
15259 
15260    if (ast_strlen_zero(channel)) {
15261       astman_send_error(s, m, "No channel specified");
15262       return 0;
15263    }
15264    p = find_channel(atoi(channel));
15265    if (!p) {
15266       astman_send_error(s, m, "No such channel");
15267       return 0;
15268    }
15269    p->dnd = 1;
15270    astman_send_ack(s, m, "DND Enabled");
15271    return 0;
15272 }
15273 
15274 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15275 {
15276    struct dahdi_pvt *p = NULL;
15277    const char *channel = astman_get_header(m, "DAHDIChannel");
15278 
15279    if (ast_strlen_zero(channel)) {
15280       astman_send_error(s, m, "No channel specified");
15281       return 0;
15282    }
15283    p = find_channel(atoi(channel));
15284    if (!p) {
15285       astman_send_error(s, m, "No such channel");
15286       return 0;
15287    }
15288    p->dnd = 0;
15289    astman_send_ack(s, m, "DND Disabled");
15290    return 0;
15291 }
15292 
15293 static int action_transfer(struct mansession *s, const struct message *m)
15294 {
15295    struct dahdi_pvt *p = NULL;
15296    const char *channel = astman_get_header(m, "DAHDIChannel");
15297 
15298    if (ast_strlen_zero(channel)) {
15299       astman_send_error(s, m, "No channel specified");
15300       return 0;
15301    }
15302    p = find_channel(atoi(channel));
15303    if (!p) {
15304       astman_send_error(s, m, "No such channel");
15305       return 0;
15306    }
15307    dahdi_fake_event(p,TRANSFER);
15308    astman_send_ack(s, m, "DAHDITransfer");
15309    return 0;
15310 }
15311 
15312 static int action_transferhangup(struct mansession *s, const struct message *m)
15313 {
15314    struct dahdi_pvt *p = NULL;
15315    const char *channel = astman_get_header(m, "DAHDIChannel");
15316 
15317    if (ast_strlen_zero(channel)) {
15318       astman_send_error(s, m, "No channel specified");
15319       return 0;
15320    }
15321    p = find_channel(atoi(channel));
15322    if (!p) {
15323       astman_send_error(s, m, "No such channel");
15324       return 0;
15325    }
15326    dahdi_fake_event(p,HANGUP);
15327    astman_send_ack(s, m, "DAHDIHangup");
15328    return 0;
15329 }
15330 
15331 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15332 {
15333    struct dahdi_pvt *p = NULL;
15334    const char *channel = astman_get_header(m, "DAHDIChannel");
15335    const char *number = astman_get_header(m, "Number");
15336    int i;
15337 
15338    if (ast_strlen_zero(channel)) {
15339       astman_send_error(s, m, "No channel specified");
15340       return 0;
15341    }
15342    if (ast_strlen_zero(number)) {
15343       astman_send_error(s, m, "No number specified");
15344       return 0;
15345    }
15346    p = find_channel(atoi(channel));
15347    if (!p) {
15348       astman_send_error(s, m, "No such channel");
15349       return 0;
15350    }
15351    if (!p->owner) {
15352       astman_send_error(s, m, "Channel does not have it's owner");
15353       return 0;
15354    }
15355    for (i = 0; i < strlen(number); i++) {
15356       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15357       dahdi_queue_frame(p, &f, NULL);
15358    }
15359    astman_send_ack(s, m, "DAHDIDialOffhook");
15360    return 0;
15361 }
15362 
15363 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15364 {
15365    struct dahdi_pvt *tmp = NULL;
15366    const char *id = astman_get_header(m, "ActionID");
15367    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15368    char idText[256] = "";
15369    int channels = 0;
15370    int dahdichanquery = -1;
15371    if (!ast_strlen_zero(dahdichannel)) {
15372       dahdichanquery = atoi(dahdichannel);
15373    }
15374 
15375    astman_send_ack(s, m, "DAHDI channel status will follow");
15376    if (!ast_strlen_zero(id))
15377       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15378 
15379    ast_mutex_lock(&iflock);
15380 
15381    tmp = iflist;
15382    while (tmp) {
15383       if (tmp->channel > 0) {
15384          int alm = get_alarms(tmp);
15385 
15386          /* If a specific channel is queried for, only deliver status for that channel */
15387          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15388             continue;
15389 
15390          channels++;
15391          if (tmp->owner) {
15392             /* Add data if we have a current call */
15393             astman_append(s,
15394                "Event: DAHDIShowChannels\r\n"
15395                "DAHDIChannel: %d\r\n"
15396                "Channel: %s\r\n"
15397                "Uniqueid: %s\r\n"
15398                "AccountCode: %s\r\n"
15399                "Signalling: %s\r\n"
15400                "SignallingCode: %d\r\n"
15401                "Context: %s\r\n"
15402                "DND: %s\r\n"
15403                "Alarm: %s\r\n"
15404                "%s"
15405                "\r\n",
15406                tmp->channel,
15407                tmp->owner->name,
15408                tmp->owner->uniqueid,
15409                tmp->owner->accountcode,
15410                sig2str(tmp->sig),
15411                tmp->sig,
15412                tmp->context,
15413                tmp->dnd ? "Enabled" : "Disabled",
15414                alarm2str(alm), idText);
15415          } else {
15416             astman_append(s,
15417                "Event: DAHDIShowChannels\r\n"
15418                "DAHDIChannel: %d\r\n"
15419                "Signalling: %s\r\n"
15420                "SignallingCode: %d\r\n"
15421                "Context: %s\r\n"
15422                "DND: %s\r\n"
15423                "Alarm: %s\r\n"
15424                "%s"
15425                "\r\n",
15426                tmp->channel, sig2str(tmp->sig), tmp->sig,
15427                tmp->context,
15428                tmp->dnd ? "Enabled" : "Disabled",
15429                alarm2str(alm), idText);
15430          }
15431       }
15432 
15433       tmp = tmp->next;
15434    }
15435 
15436    ast_mutex_unlock(&iflock);
15437 
15438    astman_append(s,
15439       "Event: DAHDIShowChannelsComplete\r\n"
15440       "%s"
15441       "Items: %d\r\n"
15442       "\r\n",
15443       idText,
15444       channels);
15445    return 0;
15446 }
15447 
15448 #if defined(HAVE_SS7)
15449 static int linkset_addsigchan(int sigchan)
15450 {
15451    struct dahdi_ss7 *link;
15452    int res;
15453    int curfd;
15454    struct dahdi_params p;
15455    struct dahdi_bufferinfo bi;
15456    struct dahdi_spaninfo si;
15457 
15458 
15459    link = ss7_resolve_linkset(cur_linkset);
15460    if (!link) {
15461       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15462       return -1;
15463    }
15464 
15465    if (cur_ss7type < 0) {
15466       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15467       return -1;
15468    }
15469 
15470    if (!link->ss7)
15471       link->ss7 = ss7_new(cur_ss7type);
15472 
15473    if (!link->ss7) {
15474       ast_log(LOG_ERROR, "Can't create new SS7!\n");
15475       return -1;
15476    }
15477 
15478    link->type = cur_ss7type;
15479 
15480    if (cur_pointcode < 0) {
15481       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15482       return -1;
15483    } else
15484       ss7_set_pc(link->ss7, cur_pointcode);
15485 
15486    if (sigchan < 0) {
15487       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15488       return -1;
15489    } else {
15490       if (link->numsigchans >= NUM_DCHANS) {
15491          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15492          return -1;
15493       }
15494       curfd = link->numsigchans;
15495 
15496       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15497       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15498          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15499          return -1;
15500       }
15501       memset(&p, 0, sizeof(p));
15502       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15503       if (res) {
15504          dahdi_close_ss7_fd(link, curfd);
15505          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15506          return -1;
15507       }
15508       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15509          dahdi_close_ss7_fd(link, curfd);
15510          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15511          return -1;
15512       }
15513 
15514       memset(&bi, 0, sizeof(bi));
15515       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15516       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15517       bi.numbufs = 32;
15518       bi.bufsize = 512;
15519 
15520       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15521          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15522          dahdi_close_ss7_fd(link, curfd);
15523          return -1;
15524       }
15525 
15526       if (p.sigtype == DAHDI_SIG_MTP2)
15527          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15528       else
15529          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15530 
15531       link->numsigchans++;
15532 
15533       memset(&si, 0, sizeof(si));
15534       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15535       if (res) {
15536          dahdi_close_ss7_fd(link, curfd);
15537          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15538       }
15539 
15540       if (!si.alarms) {
15541          link->linkstate[curfd] = LINKSTATE_DOWN;
15542          ss7_link_noalarm(link->ss7, link->fds[curfd]);
15543       } else {
15544          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15545          ss7_link_alarm(link->ss7, link->fds[curfd]);
15546       }
15547    }
15548 
15549    if (cur_adjpointcode < 0) {
15550       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15551       return -1;
15552    } else {
15553       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15554    }
15555 
15556    if (cur_defaultdpc < 0) {
15557       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15558       return -1;
15559    }
15560 
15561    if (cur_networkindicator < 0) {
15562       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15563       return -1;
15564    } else
15565       ss7_set_network_ind(link->ss7, cur_networkindicator);
15566 
15567    return 0;
15568 }
15569 #endif   /* defined(HAVE_SS7) */
15570 
15571 #if defined(HAVE_SS7)
15572 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15573 {
15574    int span;
15575    switch (cmd) {
15576    case CLI_INIT:
15577       e->command = "ss7 set debug {on|off} linkset";
15578       e->usage =
15579          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15580          "       Enables debugging on a given SS7 linkset\n";
15581       return NULL;
15582    case CLI_GENERATE:
15583       return NULL;
15584    }
15585    if (a->argc < 6)
15586       return CLI_SHOWUSAGE;
15587    span = atoi(a->argv[5]);
15588    if ((span < 1) || (span > NUM_SPANS)) {
15589       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15590       return CLI_SUCCESS;
15591    }
15592    if (!linksets[span-1].ss7) {
15593       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15594       return CLI_SUCCESS;
15595    }
15596    if (linksets[span-1].ss7) {
15597       if (strcasecmp(a->argv[3], "on")) {
15598          ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15599          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15600       } else {
15601          ss7_set_debug(linksets[span-1].ss7, 0);
15602          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15603       }
15604    }
15605 
15606    return CLI_SUCCESS;
15607 }
15608 #endif   /* defined(HAVE_SS7) */
15609 
15610 #if defined(HAVE_SS7)
15611 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15612 {
15613    int linkset, cic;
15614    int blocked = -1, i;
15615    switch (cmd) {
15616    case CLI_INIT:
15617       e->command = "ss7 block cic";
15618       e->usage =
15619          "Usage: ss7 block cic <linkset> <CIC>\n"
15620          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15621       return NULL;
15622    case CLI_GENERATE:
15623       return NULL;
15624    }
15625    if (a->argc == 5)
15626       linkset = atoi(a->argv[3]);
15627    else
15628       return CLI_SHOWUSAGE;
15629 
15630    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15631       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15632       return CLI_SUCCESS;
15633    }
15634 
15635    if (!linksets[linkset-1].ss7) {
15636       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15637       return CLI_SUCCESS;
15638    }
15639 
15640    cic = atoi(a->argv[4]);
15641 
15642    if (cic < 1) {
15643       ast_cli(a->fd, "Invalid CIC specified!\n");
15644       return CLI_SUCCESS;
15645    }
15646 
15647    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15648       if (linksets[linkset-1].pvts[i]->cic == cic) {
15649          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15650          if (!blocked) {
15651             ast_mutex_lock(&linksets[linkset-1].lock);
15652             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15653             ast_mutex_unlock(&linksets[linkset-1].lock);
15654          }
15655       }
15656    }
15657 
15658    if (blocked < 0) {
15659       ast_cli(a->fd, "Invalid CIC specified!\n");
15660       return CLI_SUCCESS;
15661    }
15662 
15663    if (!blocked)
15664       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15665    else
15666       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15667 
15668    /* Break poll on the linkset so it sends our messages */
15669    pthread_kill(linksets[linkset-1].master, SIGURG);
15670 
15671    return CLI_SUCCESS;
15672 }
15673 #endif   /* defined(HAVE_SS7) */
15674 
15675 #if defined(HAVE_SS7)
15676 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15677 {
15678    int linkset;
15679    int i;
15680    switch (cmd) {
15681    case CLI_INIT:
15682       e->command = "ss7 block linkset";
15683       e->usage =
15684          "Usage: ss7 block linkset <linkset number>\n"
15685          "       Sends a remote blocking request for all CICs on the given linkset\n";
15686       return NULL;
15687    case CLI_GENERATE:
15688       return NULL;
15689    }
15690    if (a->argc == 4)
15691       linkset = atoi(a->argv[3]);
15692    else
15693       return CLI_SHOWUSAGE;
15694 
15695    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15696       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15697       return CLI_SUCCESS;
15698    }
15699 
15700    if (!linksets[linkset-1].ss7) {
15701       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15702       return CLI_SUCCESS;
15703    }
15704 
15705    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15706       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15707       ast_mutex_lock(&linksets[linkset-1].lock);
15708       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15709       ast_mutex_unlock(&linksets[linkset-1].lock);
15710    }
15711 
15712    /* Break poll on the linkset so it sends our messages */
15713    pthread_kill(linksets[linkset-1].master, SIGURG);
15714 
15715    return CLI_SUCCESS;
15716 }
15717 #endif   /* defined(HAVE_SS7) */
15718 
15719 #if defined(HAVE_SS7)
15720 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15721 {
15722    int linkset, cic;
15723    int i, blocked = -1;
15724    switch (cmd) {
15725    case CLI_INIT:
15726       e->command = "ss7 unblock cic";
15727       e->usage =
15728          "Usage: ss7 unblock cic <linkset> <CIC>\n"
15729          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15730       return NULL;
15731    case CLI_GENERATE:
15732       return NULL;
15733    }
15734 
15735    if (a->argc == 5)
15736       linkset = atoi(a->argv[3]);
15737    else
15738       return CLI_SHOWUSAGE;
15739 
15740    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15741       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15742       return CLI_SUCCESS;
15743    }
15744 
15745    if (!linksets[linkset-1].ss7) {
15746       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15747       return CLI_SUCCESS;
15748    }
15749 
15750    cic = atoi(a->argv[4]);
15751 
15752    if (cic < 1) {
15753       ast_cli(a->fd, "Invalid CIC specified!\n");
15754       return CLI_SUCCESS;
15755    }
15756 
15757    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15758       if (linksets[linkset-1].pvts[i]->cic == cic) {
15759          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15760          if (blocked) {
15761             ast_mutex_lock(&linksets[linkset-1].lock);
15762             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15763             ast_mutex_unlock(&linksets[linkset-1].lock);
15764          }
15765       }
15766    }
15767 
15768    if (blocked > 0)
15769       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15770 
15771    /* Break poll on the linkset so it sends our messages */
15772    pthread_kill(linksets[linkset-1].master, SIGURG);
15773 
15774    return CLI_SUCCESS;
15775 }
15776 #endif   /* defined(HAVE_SS7) */
15777 
15778 #if defined(HAVE_SS7)
15779 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15780 {
15781    int linkset;
15782    int i;
15783    switch (cmd) {
15784    case CLI_INIT:
15785       e->command = "ss7 unblock linkset";
15786       e->usage =
15787          "Usage: ss7 unblock linkset <linkset number>\n"
15788          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15789       return NULL;
15790    case CLI_GENERATE:
15791       return NULL;
15792    }
15793 
15794    if (a->argc == 4)
15795       linkset = atoi(a->argv[3]);
15796    else
15797       return CLI_SHOWUSAGE;
15798 
15799    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15800       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15801       return CLI_SUCCESS;
15802    }
15803 
15804    if (!linksets[linkset-1].ss7) {
15805       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15806       return CLI_SUCCESS;
15807    }
15808 
15809    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15810       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15811       ast_mutex_lock(&linksets[linkset-1].lock);
15812       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15813       ast_mutex_unlock(&linksets[linkset-1].lock);
15814    }
15815 
15816    /* Break poll on the linkset so it sends our messages */
15817    pthread_kill(linksets[linkset-1].master, SIGURG);
15818 
15819    return CLI_SUCCESS;
15820 }
15821 #endif   /* defined(HAVE_SS7) */
15822 
15823 #if defined(HAVE_SS7)
15824 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15825 {
15826    int linkset;
15827    struct dahdi_ss7 *ss7;
15828    switch (cmd) {
15829    case CLI_INIT:
15830       e->command = "ss7 show linkset";
15831       e->usage =
15832          "Usage: ss7 show linkset <span>\n"
15833          "       Shows the status of an SS7 linkset.\n";
15834       return NULL;
15835    case CLI_GENERATE:
15836       return NULL;
15837    }
15838 
15839    if (a->argc < 4)
15840       return CLI_SHOWUSAGE;
15841    linkset = atoi(a->argv[3]);
15842    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15843       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15844       return CLI_SUCCESS;
15845    }
15846    if (!linksets[linkset-1].ss7) {
15847       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15848       return CLI_SUCCESS;
15849    }
15850    if (linksets[linkset-1].ss7)
15851       ss7 = &linksets[linkset-1];
15852 
15853    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15854 
15855    return CLI_SUCCESS;
15856 }
15857 #endif   /* defined(HAVE_SS7) */
15858 
15859 #if defined(HAVE_SS7)
15860 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15861 {
15862    switch (cmd) {
15863    case CLI_INIT:
15864       e->command = "ss7 show version";
15865       e->usage =
15866          "Usage: ss7 show version\n"
15867          "  Show the libss7 version\n";
15868       return NULL;
15869    case CLI_GENERATE:
15870       return NULL;
15871    }
15872 
15873    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15874 
15875    return CLI_SUCCESS;
15876 }
15877 #endif   /* defined(HAVE_SS7) */
15878 
15879 #if defined(HAVE_SS7)
15880 static struct ast_cli_entry dahdi_ss7_cli[] = {
15881    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15882    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15883    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15884    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15885    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15886    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15887    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15888 };
15889 #endif   /* defined(HAVE_SS7) */
15890 
15891 static int __unload_module(void)
15892 {
15893    struct dahdi_pvt *p;
15894 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15895    int i, j;
15896 #endif
15897 
15898 #ifdef HAVE_PRI
15899    for (i = 0; i < NUM_SPANS; i++) {
15900       if (pris[i].master != AST_PTHREADT_NULL)
15901          pthread_cancel(pris[i].master);
15902    }
15903    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15904    ast_unregister_application(dahdi_send_keypad_facility_app);
15905 #ifdef HAVE_PRI_PROG_W_CAUSE
15906    ast_unregister_application(dahdi_send_callrerouting_facility_app);
15907 #endif
15908 #endif
15909 #if defined(HAVE_SS7)
15910    for (i = 0; i < NUM_SPANS; i++) {
15911       if (linksets[i].master != AST_PTHREADT_NULL)
15912          pthread_cancel(linksets[i].master);
15913       }
15914    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15915 #endif
15916 #if defined(HAVE_OPENR2)
15917    dahdi_r2_destroy_links();
15918    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15919    ast_unregister_application(dahdi_accept_r2_call_app);
15920 #endif
15921 
15922    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15923    ast_manager_unregister( "DAHDIDialOffhook" );
15924    ast_manager_unregister( "DAHDIHangup" );
15925    ast_manager_unregister( "DAHDITransfer" );
15926    ast_manager_unregister( "DAHDIDNDoff" );
15927    ast_manager_unregister( "DAHDIDNDon" );
15928    ast_manager_unregister("DAHDIShowChannels");
15929    ast_manager_unregister("DAHDIRestart");
15930    ast_channel_unregister(&dahdi_tech);
15931    ast_mutex_lock(&iflock);
15932    /* Hangup all interfaces if they have an owner */
15933    p = iflist;
15934    while (p) {
15935       if (p->owner)
15936          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15937       p = p->next;
15938    }
15939    ast_mutex_unlock(&iflock);
15940    ast_mutex_lock(&monlock);
15941    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15942       pthread_cancel(monitor_thread);
15943       pthread_kill(monitor_thread, SIGURG);
15944       pthread_join(monitor_thread, NULL);
15945    }
15946    monitor_thread = AST_PTHREADT_STOP;
15947    ast_mutex_unlock(&monlock);
15948 
15949    destroy_all_channels();
15950 
15951 #if defined(HAVE_PRI)
15952    for (i = 0; i < NUM_SPANS; i++) {
15953       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
15954          pthread_join(pris[i].master, NULL);
15955       for (j = 0; j < NUM_DCHANS; j++) {
15956          dahdi_close_pri_fd(&(pris[i]), j);
15957       }
15958    }
15959 #endif
15960 
15961 #if defined(HAVE_SS7)
15962    for (i = 0; i < NUM_SPANS; i++) {
15963       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15964          pthread_join(linksets[i].master, NULL);
15965       for (j = 0; j < NUM_DCHANS; j++) {
15966          dahdi_close_ss7_fd(&(linksets[i]), j);
15967       }
15968    }
15969 #endif
15970    ast_cond_destroy(&ss_thread_complete);
15971    return 0;
15972 }
15973 
15974 static int unload_module(void)
15975 {
15976 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15977    int y;
15978 #endif
15979 #ifdef HAVE_PRI
15980    for (y = 0; y < NUM_SPANS; y++)
15981       ast_mutex_destroy(&pris[y].lock);
15982 #endif
15983 #ifdef HAVE_SS7
15984    for (y = 0; y < NUM_SPANS; y++)
15985       ast_mutex_destroy(&linksets[y].lock);
15986 #endif /* HAVE_SS7 */
15987    return __unload_module();
15988 }
15989 
15990 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
15991 {
15992    char *c, *chan;
15993    int x, start, finish;
15994    struct dahdi_pvt *tmp;
15995 #ifdef HAVE_PRI
15996    struct dahdi_pri *pri;
15997    int trunkgroup, y;
15998 #endif
15999 
16000    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16001       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16002       return -1;
16003    }
16004 
16005    c = ast_strdupa(value);
16006 
16007 #ifdef HAVE_PRI
16008    pri = NULL;
16009    if (iscrv) {
16010       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16011          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16012          return -1;
16013       }
16014       if (trunkgroup < 1) {
16015          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16016          return -1;
16017       }
16018       c += y;
16019       for (y = 0; y < NUM_SPANS; y++) {
16020          if (pris[y].trunkgroup == trunkgroup) {
16021             pri = pris + y;
16022             break;
16023          }
16024       }
16025       if (!pri) {
16026          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16027          return -1;
16028       }
16029    }
16030 #endif
16031 
16032    while ((chan = strsep(&c, ","))) {
16033       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16034          /* Range */
16035       } else if (sscanf(chan, "%30d", &start)) {
16036          /* Just one */
16037          finish = start;
16038       } else if (!strcasecmp(chan, "pseudo")) {
16039          finish = start = CHAN_PSEUDO;
16040          if (found_pseudo)
16041             *found_pseudo = 1;
16042       } else {
16043          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16044          return -1;
16045       }
16046       if (finish < start) {
16047          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16048          x = finish;
16049          finish = start;
16050          start = x;
16051       }
16052 
16053       for (x = start; x <= finish; x++) {
16054 #ifdef HAVE_PRI
16055          tmp = mkintf(x, conf, pri, reload);
16056 #else
16057          tmp = mkintf(x, conf, NULL, reload);
16058 #endif
16059 
16060          if (tmp) {
16061 #ifdef HAVE_PRI
16062             if (pri)
16063                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16064             else
16065 #endif
16066                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16067          } else {
16068             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16069                (reload == 1) ? "reconfigure" : "register", value);
16070             return -1;
16071          }
16072       }
16073    }
16074 
16075    return 0;
16076 }
16077 
16078 /** The length of the parameters list of 'dahdichan'.
16079  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16080 #define MAX_CHANLIST_LEN 80
16081 
16082 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16083 {
16084    char *parse = ast_strdupa(data);
16085    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16086    unsigned int param_count;
16087    unsigned int x;
16088 
16089    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16090       return;
16091 
16092    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16093 
16094    /* first parameter is tap length, process it here */
16095 
16096    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16097 
16098    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16099       confp->chan.echocancel.head.tap_length = x;
16100    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16101       confp->chan.echocancel.head.tap_length = 128;
16102 
16103    /* now process any remaining parameters */
16104 
16105    for (x = 1; x < param_count; x++) {
16106       struct {
16107          char *name;
16108          char *value;
16109       } param;
16110 
16111       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16112          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16113          continue;
16114       }
16115 
16116       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16117          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16118          continue;
16119       }
16120 
16121       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16122 
16123       if (param.value) {
16124          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16125             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16126             continue;
16127          }
16128       }
16129       confp->chan.echocancel.head.param_count++;
16130    }
16131 }
16132 
16133 /*! process_dahdi() - ignore keyword 'channel' and similar */
16134 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16135 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16136 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16137 
16138 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16139 {
16140    struct dahdi_pvt *tmp;
16141    int y;
16142    int found_pseudo = 0;
16143    char dahdichan[MAX_CHANLIST_LEN] = {};
16144 
16145    for (; v; v = v->next) {
16146       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16147          continue;
16148 
16149       /* must have parkinglot in confp before build_channels is called */
16150       if (!strcasecmp(v->name, "parkinglot")) {
16151          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16152       }
16153 
16154       /* Create the interface list */
16155       if (!strcasecmp(v->name, "channel")
16156 #ifdef HAVE_PRI
16157          || !strcasecmp(v->name, "crv")
16158 #endif
16159          ) {
16160          int iscrv;
16161          if (options & PROC_DAHDI_OPT_NOCHAN) {
16162             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16163             continue;
16164          }
16165          iscrv = !strcasecmp(v->name, "crv");
16166          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16167                return -1;
16168          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16169       } else if (!strcasecmp(v->name, "buffers")) {
16170          int res;
16171          char policy[21] = "";
16172 
16173          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
16174          if (res != 2) {
16175             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
16176             confp->chan.buf_no = numbufs;
16177             continue;
16178          }
16179          if (confp->chan.buf_no < 0)
16180             confp->chan.buf_no = numbufs;
16181          if (!strcasecmp(policy, "full")) {
16182             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
16183          } else if (!strcasecmp(policy, "immediate")) {
16184             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16185 #ifdef HAVE_DAHDI_HALF_FULL
16186          } else if (!strcasecmp(policy, "half_full")) {
16187             confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
16188 #endif
16189          } else {
16190             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16191          }
16192       } else if (!strcasecmp(v->name, "faxbuffers")) {
16193          int res;
16194          char policy[21] = "";
16195 
16196          res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy);
16197          if (res != 2) {
16198             ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
16199             confp->chan.faxbuf_no = numbufs;
16200             continue;
16201          }
16202          confp->chan.usefaxbuffers = 1;
16203          if (confp->chan.faxbuf_no < 0)
16204             confp->chan.faxbuf_no = numbufs;
16205          if (!strcasecmp(policy, "full")) {
16206             confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
16207          } else if (!strcasecmp(policy, "immediate")) {
16208             confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
16209          } else {
16210             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16211             confp->chan.usefaxbuffers = 0;
16212          }
16213       } else if (!strcasecmp(v->name, "dahdichan")) {
16214          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16215       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16216          usedistinctiveringdetection = ast_true(v->value);
16217       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16218          distinctiveringaftercid = ast_true(v->value);
16219       } else if (!strcasecmp(v->name, "dring1context")) {
16220          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16221       } else if (!strcasecmp(v->name, "dring2context")) {
16222          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16223       } else if (!strcasecmp(v->name, "dring3context")) {
16224          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16225       } else if (!strcasecmp(v->name, "dring1range")) {
16226          confp->chan.drings.ringnum[0].range = atoi(v->value);
16227       } else if (!strcasecmp(v->name, "dring2range")) {
16228          confp->chan.drings.ringnum[1].range = atoi(v->value);
16229       } else if (!strcasecmp(v->name, "dring3range")) {
16230          confp->chan.drings.ringnum[2].range = atoi(v->value);
16231       } else if (!strcasecmp(v->name, "dring1")) {
16232          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]);
16233       } else if (!strcasecmp(v->name, "dring2")) {
16234          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]);
16235       } else if (!strcasecmp(v->name, "dring3")) {
16236          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]);
16237       } else if (!strcasecmp(v->name, "usecallerid")) {
16238          confp->chan.use_callerid = ast_true(v->value);
16239       } else if (!strcasecmp(v->name, "cidsignalling")) {
16240          if (!strcasecmp(v->value, "bell"))
16241             confp->chan.cid_signalling = CID_SIG_BELL;
16242          else if (!strcasecmp(v->value, "v23"))
16243             confp->chan.cid_signalling = CID_SIG_V23;
16244          else if (!strcasecmp(v->value, "dtmf"))
16245             confp->chan.cid_signalling = CID_SIG_DTMF;
16246          else if (!strcasecmp(v->value, "smdi"))
16247             confp->chan.cid_signalling = CID_SIG_SMDI;
16248          else if (!strcasecmp(v->value, "v23_jp"))
16249             confp->chan.cid_signalling = CID_SIG_V23_JP;
16250          else if (ast_true(v->value))
16251             confp->chan.cid_signalling = CID_SIG_BELL;
16252       } else if (!strcasecmp(v->name, "cidstart")) {
16253          if (!strcasecmp(v->value, "ring"))
16254             confp->chan.cid_start = CID_START_RING;
16255          else if (!strcasecmp(v->value, "polarity_in"))
16256             confp->chan.cid_start = CID_START_POLARITY_IN;
16257          else if (!strcasecmp(v->value, "polarity"))
16258             confp->chan.cid_start = CID_START_POLARITY;
16259          else if (ast_true(v->value))
16260             confp->chan.cid_start = CID_START_RING;
16261       } else if (!strcasecmp(v->name, "threewaycalling")) {
16262          confp->chan.threewaycalling = ast_true(v->value);
16263       } else if (!strcasecmp(v->name, "cancallforward")) {
16264          confp->chan.cancallforward = ast_true(v->value);
16265       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16266          if (ast_true(v->value))
16267             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16268          else
16269             confp->chan.dtmfrelax = 0;
16270       } else if (!strcasecmp(v->name, "mailbox")) {
16271          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16272       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16273          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16274             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16275          }
16276       } else if (!strcasecmp(v->name, "adsi")) {
16277          confp->chan.adsi = ast_true(v->value);
16278       } else if (!strcasecmp(v->name, "usesmdi")) {
16279          confp->chan.use_smdi = ast_true(v->value);
16280       } else if (!strcasecmp(v->name, "smdiport")) {
16281          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16282       } else if (!strcasecmp(v->name, "transfer")) {
16283          confp->chan.transfer = ast_true(v->value);
16284       } else if (!strcasecmp(v->name, "canpark")) {
16285          confp->chan.canpark = ast_true(v->value);
16286       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16287          confp->chan.echocanbridged = ast_true(v->value);
16288       } else if (!strcasecmp(v->name, "busydetect")) {
16289          confp->chan.busydetect = ast_true(v->value);
16290       } else if (!strcasecmp(v->name, "busycount")) {
16291          confp->chan.busycount = atoi(v->value);
16292       } else if (!strcasecmp(v->name, "busypattern")) {
16293          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16294             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16295          }
16296       } else if (!strcasecmp(v->name, "callprogress")) {
16297          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16298          if (ast_true(v->value))
16299             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16300       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16301          confp->chan.waitfordialtone = atoi(v->value);
16302       } else if (!strcasecmp(v->name, "faxdetect")) {
16303          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16304          if (!strcasecmp(v->value, "incoming")) {
16305             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16306          } else if (!strcasecmp(v->value, "outgoing")) {
16307             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16308          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16309             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16310       } else if (!strcasecmp(v->name, "echocancel")) {
16311          process_echocancel(confp, v->value, v->lineno);
16312       } else if (!strcasecmp(v->name, "echotraining")) {
16313          if (sscanf(v->value, "%30d", &y) == 1) {
16314             if ((y < 10) || (y > 4000)) {
16315                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16316             } else {
16317                confp->chan.echotraining = y;
16318             }
16319          } else if (ast_true(v->value)) {
16320             confp->chan.echotraining = 400;
16321          } else
16322             confp->chan.echotraining = 0;
16323       } else if (!strcasecmp(v->name, "hidecallerid")) {
16324          confp->chan.hidecallerid = ast_true(v->value);
16325       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16326          confp->chan.hidecalleridname = ast_true(v->value);
16327       } else if (!strcasecmp(v->name, "pulsedial")) {
16328          confp->chan.pulse = ast_true(v->value);
16329       } else if (!strcasecmp(v->name, "callreturn")) {
16330          confp->chan.callreturn = ast_true(v->value);
16331       } else if (!strcasecmp(v->name, "callwaiting")) {
16332          confp->chan.callwaiting = ast_true(v->value);
16333       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16334          confp->chan.callwaitingcallerid = ast_true(v->value);
16335       } else if (!strcasecmp(v->name, "context")) {
16336          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16337       } else if (!strcasecmp(v->name, "language")) {
16338          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16339       } else if (!strcasecmp(v->name, "progzone")) {
16340          ast_copy_string(progzone, v->value, sizeof(progzone));
16341       } else if (!strcasecmp(v->name, "mohinterpret")
16342          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16343          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16344       } else if (!strcasecmp(v->name, "mohsuggest")) {
16345          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16346       } else if (!strcasecmp(v->name, "parkinglot")) {
16347          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16348       } else if (!strcasecmp(v->name, "stripmsd")) {
16349          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16350          confp->chan.stripmsd = atoi(v->value);
16351       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16352          numbufs = atoi(v->value);
16353       } else if (!strcasecmp(v->name, "group")) {
16354          confp->chan.group = ast_get_group(v->value);
16355       } else if (!strcasecmp(v->name, "callgroup")) {
16356          if (!strcasecmp(v->value, "none"))
16357             confp->chan.callgroup = 0;
16358          else
16359             confp->chan.callgroup = ast_get_group(v->value);
16360       } else if (!strcasecmp(v->name, "pickupgroup")) {
16361          if (!strcasecmp(v->value, "none"))
16362             confp->chan.pickupgroup = 0;
16363          else
16364             confp->chan.pickupgroup = ast_get_group(v->value);
16365       } else if (!strcasecmp(v->name, "setvar")) {
16366          char *varname = ast_strdupa(v->value), *varval = NULL;
16367          struct ast_variable *tmpvar;
16368          if (varname && (varval = strchr(varname, '='))) {
16369             *varval++ = '\0';
16370             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16371                tmpvar->next = confp->chan.vars;
16372                confp->chan.vars = tmpvar;
16373             }
16374          }
16375       } else if (!strcasecmp(v->name, "immediate")) {
16376          confp->chan.immediate = ast_true(v->value);
16377       } else if (!strcasecmp(v->name, "transfertobusy")) {
16378          confp->chan.transfertobusy = ast_true(v->value);
16379       } else if (!strcasecmp(v->name, "mwimonitor")) {
16380          confp->chan.mwimonitor_neon = 0;
16381          confp->chan.mwimonitor_fsk = 0;
16382          confp->chan.mwimonitor_rpas = 0;
16383          if (strcasestr(v->value, "fsk")) {
16384             confp->chan.mwimonitor_fsk = 1;
16385          }
16386          if (strcasestr(v->value, "rpas")) {
16387             confp->chan.mwimonitor_rpas = 1;
16388          }
16389          if (strcasestr(v->value, "neon")) {
16390             confp->chan.mwimonitor_neon = 1;
16391          }
16392          /* If set to true or yes, assume that simple fsk is desired */
16393          if (ast_true(v->value)) {
16394             confp->chan.mwimonitor_fsk = 1;
16395          }
16396       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16397          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16398             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16399          }
16400       } else if (!strcasecmp(v->name, "rxgain")) {
16401          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16402             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16403          }
16404       } else if (!strcasecmp(v->name, "txgain")) {
16405          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16406             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16407          }
16408       } else if (!strcasecmp(v->name, "tonezone")) {
16409          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16410             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16411          }
16412       } else if (!strcasecmp(v->name, "callerid")) {
16413          if (!strcasecmp(v->value, "asreceived")) {
16414             confp->chan.cid_num[0] = '\0';
16415             confp->chan.cid_name[0] = '\0';
16416          } else {
16417             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16418          }
16419       } else if (!strcasecmp(v->name, "fullname")) {
16420          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16421       } else if (!strcasecmp(v->name, "cid_number")) {
16422          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16423       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16424          confp->chan.dahditrcallerid = ast_true(v->value);
16425       } else if (!strcasecmp(v->name, "restrictcid")) {
16426          confp->chan.restrictcid = ast_true(v->value);
16427       } else if (!strcasecmp(v->name, "usecallingpres")) {
16428          confp->chan.use_callingpres = ast_true(v->value);
16429       } else if (!strcasecmp(v->name, "accountcode")) {
16430          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16431       } else if (!strcasecmp(v->name, "amaflags")) {
16432          y = ast_cdr_amaflags2int(v->value);
16433          if (y < 0)
16434             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16435          else
16436             confp->chan.amaflags = y;
16437       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16438          confp->chan.polarityonanswerdelay = atoi(v->value);
16439       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16440          confp->chan.answeronpolarityswitch = ast_true(v->value);
16441       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16442          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16443       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16444          confp->chan.sendcalleridafter = atoi(v->value);
16445       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16446          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16447       } else if (!strcasecmp(v->name, "mwisendtype")) {
16448 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16449          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16450             mwisend_rpas = 1;
16451          } else {
16452             mwisend_rpas = 0;
16453          }
16454 #else
16455          /* Default is fsk, to turn it off you must specify nofsk */
16456          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16457          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16458             confp->chan.mwisend_fsk = 0;
16459          } else {             /* Default FSK */
16460             confp->chan.mwisend_fsk = 1;
16461          }
16462          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16463             confp->chan.mwisend_rpas = 1;
16464          } else {
16465             confp->chan.mwisend_rpas = 0;
16466          }
16467          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16468             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16469          }
16470          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16471             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16472          }
16473          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16474             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16475          }
16476 #endif
16477       } else if (reload != 1) {
16478           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16479             int orig_radio = confp->chan.radio;
16480             int orig_outsigmod = confp->chan.outsigmod;
16481             int orig_auto = confp->is_sig_auto;
16482 
16483             confp->chan.radio = 0;
16484             confp->chan.outsigmod = -1;
16485             confp->is_sig_auto = 0;
16486             if (!strcasecmp(v->value, "em")) {
16487                confp->chan.sig = SIG_EM;
16488             } else if (!strcasecmp(v->value, "em_e1")) {
16489                confp->chan.sig = SIG_EM_E1;
16490             } else if (!strcasecmp(v->value, "em_w")) {
16491                confp->chan.sig = SIG_EMWINK;
16492             } else if (!strcasecmp(v->value, "fxs_ls")) {
16493                confp->chan.sig = SIG_FXSLS;
16494             } else if (!strcasecmp(v->value, "fxs_gs")) {
16495                confp->chan.sig = SIG_FXSGS;
16496             } else if (!strcasecmp(v->value, "fxs_ks")) {
16497                confp->chan.sig = SIG_FXSKS;
16498             } else if (!strcasecmp(v->value, "fxo_ls")) {
16499                confp->chan.sig = SIG_FXOLS;
16500             } else if (!strcasecmp(v->value, "fxo_gs")) {
16501                confp->chan.sig = SIG_FXOGS;
16502             } else if (!strcasecmp(v->value, "fxo_ks")) {
16503                confp->chan.sig = SIG_FXOKS;
16504             } else if (!strcasecmp(v->value, "fxs_rx")) {
16505                confp->chan.sig = SIG_FXSKS;
16506                confp->chan.radio = 1;
16507             } else if (!strcasecmp(v->value, "fxo_rx")) {
16508                confp->chan.sig = SIG_FXOLS;
16509                confp->chan.radio = 1;
16510             } else if (!strcasecmp(v->value, "fxs_tx")) {
16511                confp->chan.sig = SIG_FXSLS;
16512                confp->chan.radio = 1;
16513             } else if (!strcasecmp(v->value, "fxo_tx")) {
16514                confp->chan.sig = SIG_FXOGS;
16515                confp->chan.radio = 1;
16516             } else if (!strcasecmp(v->value, "em_rx")) {
16517                confp->chan.sig = SIG_EM;
16518                confp->chan.radio = 1;
16519             } else if (!strcasecmp(v->value, "em_tx")) {
16520                confp->chan.sig = SIG_EM;
16521                confp->chan.radio = 1;
16522             } else if (!strcasecmp(v->value, "em_rxtx")) {
16523                confp->chan.sig = SIG_EM;
16524                confp->chan.radio = 2;
16525             } else if (!strcasecmp(v->value, "em_txrx")) {
16526                confp->chan.sig = SIG_EM;
16527                confp->chan.radio = 2;
16528             } else if (!strcasecmp(v->value, "sf")) {
16529                confp->chan.sig = SIG_SF;
16530             } else if (!strcasecmp(v->value, "sf_w")) {
16531                confp->chan.sig = SIG_SFWINK;
16532             } else if (!strcasecmp(v->value, "sf_featd")) {
16533                confp->chan.sig = SIG_FEATD;
16534             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16535                confp->chan.sig = SIG_FEATDMF;
16536             } else if (!strcasecmp(v->value, "sf_featb")) {
16537                confp->chan.sig = SIG_SF_FEATB;
16538             } else if (!strcasecmp(v->value, "sf")) {
16539                confp->chan.sig = SIG_SF;
16540             } else if (!strcasecmp(v->value, "sf_rx")) {
16541                confp->chan.sig = SIG_SF;
16542                confp->chan.radio = 1;
16543             } else if (!strcasecmp(v->value, "sf_tx")) {
16544                confp->chan.sig = SIG_SF;
16545                confp->chan.radio = 1;
16546             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16547                confp->chan.sig = SIG_SF;
16548                confp->chan.radio = 2;
16549             } else if (!strcasecmp(v->value, "sf_txrx")) {
16550                confp->chan.sig = SIG_SF;
16551                confp->chan.radio = 2;
16552             } else if (!strcasecmp(v->value, "featd")) {
16553                confp->chan.sig = SIG_FEATD;
16554             } else if (!strcasecmp(v->value, "featdmf")) {
16555                confp->chan.sig = SIG_FEATDMF;
16556             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16557                confp->chan.sig = SIG_FEATDMF_TA;
16558             } else if (!strcasecmp(v->value, "e911")) {
16559                confp->chan.sig = SIG_E911;
16560             } else if (!strcasecmp(v->value, "fgccama")) {
16561                confp->chan.sig = SIG_FGC_CAMA;
16562             } else if (!strcasecmp(v->value, "fgccamamf")) {
16563                confp->chan.sig = SIG_FGC_CAMAMF;
16564             } else if (!strcasecmp(v->value, "featb")) {
16565                confp->chan.sig = SIG_FEATB;
16566 #ifdef HAVE_PRI
16567             } else if (!strcasecmp(v->value, "pri_net")) {
16568                confp->chan.sig = SIG_PRI;
16569                confp->pri.nodetype = PRI_NETWORK;
16570             } else if (!strcasecmp(v->value, "pri_cpe")) {
16571                confp->chan.sig = SIG_PRI;
16572                confp->pri.nodetype = PRI_CPE;
16573             } else if (!strcasecmp(v->value, "bri_cpe")) {
16574                confp->chan.sig = SIG_BRI;
16575                confp->pri.nodetype = PRI_CPE;
16576             } else if (!strcasecmp(v->value, "bri_net")) {
16577                confp->chan.sig = SIG_BRI;
16578                confp->pri.nodetype = PRI_NETWORK;
16579             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16580                confp->chan.sig = SIG_BRI_PTMP;
16581                confp->pri.nodetype = PRI_CPE;
16582             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16583                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16584             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16585                confp->chan.sig = SIG_GR303FXOKS;
16586                confp->pri.nodetype = PRI_NETWORK;
16587             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16588                confp->chan.sig = SIG_GR303FXSKS;
16589                confp->pri.nodetype = PRI_CPE;
16590 #endif
16591 #ifdef HAVE_SS7
16592             } else if (!strcasecmp(v->value, "ss7")) {
16593                confp->chan.sig = SIG_SS7;
16594 #endif
16595 #ifdef HAVE_OPENR2
16596             } else if (!strcasecmp(v->value, "mfcr2")) {
16597                confp->chan.sig = SIG_MFCR2;
16598 #endif
16599             } else if (!strcasecmp(v->value, "auto")) {
16600                confp->is_sig_auto = 1;
16601             } else {
16602                confp->chan.outsigmod = orig_outsigmod;
16603                confp->chan.radio = orig_radio;
16604                confp->is_sig_auto = orig_auto;
16605                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16606             }
16607           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16608             if (!strcasecmp(v->value, "em")) {
16609                confp->chan.outsigmod = SIG_EM;
16610             } else if (!strcasecmp(v->value, "em_e1")) {
16611                confp->chan.outsigmod = SIG_EM_E1;
16612             } else if (!strcasecmp(v->value, "em_w")) {
16613                confp->chan.outsigmod = SIG_EMWINK;
16614             } else if (!strcasecmp(v->value, "sf")) {
16615                confp->chan.outsigmod = SIG_SF;
16616             } else if (!strcasecmp(v->value, "sf_w")) {
16617                confp->chan.outsigmod = SIG_SFWINK;
16618             } else if (!strcasecmp(v->value, "sf_featd")) {
16619                confp->chan.outsigmod = SIG_FEATD;
16620             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16621                confp->chan.outsigmod = SIG_FEATDMF;
16622             } else if (!strcasecmp(v->value, "sf_featb")) {
16623                confp->chan.outsigmod = SIG_SF_FEATB;
16624             } else if (!strcasecmp(v->value, "sf")) {
16625                confp->chan.outsigmod = SIG_SF;
16626             } else if (!strcasecmp(v->value, "featd")) {
16627                confp->chan.outsigmod = SIG_FEATD;
16628             } else if (!strcasecmp(v->value, "featdmf")) {
16629                confp->chan.outsigmod = SIG_FEATDMF;
16630             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16631                confp->chan.outsigmod = SIG_FEATDMF_TA;
16632             } else if (!strcasecmp(v->value, "e911")) {
16633                confp->chan.outsigmod = SIG_E911;
16634             } else if (!strcasecmp(v->value, "fgccama")) {
16635                confp->chan.outsigmod = SIG_FGC_CAMA;
16636             } else if (!strcasecmp(v->value, "fgccamamf")) {
16637                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16638             } else if (!strcasecmp(v->value, "featb")) {
16639                confp->chan.outsigmod = SIG_FEATB;
16640             } else {
16641                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16642             }
16643 #ifdef HAVE_PRI
16644          } else if (!strcasecmp(v->name, "pridialplan")) {
16645             if (!strcasecmp(v->value, "national")) {
16646                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16647             } else if (!strcasecmp(v->value, "unknown")) {
16648                confp->pri.dialplan = PRI_UNKNOWN + 1;
16649             } else if (!strcasecmp(v->value, "private")) {
16650                confp->pri.dialplan = PRI_PRIVATE + 1;
16651             } else if (!strcasecmp(v->value, "international")) {
16652                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16653             } else if (!strcasecmp(v->value, "local")) {
16654                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16655             } else if (!strcasecmp(v->value, "dynamic")) {
16656                confp->pri.dialplan = -1;
16657             } else if (!strcasecmp(v->value, "redundant")) {
16658                confp->pri.dialplan = -2;
16659             } else {
16660                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16661             }
16662          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16663             if (!strcasecmp(v->value, "national")) {
16664                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16665             } else if (!strcasecmp(v->value, "unknown")) {
16666                confp->pri.localdialplan = PRI_UNKNOWN + 1;
16667             } else if (!strcasecmp(v->value, "private")) {
16668                confp->pri.localdialplan = PRI_PRIVATE + 1;
16669             } else if (!strcasecmp(v->value, "international")) {
16670                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16671             } else if (!strcasecmp(v->value, "local")) {
16672                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16673             } else if (!strcasecmp(v->value, "dynamic")) {
16674                confp->pri.localdialplan = -1;
16675             } else if (!strcasecmp(v->value, "redundant")) {
16676                confp->pri.localdialplan = -2;
16677             } else {
16678                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16679             }
16680          } else if (!strcasecmp(v->name, "switchtype")) {
16681             if (!strcasecmp(v->value, "national"))
16682                confp->pri.switchtype = PRI_SWITCH_NI2;
16683             else if (!strcasecmp(v->value, "ni1"))
16684                confp->pri.switchtype = PRI_SWITCH_NI1;
16685             else if (!strcasecmp(v->value, "dms100"))
16686                confp->pri.switchtype = PRI_SWITCH_DMS100;
16687             else if (!strcasecmp(v->value, "4ess"))
16688                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16689             else if (!strcasecmp(v->value, "5ess"))
16690                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16691             else if (!strcasecmp(v->value, "euroisdn"))
16692                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16693             else if (!strcasecmp(v->value, "qsig"))
16694                confp->pri.switchtype = PRI_SWITCH_QSIG;
16695             else {
16696                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16697                return -1;
16698             }
16699          } else if (!strcasecmp(v->name, "nsf")) {
16700             if (!strcasecmp(v->value, "sdn"))
16701                confp->pri.nsf = PRI_NSF_SDN;
16702             else if (!strcasecmp(v->value, "megacom"))
16703                confp->pri.nsf = PRI_NSF_MEGACOM;
16704             else if (!strcasecmp(v->value, "tollfreemegacom"))
16705                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16706             else if (!strcasecmp(v->value, "accunet"))
16707                confp->pri.nsf = PRI_NSF_ACCUNET;
16708             else if (!strcasecmp(v->value, "none"))
16709                confp->pri.nsf = PRI_NSF_NONE;
16710             else {
16711                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16712                confp->pri.nsf = PRI_NSF_NONE;
16713             }
16714          } else if (!strcasecmp(v->name, "priindication")) {
16715             if (!strcasecmp(v->value, "outofband"))
16716                confp->chan.priindication_oob = 1;
16717             else if (!strcasecmp(v->value, "inband"))
16718                confp->chan.priindication_oob = 0;
16719             else
16720                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16721                   v->value, v->lineno);
16722          } else if (!strcasecmp(v->name, "priexclusive")) {
16723             confp->chan.priexclusive = ast_true(v->value);
16724          } else if (!strcasecmp(v->name, "internationalprefix")) {
16725             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16726          } else if (!strcasecmp(v->name, "nationalprefix")) {
16727             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16728          } else if (!strcasecmp(v->name, "localprefix")) {
16729             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16730          } else if (!strcasecmp(v->name, "privateprefix")) {
16731             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16732          } else if (!strcasecmp(v->name, "unknownprefix")) {
16733             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16734          } else if (!strcasecmp(v->name, "resetinterval")) {
16735             if (!strcasecmp(v->value, "never"))
16736                confp->pri.resetinterval = -1;
16737             else if (atoi(v->value) >= 60)
16738                confp->pri.resetinterval = atoi(v->value);
16739             else
16740                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16741                   v->value, v->lineno);
16742          } else if (!strcasecmp(v->name, "minunused")) {
16743             confp->pri.minunused = atoi(v->value);
16744          } else if (!strcasecmp(v->name, "minidle")) {
16745             confp->pri.minidle = atoi(v->value);
16746          } else if (!strcasecmp(v->name, "idleext")) {
16747             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16748          } else if (!strcasecmp(v->name, "idledial")) {
16749             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16750          } else if (!strcasecmp(v->name, "overlapdial")) {
16751             if (ast_true(v->value)) {
16752                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16753             } else if (!strcasecmp(v->value, "incoming")) {
16754                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16755             } else if (!strcasecmp(v->value, "outgoing")) {
16756                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16757             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16758                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16759             } else {
16760                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16761             }
16762 #ifdef HAVE_PRI_PROG_W_CAUSE
16763          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16764             if (!strcasecmp(v->value, "logical")) {
16765                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16766             } else if (!strcasecmp(v->value, "physical")) {
16767                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16768             } else {
16769                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16770             }
16771 #endif
16772          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16773             confp->pri.discardremoteholdretrieval = ast_true(v->value);
16774 #ifdef HAVE_PRI_INBANDDISCONNECT
16775          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16776             confp->pri.inbanddisconnect = ast_true(v->value);
16777 #endif
16778          } else if (!strcasecmp(v->name, "pritimer")) {
16779 #ifdef PRI_GETSET_TIMERS
16780             char tmp[20];
16781             char *timerc;
16782             char *c;
16783             int timer;
16784             int timeridx;
16785 
16786             ast_copy_string(tmp, v->value, sizeof(tmp));
16787             c = tmp;
16788             timerc = strsep(&c, ",");
16789             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16790                timeridx = pri_timer2idx(timerc);
16791                timer = atoi(c);
16792                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16793                   ast_log(LOG_WARNING,
16794                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16795                      v->lineno);
16796                } else if (!timer) {
16797                   ast_log(LOG_WARNING,
16798                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16799                      c, timerc, v->lineno);
16800                } else {
16801                   pritimers[timeridx] = timer;
16802                }
16803             } else {
16804                ast_log(LOG_WARNING,
16805                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16806                   v->value, v->lineno);
16807             }
16808 
16809          } else if (!strcasecmp(v->name, "facilityenable")) {
16810             confp->pri.facilityenable = ast_true(v->value);
16811 #endif /* PRI_GETSET_TIMERS */
16812 #endif /* HAVE_PRI */
16813 #ifdef HAVE_SS7
16814          } else if (!strcasecmp(v->name, "ss7type")) {
16815             if (!strcasecmp(v->value, "itu")) {
16816                cur_ss7type = SS7_ITU;
16817             } else if (!strcasecmp(v->value, "ansi")) {
16818                cur_ss7type = SS7_ANSI;
16819             } else
16820                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16821          } else if (!strcasecmp(v->name, "linkset")) {
16822             cur_linkset = atoi(v->value);
16823          } else if (!strcasecmp(v->name, "pointcode")) {
16824             cur_pointcode = parse_pointcode(v->value);
16825          } else if (!strcasecmp(v->name, "adjpointcode")) {
16826             cur_adjpointcode = parse_pointcode(v->value);
16827          } else if (!strcasecmp(v->name, "defaultdpc")) {
16828             cur_defaultdpc = parse_pointcode(v->value);
16829          } else if (!strcasecmp(v->name, "cicbeginswith")) {
16830             cur_cicbeginswith = atoi(v->value);
16831          } else if (!strcasecmp(v->name, "networkindicator")) {
16832             if (!strcasecmp(v->value, "national"))
16833                cur_networkindicator = SS7_NI_NAT;
16834             else if (!strcasecmp(v->value, "national_spare"))
16835                cur_networkindicator = SS7_NI_NAT_SPARE;
16836             else if (!strcasecmp(v->value, "international"))
16837                cur_networkindicator = SS7_NI_INT;
16838             else if (!strcasecmp(v->value, "international_spare"))
16839                cur_networkindicator = SS7_NI_INT_SPARE;
16840             else
16841                cur_networkindicator = -1;
16842          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16843             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16844          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16845             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16846          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16847             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16848          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16849             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16850          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16851             if (!strcasecmp(v->value, "national")) {
16852                confp->ss7.called_nai = SS7_NAI_NATIONAL;
16853             } else if (!strcasecmp(v->value, "international")) {
16854                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16855             } else if (!strcasecmp(v->value, "subscriber")) {
16856                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16857             } else if (!strcasecmp(v->value, "dynamic")) {
16858                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16859             } else {
16860                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16861             }
16862          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16863             if (!strcasecmp(v->value, "national")) {
16864                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16865             } else if (!strcasecmp(v->value, "international")) {
16866                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16867             } else if (!strcasecmp(v->value, "subscriber")) {
16868                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16869             } else if (!strcasecmp(v->value, "dynamic")) {
16870                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16871             } else {
16872                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16873             }
16874          } else if (!strcasecmp(v->name, "sigchan")) {
16875             int sigchan, res;
16876             sigchan = atoi(v->value);
16877             res = linkset_addsigchan(sigchan);
16878             if (res < 0)
16879                return -1;
16880 
16881          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16882             struct dahdi_ss7 *link;
16883             link = ss7_resolve_linkset(cur_linkset);
16884             if (!link) {
16885                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16886                return -1;
16887             }
16888             if (ast_true(v->value))
16889                link->flags |= LINKSET_FLAG_EXPLICITACM;
16890 #endif /* HAVE_SS7 */
16891 #ifdef HAVE_OPENR2
16892          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16893             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16894             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);
16895          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16896             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16897          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16898             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16899             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16900                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16901                confp->mfcr2.variant = OR2_VAR_ITU;
16902             }
16903          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16904             confp->mfcr2.mfback_timeout = atoi(v->value);
16905             if (!confp->mfcr2.mfback_timeout) {
16906                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16907                confp->mfcr2.mfback_timeout = -1;
16908             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16909                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16910             }
16911          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16912             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16913             if (confp->mfcr2.metering_pulse_timeout > 500) {
16914                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16915             }
16916          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16917             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16918          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16919             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16920          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16921             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16922          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16923             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16924          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16925             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16926          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16927             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16928          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16929             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16930          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
16931             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
16932          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16933             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16934          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16935             confp->mfcr2.max_ani = atoi(v->value);
16936             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16937                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16938             }
16939          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16940             confp->mfcr2.max_dnis = atoi(v->value);
16941             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16942                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16943             }
16944          } else if (!strcasecmp(v->name, "mfcr2_category")) {
16945             confp->mfcr2.category = openr2_proto_get_category(v->value);
16946             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
16947                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
16948                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
16949                      v->value, v->lineno);
16950             }
16951          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
16952             openr2_log_level_t tmplevel;
16953             char *clevel;
16954             char *logval = ast_strdupa(v->value);
16955             while (logval) {
16956                clevel = strsep(&logval,",");
16957                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
16958                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
16959                   continue;
16960                }
16961                confp->mfcr2.loglevel |= tmplevel;
16962             }
16963 #endif /* HAVE_OPENR2 */
16964          } else if (!strcasecmp(v->name, "cadence")) {
16965             /* setup to scan our argument */
16966             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
16967             int i;
16968             struct dahdi_ring_cadence new_cadence;
16969             int cid_location = -1;
16970             int firstcadencepos = 0;
16971             char original_args[80];
16972             int cadence_is_ok = 1;
16973 
16974             ast_copy_string(original_args, v->value, sizeof(original_args));
16975             /* 16 cadences allowed (8 pairs) */
16976             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]);
16977 
16978             /* Cadence must be even (on/off) */
16979             if (element_count % 2 == 1) {
16980                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
16981                cadence_is_ok = 0;
16982             }
16983 
16984             /* Ring cadences cannot be negative */
16985             for (i = 0; i < element_count; i++) {
16986                if (c[i] == 0) {
16987                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
16988                   cadence_is_ok = 0;
16989                   break;
16990                } else if (c[i] < 0) {
16991                   if (i % 2 == 1) {
16992                      /* Silence duration, negative possibly okay */
16993                      if (cid_location == -1) {
16994                         cid_location = i;
16995                         c[i] *= -1;
16996                      } else {
16997                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
16998                         cadence_is_ok = 0;
16999                         break;
17000                      }
17001                   } else {
17002                      if (firstcadencepos == 0) {
17003                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17004                                  /* duration will be passed negative to the DAHDI driver */
17005                      } else {
17006                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17007                         cadence_is_ok = 0;
17008                         break;
17009                      }
17010                   }
17011                }
17012             }
17013 
17014             /* Substitute our scanned cadence */
17015             for (i = 0; i < 16; i++) {
17016                new_cadence.ringcadence[i] = c[i];
17017             }
17018 
17019             if (cadence_is_ok) {
17020                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17021                if (element_count < 2) {
17022                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17023                } else {
17024                   if (cid_location == -1) {
17025                      /* user didn't say; default to first pause */
17026                      cid_location = 1;
17027                   } else {
17028                      /* convert element_index to cidrings value */
17029                      cid_location = (cid_location + 1) / 2;
17030                   }
17031                   /* ---we like their cadence; try to install it--- */
17032                   if (!user_has_defined_cadences++)
17033                      /* this is the first user-defined cadence; clear the default user cadences */
17034                      num_cadence = 0;
17035                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17036                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17037                   else {
17038                      cadences[num_cadence] = new_cadence;
17039                      cidrings[num_cadence++] = cid_location;
17040                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17041                   }
17042                }
17043             }
17044          } else if (!strcasecmp(v->name, "ringtimeout")) {
17045             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17046          } else if (!strcasecmp(v->name, "prewink")) {
17047             confp->timing.prewinktime = atoi(v->value);
17048          } else if (!strcasecmp(v->name, "preflash")) {
17049             confp->timing.preflashtime = atoi(v->value);
17050          } else if (!strcasecmp(v->name, "wink")) {
17051             confp->timing.winktime = atoi(v->value);
17052          } else if (!strcasecmp(v->name, "flash")) {
17053             confp->timing.flashtime = atoi(v->value);
17054          } else if (!strcasecmp(v->name, "start")) {
17055             confp->timing.starttime = atoi(v->value);
17056          } else if (!strcasecmp(v->name, "rxwink")) {
17057             confp->timing.rxwinktime = atoi(v->value);
17058          } else if (!strcasecmp(v->name, "rxflash")) {
17059             confp->timing.rxflashtime = atoi(v->value);
17060          } else if (!strcasecmp(v->name, "debounce")) {
17061             confp->timing.debouncetime = atoi(v->value);
17062          } else if (!strcasecmp(v->name, "toneduration")) {
17063             int toneduration;
17064             int ctlfd;
17065             int res;
17066             struct dahdi_dialparams dps;
17067 
17068             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17069             if (ctlfd == -1) {
17070                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17071                return -1;
17072             }
17073 
17074             toneduration = atoi(v->value);
17075             if (toneduration > -1) {
17076                memset(&dps, 0, sizeof(dps));
17077 
17078                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17079                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17080                if (res < 0) {
17081                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17082                   return -1;
17083                }
17084             }
17085             close(ctlfd);
17086          } else if (!strcasecmp(v->name, "defaultcic")) {
17087             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17088          } else if (!strcasecmp(v->name, "defaultozz")) {
17089             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17090          } else if (!strcasecmp(v->name, "mwilevel")) {
17091             mwilevel = atoi(v->value);
17092          }
17093       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17094          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17095    }
17096    if (dahdichan[0]) {
17097       /* The user has set 'dahdichan' */
17098       /*< \todo pass proper line number instead of 0 */
17099       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17100          return -1;
17101       }
17102    }
17103    /*< \todo why check for the pseudo in the per-channel section.
17104     * Any actual use for manual setup of the pseudo channel? */
17105    if (!found_pseudo && reload != 1) {
17106       /* use the default configuration for a channel, so
17107          that any settings from real configured channels
17108          don't "leak" into the pseudo channel config
17109       */
17110       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17111 
17112       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17113 
17114       if (tmp) {
17115          ast_verb(3, "Automatically generated pseudo channel\n");
17116       } else {
17117          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17118       }
17119    }
17120    return 0;
17121 }
17122 
17123 static int setup_dahdi(int reload)
17124 {
17125    struct ast_config *cfg, *ucfg;
17126    struct ast_variable *v;
17127    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17128    struct dahdi_chan_conf conf;
17129    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17130    const char *cat;
17131    int res;
17132 
17133 #ifdef HAVE_PRI
17134    char *c;
17135    int spanno;
17136    int i;
17137    int logicalspan;
17138    int trunkgroup;
17139    int dchannels[NUM_DCHANS];
17140 #endif
17141 
17142    cfg = ast_config_load(config, config_flags);
17143 
17144    /* Error if we have no config file */
17145    if (!cfg) {
17146       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17147       return 0;
17148    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17149       ucfg = ast_config_load("users.conf", config_flags);
17150       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17151          return 0;
17152       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17153          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17154          return 0;
17155       }
17156       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17157       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17158          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17159          ast_config_destroy(ucfg);
17160          return 0;
17161       }
17162    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17163       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17164       return 0;
17165    } else {
17166       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17167       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17168          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17169          ast_config_destroy(cfg);
17170          return 0;
17171       }
17172    }
17173 
17174    /* It's a little silly to lock it, but we mind as well just to be sure */
17175    ast_mutex_lock(&iflock);
17176 #ifdef HAVE_PRI
17177    if (reload != 1) {
17178       /* Process trunkgroups first */
17179       v = ast_variable_browse(cfg, "trunkgroups");
17180       while (v) {
17181          if (!strcasecmp(v->name, "trunkgroup")) {
17182             trunkgroup = atoi(v->value);
17183             if (trunkgroup > 0) {
17184                if ((c = strchr(v->value, ','))) {
17185                   i = 0;
17186                   memset(dchannels, 0, sizeof(dchannels));
17187                   while (c && (i < NUM_DCHANS)) {
17188                      dchannels[i] = atoi(c + 1);
17189                      if (dchannels[i] < 0) {
17190                         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);
17191                      } else
17192                         i++;
17193                      c = strchr(c + 1, ',');
17194                   }
17195                   if (i) {
17196                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17197                         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);
17198                   } else
17199                         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");
17200                   } else
17201                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17202                } else
17203                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17204             } else
17205                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17206          } else if (!strcasecmp(v->name, "spanmap")) {
17207             spanno = atoi(v->value);
17208             if (spanno > 0) {
17209                if ((c = strchr(v->value, ','))) {
17210                   trunkgroup = atoi(c + 1);
17211                   if (trunkgroup > 0) {
17212                      if ((c = strchr(c + 1, ',')))
17213                         logicalspan = atoi(c + 1);
17214                      else
17215                         logicalspan = 0;
17216                      if (logicalspan >= 0) {
17217                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17218                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17219                      } else
17220                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17221                      } else
17222                         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);
17223                   } else
17224                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17225                } else
17226                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17227             } else
17228                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17229          } else {
17230             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17231          }
17232          v = v->next;
17233       }
17234    }
17235 #endif
17236 
17237    /* Copy the default jb config over global_jbconf */
17238    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17239 
17240    mwimonitornotify[0] = '\0';
17241 
17242    v = ast_variable_browse(cfg, "channels");
17243    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17244       ast_mutex_unlock(&iflock);
17245       ast_config_destroy(cfg);
17246       if (ucfg) {
17247          ast_config_destroy(ucfg);
17248       }
17249       return res;
17250    }
17251 
17252    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17253    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17254       /* [channels] and [trunkgroups] are used. Let's also reserve
17255        * [globals] and [general] for future use
17256        */
17257       if (!strcasecmp(cat, "general") ||
17258          !strcasecmp(cat, "trunkgroups") ||
17259          !strcasecmp(cat, "globals") ||
17260          !strcasecmp(cat, "channels")) {
17261          continue;
17262       }
17263 
17264       memcpy(&conf, &base_conf, sizeof(conf));
17265 
17266       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17267          ast_mutex_unlock(&iflock);
17268          ast_config_destroy(cfg);
17269          if (ucfg) {
17270             ast_config_destroy(ucfg);
17271          }
17272          return res;
17273       }
17274    }
17275 
17276    ast_config_destroy(cfg);
17277 
17278    if (ucfg) {
17279       const char *chans;
17280 
17281       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17282 
17283       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17284          if (!strcasecmp(cat, "general")) {
17285             continue;
17286          }
17287 
17288          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17289 
17290          if (ast_strlen_zero(chans)) {
17291             continue;
17292          }
17293 
17294          memcpy(&conf, &base_conf, sizeof(conf));
17295 
17296          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17297             ast_config_destroy(ucfg);
17298             ast_mutex_unlock(&iflock);
17299             return res;
17300          }
17301       }
17302       ast_config_destroy(ucfg);
17303    }
17304    ast_mutex_unlock(&iflock);
17305 
17306 #ifdef HAVE_PRI
17307    if (reload != 1) {
17308       int x;
17309       for (x = 0; x < NUM_SPANS; x++) {
17310          if (pris[x].pvts[0]) {
17311             if (start_pri(pris + x)) {
17312                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17313                return -1;
17314             } else
17315                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17316          }
17317       }
17318    }
17319 #endif
17320 #ifdef HAVE_SS7
17321    if (reload != 1) {
17322       int x;
17323       for (x = 0; x < NUM_SPANS; x++) {
17324          if (linksets[x].ss7) {
17325             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17326                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17327                return -1;
17328             } else
17329                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17330          }
17331       }
17332    }
17333 #endif
17334 #ifdef HAVE_OPENR2
17335    if (reload != 1) {
17336       int x;
17337       for (x = 0; x < r2links_count; x++) {
17338          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17339             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17340             return -1;
17341          } else {
17342             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17343          }
17344       }
17345    }
17346 #endif
17347    /* And start the monitor for the first time */
17348    restart_monitor();
17349    return 0;
17350 }
17351 
17352 static int load_module(void)
17353 {
17354    int res;
17355 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17356    int y, i;
17357 #endif
17358 
17359 #ifdef HAVE_PRI
17360    memset(pris, 0, sizeof(pris));
17361    for (y = 0; y < NUM_SPANS; y++) {
17362       ast_mutex_init(&pris[y].lock);
17363       pris[y].offset = -1;
17364       pris[y].master = AST_PTHREADT_NULL;
17365       for (i = 0; i < NUM_DCHANS; i++)
17366          pris[y].fds[i] = -1;
17367    }
17368    pri_set_error(dahdi_pri_error);
17369    pri_set_message(dahdi_pri_message);
17370    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17371 #ifdef HAVE_PRI_PROG_W_CAUSE
17372    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17373 #endif
17374 #endif
17375 #ifdef HAVE_SS7
17376    memset(linksets, 0, sizeof(linksets));
17377    for (y = 0; y < NUM_SPANS; y++) {
17378       ast_mutex_init(&linksets[y].lock);
17379       linksets[y].master = AST_PTHREADT_NULL;
17380       for (i = 0; i < NUM_DCHANS; i++)
17381          linksets[y].fds[i] = -1;
17382    }
17383    ss7_set_error(dahdi_ss7_error);
17384    ss7_set_message(dahdi_ss7_message);
17385 #endif /* HAVE_SS7 */
17386    res = setup_dahdi(0);
17387    /* Make sure we can register our DAHDI channel type */
17388    if (res)
17389       return AST_MODULE_LOAD_DECLINE;
17390    if (ast_channel_register(&dahdi_tech)) {
17391       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17392       __unload_module();
17393       return AST_MODULE_LOAD_FAILURE;
17394    }
17395 #ifdef HAVE_PRI
17396    ast_string_field_init(&inuse, 16);
17397    ast_string_field_set(&inuse, name, "GR-303InUse");
17398    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17399 #endif
17400 #ifdef HAVE_SS7
17401    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17402 #endif
17403 #ifdef HAVE_OPENR2
17404    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17405    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17406 #endif
17407 
17408    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17409 
17410    memset(round_robin, 0, sizeof(round_robin));
17411    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17412    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17413    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17414    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17415    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17416    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17417    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17418 
17419    ast_cond_init(&ss_thread_complete, NULL);
17420 
17421    return res;
17422 }
17423 
17424 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17425 {
17426 #define  END_SILENCE_LEN 400
17427 #define  HEADER_MS 50
17428 #define  TRAILER_MS 5
17429 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17430 #define  ASCII_BYTES_PER_CHAR 80
17431 
17432    unsigned char *buf,*mybuf;
17433    struct dahdi_pvt *p = c->tech_pvt;
17434    struct pollfd fds[1];
17435    int size,res,fd,len,x;
17436    int bytes=0;
17437    /* Initial carrier (imaginary) */
17438    float cr = 1.0;
17439    float ci = 0.0;
17440    float scont = 0.0;
17441    int idx;
17442 
17443    idx = dahdi_get_index(c, p, 0);
17444    if (idx < 0) {
17445       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
17446       return -1;
17447    }
17448    if (!text[0]) return(0); /* if nothing to send, dont */
17449    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
17450    if (p->mate)
17451       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17452    else
17453       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17454    if (!buf)
17455       return -1;
17456    mybuf = buf;
17457    if (p->mate) {
17458       int codec = AST_LAW(p);
17459       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
17460          PUT_CLID_MARKMS;
17461       }
17462       /* Put actual message */
17463       for (x = 0; text[x]; x++) {
17464          PUT_CLID(text[x]);
17465       }
17466       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
17467          PUT_CLID_MARKMS;
17468       }
17469       len = bytes;
17470       buf = mybuf;
17471    } else {
17472       len = tdd_generate(p->tdd, buf, text);
17473       if (len < 1) {
17474          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17475          ast_free(mybuf);
17476          return -1;
17477       }
17478    }
17479    memset(buf + len, 0x7f, END_SILENCE_LEN);
17480    len += END_SILENCE_LEN;
17481    fd = p->subs[idx].dfd;
17482    while (len) {
17483       if (ast_check_hangup(c)) {
17484          ast_free(mybuf);
17485          return -1;
17486       }
17487       size = len;
17488       if (size > READ_SIZE)
17489          size = READ_SIZE;
17490       fds[0].fd = fd;
17491       fds[0].events = POLLOUT | POLLPRI;
17492       fds[0].revents = 0;
17493       res = poll(fds, 1, -1);
17494       if (!res) {
17495          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17496          continue;
17497       }
17498       /* if got exception */
17499       if (fds[0].revents & POLLPRI) {
17500          ast_free(mybuf);
17501          return -1;
17502       }
17503       if (!(fds[0].revents & POLLOUT)) {
17504          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17505          continue;
17506       }
17507       res = write(fd, buf, size);
17508       if (res != size) {
17509          if (res == -1) {
17510             ast_free(mybuf);
17511             return -1;
17512          }
17513          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17514          break;
17515       }
17516       len -= size;
17517       buf += size;
17518    }
17519    ast_free(mybuf);
17520    return(0);
17521 }
17522 
17523 
17524 static int reload(void)
17525 {
17526    int res = 0;
17527 
17528    res = setup_dahdi(1);
17529    if (res) {
17530       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17531       return -1;
17532    }
17533    return 0;
17534 }
17535 
17536 /* This is a workaround so that menuselect displays a proper description
17537  * AST_MODULE_INFO(, , "DAHDI Telephony"
17538  */
17539 
17540 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17541    .load = load_module,
17542    .unload = unload_module,
17543    .reload = reload,
17544    );