Sat Feb 11 06:33:06 2012

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 - 2008, 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    <use type="module">res_smdi</use>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use type="external">pri</use>
00045    <use type="external">ss7</use>
00046    <use type="external">openr2</use>
00047    <support_level>core</support_level>
00048  ***/
00049 
00050 #include "asterisk.h"
00051 
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 354498 $")
00053 
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064 
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068 /* Analog signaling is currently still present in chan_dahdi for use with
00069  * radio. Sig_analog does not currently handle any radio operations. If
00070  * radio only uses analog signaling, then the radio handling logic could
00071  * be placed in sig_analog and the duplicated code could be removed.
00072  */
00073 
00074 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077 
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif   /* defined(HAVE_SS7) */
00081 
00082 #ifdef HAVE_OPENR2
00083 /* put this here until sig_mfcr2 comes along */
00084 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00085 #include <openr2.h>
00086 #endif
00087 
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122 
00123 /*** DOCUMENTATION
00124    <application name="DAHDISendKeypadFacility" language="en_US">
00125       <synopsis>
00126          Send digits out of band over a PRI.
00127       </synopsis>
00128       <syntax>
00129          <parameter name="digits" required="true" />
00130       </syntax>
00131       <description>
00132          <para>This application will send the given string of digits in a Keypad
00133          Facility IE over the current channel.</para>
00134       </description>
00135    </application>
00136    <application name="DAHDISendCallreroutingFacility" language="en_US">
00137       <synopsis>
00138          Send an ISDN call rerouting/deflection facility message.
00139       </synopsis>
00140       <syntax argsep=",">
00141          <parameter name="destination" required="true">
00142             <para>Destination number.</para>
00143          </parameter>
00144          <parameter name="original">
00145             <para>Original called number.</para>
00146          </parameter>
00147          <parameter name="reason">
00148             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00149          </parameter>
00150       </syntax>
00151       <description>
00152          <para>This application will send an ISDN switch specific call
00153          rerouting/deflection facility message over the current channel.
00154          Supported switches depend upon the version of libpri in use.</para>
00155       </description>
00156    </application>
00157    <application name="DAHDIAcceptR2Call" language="en_US">
00158       <synopsis>
00159          Accept an R2 call if its not already accepted (you still need to answer it)
00160       </synopsis>
00161       <syntax>
00162          <parameter name="charge" required="true">
00163             <para>Yes or No.</para>
00164             <para>Whether you want to accept the call with charge or without charge.</para>
00165          </parameter>
00166       </syntax>
00167       <description>
00168          <para>This application will Accept the R2 call either with charge or no charge.</para>
00169       </description>
00170    </application>
00171    <manager name="DAHDITransfer" language="en_US">
00172       <synopsis>
00173          Transfer DAHDI Channel.
00174       </synopsis>
00175       <syntax>
00176          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00177          <parameter name="DAHDIChannel" required="true">
00178             <para>DAHDI channel number to transfer.</para>
00179          </parameter>
00180       </syntax>
00181       <description>
00182          <para>Simulate a flash hook event by the user connected to the channel.</para>
00183          <note><para>Valid only for analog channels.</para></note>
00184       </description>
00185    </manager>
00186    <manager name="DAHDIHangup" language="en_US">
00187       <synopsis>
00188          Hangup DAHDI Channel.
00189       </synopsis>
00190       <syntax>
00191          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00192          <parameter name="DAHDIChannel" required="true">
00193             <para>DAHDI channel number to hangup.</para>
00194          </parameter>
00195       </syntax>
00196       <description>
00197          <para>Simulate an on-hook event by the user connected to the channel.</para>
00198          <note><para>Valid only for analog channels.</para></note>
00199       </description>
00200    </manager>
00201    <manager name="DAHDIDialOffhook" language="en_US">
00202       <synopsis>
00203          Dial over DAHDI channel while offhook.
00204       </synopsis>
00205       <syntax>
00206          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00207          <parameter name="DAHDIChannel" required="true">
00208             <para>DAHDI channel number to dial digits.</para>
00209          </parameter>
00210          <parameter name="Number" required="true">
00211             <para>Digits to dial.</para>
00212          </parameter>
00213       </syntax>
00214       <description>
00215          <para>Generate DTMF control frames to the bridged peer.</para>
00216       </description>
00217    </manager>
00218    <manager name="DAHDIDNDon" language="en_US">
00219       <synopsis>
00220          Toggle DAHDI channel Do Not Disturb status ON.
00221       </synopsis>
00222       <syntax>
00223          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00224          <parameter name="DAHDIChannel" required="true">
00225             <para>DAHDI channel number to set DND on.</para>
00226          </parameter>
00227       </syntax>
00228       <description>
00229          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00230          <note><para>Feature only supported by analog channels.</para></note>
00231       </description>
00232    </manager>
00233    <manager name="DAHDIDNDoff" language="en_US">
00234       <synopsis>
00235          Toggle DAHDI channel Do Not Disturb status OFF.
00236       </synopsis>
00237       <syntax>
00238          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00239          <parameter name="DAHDIChannel" required="true">
00240             <para>DAHDI channel number to set DND off.</para>
00241          </parameter>
00242       </syntax>
00243       <description>
00244          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00245          <note><para>Feature only supported by analog channels.</para></note>
00246       </description>
00247    </manager>
00248    <manager name="DAHDIShowChannels" language="en_US">
00249       <synopsis>
00250          Show status of DAHDI channels.
00251       </synopsis>
00252       <syntax>
00253          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00254          <parameter name="DAHDIChannel">
00255             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00256          </parameter>
00257       </syntax>
00258       <description>
00259          <para>Similar to the CLI command "dahdi show channels".</para>
00260       </description>
00261    </manager>
00262    <manager name="DAHDIRestart" language="en_US">
00263       <synopsis>
00264          Fully Restart DAHDI channels (terminates calls).
00265       </synopsis>
00266       <syntax>
00267          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00268       </syntax>
00269       <description>
00270          <para>Equivalent to the CLI command "dahdi restart".</para>
00271       </description>
00272    </manager>
00273    <manager name="PRIShowSpans" language="en_US">
00274       <synopsis>
00275          Show status of PRI spans.
00276       </synopsis>
00277       <syntax>
00278          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00279          <parameter name="Span">
00280             <para>Specify the specific span to show.  Show all spans if zero or not present.</para>
00281          </parameter>
00282       </syntax>
00283       <description>
00284          <para>Similar to the CLI command "pri show spans".</para>
00285       </description>
00286    </manager>
00287  ***/
00288 
00289 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00290 
00291 static const char * const lbostr[] = {
00292 "0 db (CSU)/0-133 feet (DSX-1)",
00293 "133-266 feet (DSX-1)",
00294 "266-399 feet (DSX-1)",
00295 "399-533 feet (DSX-1)",
00296 "533-655 feet (DSX-1)",
00297 "-7.5db (CSU)",
00298 "-15db (CSU)",
00299 "-22.5db (CSU)"
00300 };
00301 
00302 /*! Global jitterbuffer configuration - by default, jb is disabled
00303  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00304 static struct ast_jb_conf default_jbconf =
00305 {
00306    .flags = 0,
00307    .max_size = 200,
00308    .resync_threshold = 1000,
00309    .impl = "fixed",
00310    .target_extra = 40,
00311 };
00312 static struct ast_jb_conf global_jbconf;
00313 
00314 /*!
00315  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00316  * the user hangs up to reset the state machine so ring works properly.
00317  * This is used to be able to support kewlstart by putting the zhone in
00318  * groundstart mode since their forward disconnect supervision is entirely
00319  * broken even though their documentation says it isn't and their support
00320  * is entirely unwilling to provide any assistance with their channel banks
00321  * even though their web site says they support their products for life.
00322  */
00323 /* #define ZHONE_HACK */
00324 
00325 /*! \brief Typically, how many rings before we should send Caller*ID */
00326 #define DEFAULT_CIDRINGS 1
00327 
00328 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00329 
00330 
00331 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00332 #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))
00333 
00334 static const char tdesc[] = "DAHDI Telephony Driver"
00335 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00336    " w/"
00337    #if defined(HAVE_PRI)
00338       "PRI"
00339    #endif   /* defined(HAVE_PRI) */
00340    #if defined(HAVE_SS7)
00341       #if defined(HAVE_PRI)
00342       " & "
00343       #endif   /* defined(HAVE_PRI) */
00344       "SS7"
00345    #endif   /* defined(HAVE_SS7) */
00346    #if defined(HAVE_OPENR2)
00347       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00348       " & "
00349       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00350       "MFC/R2"
00351    #endif   /* defined(HAVE_OPENR2) */
00352 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00353 ;
00354 
00355 static const char config[] = "chan_dahdi.conf";
00356 
00357 #define SIG_EM    DAHDI_SIG_EM
00358 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00359 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00360 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00361 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00362 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00363 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00364 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00365 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00366 #define SIG_FXSLS DAHDI_SIG_FXSLS
00367 #define SIG_FXSGS DAHDI_SIG_FXSGS
00368 #define SIG_FXSKS DAHDI_SIG_FXSKS
00369 #define SIG_FXOLS DAHDI_SIG_FXOLS
00370 #define SIG_FXOGS DAHDI_SIG_FXOGS
00371 #define SIG_FXOKS DAHDI_SIG_FXOKS
00372 #define SIG_PRI      DAHDI_SIG_CLEAR
00373 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00374 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00375 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00376 #define SIG_MFCR2    DAHDI_SIG_CAS
00377 #define  SIG_SF      DAHDI_SIG_SF
00378 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00379 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00380 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00381 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00382 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00383 
00384 #ifdef LOTS_OF_SPANS
00385 #define NUM_SPANS DAHDI_MAX_SPANS
00386 #else
00387 #define NUM_SPANS       32
00388 #endif
00389 
00390 #define CHAN_PSEUDO  -2
00391 
00392 #define CALLPROGRESS_PROGRESS    1
00393 #define CALLPROGRESS_FAX_OUTGOING   2
00394 #define CALLPROGRESS_FAX_INCOMING   4
00395 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00396 
00397 #define NUM_CADENCE_MAX 25
00398 static int num_cadence = 4;
00399 static int user_has_defined_cadences = 0;
00400 
00401 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00402    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00403    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00404    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00405    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00406 };
00407 
00408 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00409  * is 1, the second pause is 2 and so on.
00410  */
00411 
00412 static int cidrings[NUM_CADENCE_MAX] = {
00413    2,                            /*!< Right after first long ring */
00414    4,                            /*!< Right after long part */
00415    3,                            /*!< After third chirp */
00416    2,                            /*!< Second spell */
00417 };
00418 
00419 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00420 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00421 
00422 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00423          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00424 
00425 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00426 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00427 
00428 static char defaultcic[64] = "";
00429 static char defaultozz[64] = "";
00430 
00431 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00432 static char mwimonitornotify[PATH_MAX] = "";
00433 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00434 static int  mwisend_rpas = 0;
00435 #endif
00436 
00437 static char progzone[10] = "";
00438 
00439 static int usedistinctiveringdetection = 0;
00440 static int distinctiveringaftercid = 0;
00441 
00442 static int numbufs = 4;
00443 
00444 static int mwilevel = 512;
00445 static int dtmfcid_level = 256;
00446 
00447 #define REPORT_CHANNEL_ALARMS 1
00448 #define REPORT_SPAN_ALARMS    2 
00449 static int report_alarms = REPORT_CHANNEL_ALARMS;
00450 
00451 #ifdef HAVE_PRI
00452 static int pridebugfd = -1;
00453 static char pridebugfilename[1024] = "";
00454 #endif
00455 
00456 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00457 static int firstdigittimeout = 16000;
00458 
00459 /*! \brief How long to wait for following digits (FXO logic) */
00460 static int gendigittimeout = 8000;
00461 
00462 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00463 static int matchdigittimeout = 3000;
00464 
00465 /*! \brief Protect the interface list (of dahdi_pvt's) */
00466 AST_MUTEX_DEFINE_STATIC(iflock);
00467 
00468 
00469 static int ifcount = 0;
00470 
00471 #ifdef HAVE_PRI
00472 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00473 #endif
00474 
00475 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00476    when it's doing something critical. */
00477 AST_MUTEX_DEFINE_STATIC(monlock);
00478 
00479 /*! \brief This is the thread for the monitor which checks for input on the channels
00480    which are not currently in use. */
00481 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00482 static ast_cond_t ss_thread_complete;
00483 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00484 AST_MUTEX_DEFINE_STATIC(restart_lock);
00485 static int ss_thread_count = 0;
00486 static int num_restart_pending = 0;
00487 
00488 static int restart_monitor(void);
00489 
00490 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);
00491 
00492 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00493 
00494 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00495 {
00496    /* This module does not handle MWI in an event-based manner.  However, it
00497     * subscribes to MWI for each mailbox that is configured so that the core
00498     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00499     * event cache instead of checking the mailbox directly. */
00500 }
00501 
00502 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00503 static inline int dahdi_get_event(int fd)
00504 {
00505    int j;
00506    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00507       return -1;
00508    return j;
00509 }
00510 
00511 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00512 static inline int dahdi_wait_event(int fd)
00513 {
00514    int i, j = 0;
00515    i = DAHDI_IOMUX_SIGEVENT;
00516    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00517       return -1;
00518    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00519       return -1;
00520    return j;
00521 }
00522 
00523 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00524 #define READ_SIZE 160
00525 
00526 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00527 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00528 
00529 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00530 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00531 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00532 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00533 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00534 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00535 
00536 struct dahdi_pvt;
00537 
00538 /*!
00539  * \brief Configured ring timeout base.
00540  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00541  */
00542 static int ringt_base = DEFAULT_RINGT;
00543 
00544 #if defined(HAVE_SS7)
00545 
00546 struct dahdi_ss7 {
00547    struct sig_ss7_linkset ss7;
00548 };
00549 
00550 static struct dahdi_ss7 linksets[NUM_SPANS];
00551 
00552 static int cur_ss7type = -1;
00553 static int cur_linkset = -1;
00554 static int cur_pointcode = -1;
00555 static int cur_cicbeginswith = -1;
00556 static int cur_adjpointcode = -1;
00557 static int cur_networkindicator = -1;
00558 static int cur_defaultdpc = -1;
00559 #endif   /* defined(HAVE_SS7) */
00560 
00561 #ifdef HAVE_OPENR2
00562 struct dahdi_mfcr2 {
00563    pthread_t r2master;            /*!< Thread of master */
00564    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00565    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00566    int numchans;                          /*!< Number of channels in this R2 block */
00567    int monitored_count;                   /*!< Number of channels being monitored */
00568 };
00569 
00570 struct dahdi_mfcr2_conf {
00571    openr2_variant_t variant;
00572    int mfback_timeout;
00573    int metering_pulse_timeout;
00574    int max_ani;
00575    int max_dnis;
00576 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00577    int dtmf_time_on;
00578    int dtmf_time_off;
00579 #endif
00580 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00581    int dtmf_end_timeout;
00582 #endif
00583    signed int get_ani_first:2;
00584 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00585    signed int skip_category_request:2;
00586 #endif
00587    unsigned int call_files:1;
00588    unsigned int allow_collect_calls:1;
00589    unsigned int charge_calls:1;
00590    unsigned int accept_on_offer:1;
00591    unsigned int forced_release:1;
00592    unsigned int double_answer:1;
00593    signed int immediate_accept:2;
00594 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00595    signed int dtmf_dialing:2;
00596    signed int dtmf_detection:2;
00597 #endif
00598    char logdir[OR2_MAX_PATH];
00599    char r2proto_file[OR2_MAX_PATH];
00600    openr2_log_level_t loglevel;
00601    openr2_calling_party_category_t category;
00602 };
00603 
00604 /* malloc'd array of malloc'd r2links */
00605 static struct dahdi_mfcr2 **r2links;
00606 /* how many r2links have been malloc'd */
00607 static int r2links_count = 0;
00608 
00609 #endif /* HAVE_OPENR2 */
00610 
00611 #ifdef HAVE_PRI
00612 
00613 struct dahdi_pri {
00614    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00615    int mastertrunkgroup;               /*!< What trunk group is our master */
00616    int prilogicalspan;                 /*!< Logical span number within trunk group */
00617    struct sig_pri_span pri;
00618 };
00619 
00620 static struct dahdi_pri pris[NUM_SPANS];
00621 
00622 #if defined(HAVE_PRI_CCSS)
00623 /*! DAHDI PRI CCSS agent and monitor type name. */
00624 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00625 #endif   /* defined(HAVE_PRI_CCSS) */
00626 
00627 #else
00628 /*! Shut up the compiler */
00629 struct dahdi_pri;
00630 #endif
00631 
00632 #define SUB_REAL  0        /*!< Active call */
00633 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00634 #define SUB_THREEWAY 2        /*!< Three-way call */
00635 
00636 /* Polarity states */
00637 #define POLARITY_IDLE   0
00638 #define POLARITY_REV    1
00639 
00640 
00641 struct distRingData {
00642    int ring[3];
00643    int range;
00644 };
00645 struct ringContextData {
00646    char contextData[AST_MAX_CONTEXT];
00647 };
00648 struct dahdi_distRings {
00649    struct distRingData ringnum[3];
00650    struct ringContextData ringContext[3];
00651 };
00652 
00653 static const char * const subnames[] = {
00654    "Real",
00655    "Callwait",
00656    "Threeway"
00657 };
00658 
00659 struct dahdi_subchannel {
00660    int dfd;
00661    struct ast_channel *owner;
00662    int chan;
00663    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00664    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00665    unsigned int needringing:1;
00666    unsigned int needbusy:1;
00667    unsigned int needcongestion:1;
00668    unsigned int needanswer:1;
00669    unsigned int needflash:1;
00670    unsigned int needhold:1;
00671    unsigned int needunhold:1;
00672    unsigned int linear:1;
00673    unsigned int inthreeway:1;
00674    struct dahdi_confinfo curconf;
00675 };
00676 
00677 #define CONF_USER_REAL     (1 << 0)
00678 #define CONF_USER_THIRDCALL   (1 << 1)
00679 
00680 #define MAX_SLAVES   4
00681 
00682 /* States for sending MWI message
00683  * First three states are required for send Ring Pulse Alert Signal
00684  */
00685 typedef enum {
00686    MWI_SEND_NULL = 0,
00687    MWI_SEND_SA,
00688    MWI_SEND_SA_WAIT,
00689    MWI_SEND_PAUSE,
00690    MWI_SEND_SPILL,
00691    MWI_SEND_CLEANUP,
00692    MWI_SEND_DONE,
00693 } mwisend_states;
00694 
00695 struct mwisend_info {
00696    struct   timeval  pause;
00697    mwisend_states    mwisend_current;
00698 };
00699 
00700 /*! Specify the lists dahdi_pvt can be put in. */
00701 enum DAHDI_IFLIST {
00702    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00703    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00704 #if defined(HAVE_PRI)
00705    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00706 #endif   /* defined(HAVE_PRI) */
00707 };
00708 
00709 struct dahdi_pvt {
00710    ast_mutex_t lock;             /*!< Channel private lock. */
00711    struct callerid_state *cs;
00712    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00713                      /*!< Up to three channels can be associated with this call */
00714 
00715    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00716    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00717    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00718 
00719    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00720    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00721    int inconference;          /*!< If our real should be in the conference */
00722 
00723    int bufsize;                /*!< Size of the buffers */
00724    int buf_no;             /*!< Number of buffers */
00725    int buf_policy;            /*!< Buffer policy */
00726    int faxbuf_no;              /*!< Number of Fax buffers */
00727    int faxbuf_policy;          /*!< Fax buffer policy */
00728    int sig;             /*!< Signalling style */
00729    /*!
00730     * \brief Nonzero if the signaling type is sent over a radio.
00731     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00732     */
00733    int radio;
00734    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00735    int oprmode;               /*!< "Operator Services" mode */
00736    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00737    /*! \brief Amount of gain to increase during caller id */
00738    float cid_rxgain;
00739    /*! \brief Rx gain set by chan_dahdi.conf */
00740    float rxgain;
00741    /*! \brief Tx gain set by chan_dahdi.conf */
00742    float txgain;
00743 
00744    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00745    float rxdrc;
00746    
00747    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00748    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00749    struct dahdi_pvt *next;          /*!< Next channel in list */
00750    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00751 
00752    /* flags */
00753 
00754    /*!
00755     * \brief TRUE if ADSI (Analog Display Services Interface) available
00756     * \note Set from the "adsi" value read in from chan_dahdi.conf
00757     */
00758    unsigned int adsi:1;
00759    /*!
00760     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00761     * call is answered by the remote party.
00762     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00763     */
00764    unsigned int answeronpolarityswitch:1;
00765    /*!
00766     * \brief TRUE if busy detection is enabled.
00767     * (Listens for the beep-beep busy pattern.)
00768     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00769     */
00770    unsigned int busydetect:1;
00771    /*!
00772     * \brief TRUE if call return is enabled.
00773     * (*69, if your dialplan doesn't catch this first)
00774     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00775     */
00776    unsigned int callreturn:1;
00777    /*!
00778     * \brief TRUE if busy extensions will hear the call-waiting tone
00779     * and can use hook-flash to switch between callers.
00780     * \note Can be disabled by dialing *70.
00781     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00782     */
00783    unsigned int callwaiting:1;
00784    /*!
00785     * \brief TRUE if send caller ID for Call Waiting
00786     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00787     */
00788    unsigned int callwaitingcallerid:1;
00789    /*!
00790     * \brief TRUE if support for call forwarding enabled.
00791     * Dial *72 to enable call forwarding.
00792     * Dial *73 to disable call forwarding.
00793     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00794     */
00795    unsigned int cancallforward:1;
00796    /*!
00797     * \brief TRUE if support for call parking is enabled.
00798     * \note Set from the "canpark" value read in from chan_dahdi.conf
00799     */
00800    unsigned int canpark:1;
00801    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00802    unsigned int confirmanswer:1;
00803    /*!
00804     * \brief TRUE if the channel is to be destroyed on hangup.
00805     * (Used by pseudo channels.)
00806     */
00807    unsigned int destroy:1;
00808    unsigned int didtdd:1;           /*!< flag to say its done it once */
00809    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00810    unsigned int dialednone:1;
00811    /*!
00812     * \brief TRUE if in the process of dialing digits or sending something.
00813     * \note This is used as a receive squelch for ISDN until connected.
00814     */
00815    unsigned int dialing:1;
00816    /*! \brief TRUE if the transfer capability of the call is digital. */
00817    unsigned int digital:1;
00818    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00819    unsigned int dnd:1;
00820    /*! \brief XXX BOOLEAN Purpose??? */
00821    unsigned int echobreak:1;
00822    /*!
00823     * \brief TRUE if echo cancellation enabled when bridged.
00824     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00825     * \note Disabled if the echo canceller is not setup.
00826     */
00827    unsigned int echocanbridged:1;
00828    /*! \brief TRUE if echo cancellation is turned on. */
00829    unsigned int echocanon:1;
00830    /*! \brief TRUE if a fax tone has already been handled. */
00831    unsigned int faxhandled:1;
00832    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00833    unsigned int usefaxbuffers:1;
00834    /*! TRUE while buffer configuration override is in use */
00835    unsigned int bufferoverrideinuse:1;
00836    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00837    unsigned int firstradio:1;
00838    /*!
00839     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00840     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00841     */
00842    unsigned int hanguponpolarityswitch:1;
00843    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00844    unsigned int hardwaredtmf:1;
00845    /*!
00846     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00847     * \note Caller ID can be disabled by dialing *67.
00848     * \note Caller ID can be enabled by dialing *82.
00849     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00850     */
00851    unsigned int hidecallerid:1;
00852    /*!
00853     * \brief TRUE if hide just the name not the number for legacy PBX use.
00854     * \note Only applies to PRI channels.
00855     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00856     */
00857    unsigned int hidecalleridname:1;
00858    /*! \brief TRUE if DTMF detection is disabled. */
00859    unsigned int ignoredtmf:1;
00860    /*!
00861     * \brief TRUE if the channel should be answered immediately
00862     * without attempting to gather any digits.
00863     * \note Set from the "immediate" value read in from chan_dahdi.conf
00864     */
00865    unsigned int immediate:1;
00866    /*! \brief TRUE if in an alarm condition. */
00867    unsigned int inalarm:1;
00868    /*! \brief TRUE if TDD in MATE mode */
00869    unsigned int mate:1;
00870    /*! \brief TRUE if we originated the call leg. */
00871    unsigned int outgoing:1;
00872    /* unsigned int overlapdial:1;         unused and potentially confusing */
00873    /*!
00874     * \brief TRUE if busy extensions will hear the call-waiting tone
00875     * and can use hook-flash to switch between callers.
00876     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00877     */
00878    unsigned int permcallwaiting:1;
00879    /*!
00880     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00881     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00882     */
00883    unsigned int permhidecallerid:1;
00884    /*!
00885     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00886     * \note Set from the "priindication" value read in from chan_dahdi.conf
00887     */
00888    unsigned int priindication_oob:1;
00889    /*!
00890     * \brief TRUE if PRI B channels are always exclusively selected.
00891     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00892     */
00893    unsigned int priexclusive:1;
00894    /*!
00895     * \brief TRUE if we will pulse dial.
00896     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00897     */
00898    unsigned int pulse:1;
00899    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00900    unsigned int pulsedial:1;
00901    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00902    /*!
00903     * \brief TRUE if caller ID is restricted.
00904     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00905     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00906     */
00907    unsigned int restrictcid:1;
00908    /*!
00909     * \brief TRUE if three way calling is enabled
00910     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00911     */
00912    unsigned int threewaycalling:1;
00913    /*!
00914     * \brief TRUE if call transfer is enabled
00915     * \note For FXS ports (either direct analog or over T1/E1):
00916     *   Support flash-hook call transfer
00917     * \note For digital ports using ISDN PRI protocols:
00918     *   Support switch-side transfer (called 2BCT, RLT or other names)
00919     * \note Set from the "transfer" value read in from chan_dahdi.conf
00920     */
00921    unsigned int transfer:1;
00922    /*!
00923     * \brief TRUE if caller ID is used on this channel.
00924     * \note PRI and SS7 spans will save caller ID from the networking peer.
00925     * \note FXS ports will generate the caller ID spill.
00926     * \note FXO ports will listen for the caller ID spill.
00927     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00928     */
00929    unsigned int use_callerid:1;
00930    /*!
00931     * \brief TRUE if we will use the calling presentation setting
00932     * from the Asterisk channel for outgoing calls.
00933     * \note Only applies to PRI and SS7 channels.
00934     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00935     */
00936    unsigned int use_callingpres:1;
00937    /*!
00938     * \brief TRUE if distinctive rings are to be detected.
00939     * \note For FXO lines
00940     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00941     */
00942    unsigned int usedistinctiveringdetection:1;
00943    /*!
00944     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00945     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00946     */
00947    unsigned int dahditrcallerid:1;
00948    /*!
00949     * \brief TRUE if allowed to flash-transfer to busy channels.
00950     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00951     */
00952    unsigned int transfertobusy:1;
00953    /*!
00954     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00955     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00956     */
00957    unsigned int mwimonitor_neon:1;
00958    /*!
00959     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00960     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00961     */
00962    unsigned int mwimonitor_fsk:1;
00963    /*!
00964     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00965     * \note RPAS - Ring Pulse Alert Signal
00966     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00967     */
00968    unsigned int mwimonitor_rpas:1;
00969    /*! \brief TRUE if an MWI monitor thread is currently active */
00970    unsigned int mwimonitoractive:1;
00971    /*! \brief TRUE if a MWI message sending thread is active */
00972    unsigned int mwisendactive:1;
00973    /*!
00974     * \brief TRUE if channel is out of reset and ready
00975     * \note Set but not used.
00976     */
00977    unsigned int inservice:1;
00978    /*!
00979     * \brief TRUE if the channel is locally blocked.
00980     * \note Applies to SS7 and MFCR2 channels.
00981     */
00982    unsigned int locallyblocked:1;
00983    /*!
00984     * \brief TRUE if the channel is remotely blocked.
00985     * \note Applies to SS7 and MFCR2 channels.
00986     */
00987    unsigned int remotelyblocked:1;
00988    /*!
00989     * \brief TRUE if the channel alarms will be managed also as Span ones
00990     * \note Applies to all channels
00991     */
00992    unsigned int manages_span_alarms:1;
00993 
00994 #if defined(HAVE_PRI)
00995    struct sig_pri_span *pri;
00996    int logicalspan;
00997 #endif
00998    /*!
00999     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
01000     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
01001     */
01002    unsigned int use_smdi:1;
01003    struct mwisend_info mwisend_data;
01004    /*! \brief The SMDI interface to get SMDI messages from. */
01005    struct ast_smdi_interface *smdi_iface;
01006 
01007    /*! \brief Distinctive Ring data */
01008    struct dahdi_distRings drings;
01009 
01010    /*!
01011     * \brief The configured context for incoming calls.
01012     * \note The "context" string read in from chan_dahdi.conf
01013     */
01014    char context[AST_MAX_CONTEXT];
01015    /*! 
01016     * \brief A description for the channel configuration
01017     * \note The "description" string read in from chan_dahdi.conf
01018     */
01019    char description[32];
01020    /*!
01021     * \brief Saved context string.
01022     */
01023    char defcontext[AST_MAX_CONTEXT];
01024    /*! \brief Extension to use in the dialplan. */
01025    char exten[AST_MAX_EXTENSION];
01026    /*!
01027     * \brief Language configured for calls.
01028     * \note The "language" string read in from chan_dahdi.conf
01029     */
01030    char language[MAX_LANGUAGE];
01031    /*!
01032     * \brief The configured music-on-hold class to use for calls.
01033     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01034     */
01035    char mohinterpret[MAX_MUSICCLASS];
01036    /*!
01037     * \brief Suggested music-on-hold class for peer channel to use for calls.
01038     * \note The "mohsuggest" string read in from chan_dahdi.conf
01039     */
01040    char mohsuggest[MAX_MUSICCLASS];
01041    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01042 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01043    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01044    char cid_ani[AST_MAX_EXTENSION];
01045 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01046    /*! \brief Automatic Number Identification code from PRI */
01047    int cid_ani2;
01048    /*! \brief Caller ID number from an incoming call. */
01049    char cid_num[AST_MAX_EXTENSION];
01050    /*!
01051     * \brief Caller ID tag from incoming call
01052     * \note the "cid_tag" string read in from chan_dahdi.conf
01053     */
01054    char cid_tag[AST_MAX_EXTENSION];
01055    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01056    int cid_ton;
01057    /*! \brief Caller ID name from an incoming call. */
01058    char cid_name[AST_MAX_EXTENSION];
01059    /*! \brief Caller ID subaddress from an incoming call. */
01060    char cid_subaddr[AST_MAX_EXTENSION];
01061    char *origcid_num;            /*!< malloced original callerid */
01062    char *origcid_name;           /*!< malloced original callerid */
01063    /*! \brief Call waiting number. */
01064    char callwait_num[AST_MAX_EXTENSION];
01065    /*! \brief Call waiting name. */
01066    char callwait_name[AST_MAX_EXTENSION];
01067    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01068    char rdnis[AST_MAX_EXTENSION];
01069    /*! \brief Dialed Number Identifier */
01070    char dnid[AST_MAX_EXTENSION];
01071    /*!
01072     * \brief Bitmapped groups this belongs to.
01073     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01074     */
01075    ast_group_t group;
01076    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01077    int law_default;
01078    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01079    int law;
01080    int confno;             /*!< Our conference */
01081    int confusers;             /*!< Who is using our conference */
01082    int propconfno;               /*!< Propagated conference number */
01083    /*!
01084     * \brief Bitmapped call groups this belongs to.
01085     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01086     */
01087    ast_group_t callgroup;
01088    /*!
01089     * \brief Bitmapped pickup groups this belongs to.
01090     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01091     */
01092    ast_group_t pickupgroup;
01093    /*!
01094     * \brief Channel variable list with associated values to set when a channel is created.
01095     * \note The "setvar" strings read in from chan_dahdi.conf
01096     */
01097    struct ast_variable *vars;
01098    int channel;               /*!< Channel Number */
01099    int span;               /*!< Span number */
01100    time_t guardtime;          /*!< Must wait this much time before using for new call */
01101    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01102    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01103    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01104    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01105    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01106    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01107    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01108    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01109    /*! \brief Analog caller ID waveform sample buffer */
01110    unsigned char *cidspill;
01111    /*! \brief Position in the cidspill buffer to send out next. */
01112    int cidpos;
01113    /*! \brief Length of the cidspill buffer containing samples. */
01114    int cidlen;
01115    /*! \brief Ring timeout timer?? */
01116    int ringt;
01117    /*!
01118     * \brief Ring timeout base.
01119     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01120     */
01121    int ringt_base;
01122    /*!
01123     * \brief Number of most significant digits/characters to strip from the dialed number.
01124     * \note Feature is deprecated.  Use dialplan logic.
01125     * \note The characters are stripped before the PRI TON/NPI prefix
01126     * characters are processed.
01127     */
01128    int stripmsd;
01129    /*!
01130     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01131     * \note
01132     * After CAS is sent, the call waiting caller id will be sent if the phone
01133     * gives a positive reply.
01134     */
01135    int callwaitcas;
01136    /*! \brief Number of call waiting rings. */
01137    int callwaitrings;
01138    /*! \brief Echo cancel parameters. */
01139    struct {
01140       struct dahdi_echocanparams head;
01141       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01142    } echocancel;
01143    /*!
01144     * \brief Echo training time. 0 = disabled
01145     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01146     */
01147    int echotraining;
01148    /*! \brief Filled with 'w'.  XXX Purpose?? */
01149    char echorest[20];
01150    /*!
01151     * \brief Number of times to see "busy" tone before hanging up.
01152     * \note Set from the "busycount" value read in from chan_dahdi.conf
01153     */
01154    int busycount;
01155    /*!
01156     * \brief Busy cadence pattern description.
01157     * \note Set from the "busypattern" value read from chan_dahdi.conf
01158     */
01159    struct ast_dsp_busy_pattern busy_cadence;
01160    /*!
01161     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01162     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01163     */
01164    int callprogress;
01165    /*!
01166     * \brief Number of milliseconds to wait for dialtone.
01167     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01168     */
01169    int waitfordialtone;
01170    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01171    struct timeval flashtime;        /*!< Last flash-hook time */
01172    /*! \brief Opaque DSP configuration structure. */
01173    struct ast_dsp *dsp;
01174    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01175    struct dahdi_dialoperation dop;
01176    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01177    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01178    char finaldial[64];
01179    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01180    int amaflags;              /*!< AMA Flags */
01181    struct tdd_state *tdd;           /*!< TDD flag */
01182    /*! \brief Accumulated call forwarding number. */
01183    char call_forward[AST_MAX_EXTENSION];
01184    /*!
01185     * \brief Voice mailbox location.
01186     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01187     */
01188    char mailbox[AST_MAX_EXTENSION];
01189    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01190    struct ast_event_sub *mwi_event_sub;
01191    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01192    char dialdest[256];
01193 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01194    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01195    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01196    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01197 #endif
01198    int distinctivering;          /*!< Which distinctivering to use */
01199    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01200    /*! \brief Holding place for event injected from outside normal operation. */
01201    int fake_event;
01202    /*!
01203     * \brief Minimal time period (ms) between the answer polarity
01204     * switch and hangup polarity switch.
01205     */
01206    int polarityonanswerdelay;
01207    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01208    struct timeval polaritydelaytv;
01209    /*!
01210     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01211     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01212     */
01213    int sendcalleridafter;
01214    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01215    int polarity;
01216    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01217    int dsp_features;
01218 #if defined(HAVE_SS7)
01219    /*! \brief SS7 control parameters */
01220    struct sig_ss7_linkset *ss7;
01221 #endif   /* defined(HAVE_SS7) */
01222 #ifdef HAVE_OPENR2
01223    struct dahdi_mfcr2 *mfcr2;
01224    openr2_chan_t *r2chan;
01225    openr2_calling_party_category_t mfcr2_recvd_category;
01226    openr2_calling_party_category_t mfcr2_category;
01227    int mfcr2_dnis_index;
01228    int mfcr2_ani_index;
01229    int mfcr2call:1;
01230    int mfcr2_answer_pending:1;
01231    int mfcr2_charge_calls:1;
01232    int mfcr2_allow_collect_calls:1;
01233    int mfcr2_forced_release:1;
01234    int mfcr2_dnis_matched:1;
01235    int mfcr2_call_accepted:1;
01236    int mfcr2_accept_on_offer:1;
01237    int mfcr2_progress_sent:1;
01238 #endif
01239    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01240    char begindigit;
01241    /*! \brief TRUE if confrence is muted. */
01242    int muting;
01243    void *sig_pvt;
01244    struct ast_cc_config_params *cc_params;
01245    /* DAHDI channel names may differ greatly from the
01246     * string that was provided to an app such as Dial. We
01247     * need to save the original string passed to dahdi_request
01248     * for call completion purposes. This way, we can replicate
01249     * the original dialed string later.
01250     */
01251    char dialstring[AST_CHANNEL_NAME];
01252 };
01253 
01254 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01255    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01256    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01257    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01258    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01259    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01260    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01261    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01262    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01263    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01265    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01266    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01267    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01268    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01269    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01270    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01271    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01272    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01273    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01274    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01275    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01276    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01277    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01278    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01279    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01280    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01281    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01282    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01283    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01284    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01285    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01286    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01287    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01288    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01289    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01290    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01291    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01292    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01293    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01294    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01295    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01296    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01297    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01298    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01299    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01300    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01301    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01302    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01303    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01304    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01305    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01306    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01307    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01308    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01309    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01310    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01311    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01312    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01313    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01314    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01315    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01316    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01317    MEMBER(dahdi_pvt, description, AST_DATA_STRING)          \
01318    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01319    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01320    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01321    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01322    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01323 
01324 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01325 
01326 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01327 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01328 
01329 #if defined(HAVE_PRI)
01330 static struct dahdi_parms_pseudo {
01331    int buf_no;             /*!< Number of buffers */
01332    int buf_policy;            /*!< Buffer policy */
01333    int faxbuf_no;              /*!< Number of Fax buffers */
01334    int faxbuf_policy;          /*!< Fax buffer policy */
01335 } dahdi_pseudo_parms;
01336 #endif   /* defined(HAVE_PRI) */
01337 
01338 /*! \brief Channel configuration from chan_dahdi.conf .
01339  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01340  * Generally there is a field here for every possible configuration item.
01341  *
01342  * The state of fields is saved along the parsing and whenever a 'channel'
01343  * statement is reached, the current dahdi_chan_conf is used to configure the
01344  * channel (struct dahdi_pvt)
01345  *
01346  * \see dahdi_chan_init for the default values.
01347  */
01348 struct dahdi_chan_conf {
01349    struct dahdi_pvt chan;
01350 #ifdef HAVE_PRI
01351    struct dahdi_pri pri;
01352 #endif
01353 
01354 #if defined(HAVE_SS7)
01355    struct dahdi_ss7 ss7;
01356 #endif   /* defined(HAVE_SS7) */
01357 
01358 #ifdef HAVE_OPENR2
01359    struct dahdi_mfcr2_conf mfcr2;
01360 #endif
01361    struct dahdi_params timing;
01362    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01363    /*! Continue configuration even if a channel is not there. */
01364    int ignore_failed_channels;
01365 
01366    /*!
01367     * \brief The serial port to listen for SMDI data on
01368     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01369     */
01370    char smdi_port[SMDI_MAX_FILENAME_LEN];
01371 };
01372 
01373 /*! returns a new dahdi_chan_conf with default values (by-value) */
01374 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01375 {
01376    /* recall that if a field is not included here it is initialized
01377     * to 0 or equivalent
01378     */
01379    struct dahdi_chan_conf conf = {
01380 #ifdef HAVE_PRI
01381       .pri.pri = {
01382          .nsf = PRI_NSF_NONE,
01383          .switchtype = PRI_SWITCH_NI2,
01384          .dialplan = PRI_UNKNOWN + 1,
01385          .localdialplan = PRI_NATIONAL_ISDN + 1,
01386          .nodetype = PRI_CPE,
01387          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01388 
01389 #if defined(HAVE_PRI_CCSS)
01390          .cc_ptmp_recall_mode = 1,/* specificRecall */
01391          .cc_qsig_signaling_link_req = 1,/* retain */
01392          .cc_qsig_signaling_link_rsp = 1,/* retain */
01393 #endif   /* defined(HAVE_PRI_CCSS) */
01394 
01395          .minunused = 2,
01396          .idleext = "",
01397          .idledial = "",
01398          .internationalprefix = "",
01399          .nationalprefix = "",
01400          .localprefix = "",
01401          .privateprefix = "",
01402          .unknownprefix = "",
01403          .resetinterval = -1,
01404       },
01405 #endif
01406 #if defined(HAVE_SS7)
01407       .ss7.ss7 = {
01408          .called_nai = SS7_NAI_NATIONAL,
01409          .calling_nai = SS7_NAI_NATIONAL,
01410          .internationalprefix = "",
01411          .nationalprefix = "",
01412          .subscriberprefix = "",
01413          .unknownprefix = ""
01414       },
01415 #endif   /* defined(HAVE_SS7) */
01416 #ifdef HAVE_OPENR2
01417       .mfcr2 = {
01418          .variant = OR2_VAR_ITU,
01419          .mfback_timeout = -1,
01420          .metering_pulse_timeout = -1,
01421          .max_ani = 10,
01422          .max_dnis = 4,
01423          .get_ani_first = -1,
01424 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01425          .skip_category_request = -1,
01426 #endif
01427          .call_files = 0,
01428          .allow_collect_calls = 0,
01429          .charge_calls = 1,
01430          .accept_on_offer = 1,
01431          .forced_release = 0,
01432          .double_answer = 0,
01433          .immediate_accept = -1,
01434 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01435          .dtmf_dialing = -1,
01436          .dtmf_detection = -1,
01437          .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01438          .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01439 #endif
01440 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01441          .dtmf_end_timeout = -1,
01442 #endif
01443          .logdir = "",
01444          .r2proto_file = "",
01445          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01446          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01447       },
01448 #endif
01449       .chan = {
01450          .context = "default",
01451          .cid_num = "",
01452          .cid_name = "",
01453          .cid_tag = "",
01454          .mohinterpret = "default",
01455          .mohsuggest = "",
01456          .parkinglot = "",
01457          .transfertobusy = 1,
01458 
01459          .cid_signalling = CID_SIG_BELL,
01460          .cid_start = CID_START_RING,
01461          .dahditrcallerid = 0,
01462          .use_callerid = 1,
01463          .sig = -1,
01464          .outsigmod = -1,
01465 
01466          .cid_rxgain = +5.0,
01467 
01468          .tonezone = -1,
01469 
01470          .echocancel.head.tap_length = 1,
01471 
01472          .busycount = 3,
01473 
01474          .accountcode = "",
01475 
01476          .mailbox = "",
01477 
01478 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01479          .mwisend_fsk = 1,
01480 #endif
01481          .polarityonanswerdelay = 600,
01482 
01483          .sendcalleridafter = DEFAULT_CIDRINGS,
01484 
01485          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01486          .buf_no = numbufs,
01487          .usefaxbuffers = 0,
01488          .cc_params = ast_cc_config_params_init(),
01489       },
01490       .timing = {
01491          .prewinktime = -1,
01492          .preflashtime = -1,
01493          .winktime = -1,
01494          .flashtime = -1,
01495          .starttime = -1,
01496          .rxwinktime = -1,
01497          .rxflashtime = -1,
01498          .debouncetime = -1
01499       },
01500       .is_sig_auto = 1,
01501       .smdi_port = "/dev/ttyS0",
01502    };
01503 
01504    return conf;
01505 }
01506 
01507 
01508 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01509 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01510 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01511 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01512 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01513 static int dahdi_hangup(struct ast_channel *ast);
01514 static int dahdi_answer(struct ast_channel *ast);
01515 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01516 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01517 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01518 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01519 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01520 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01521 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01522 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01523 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01524 static int dahdi_devicestate(const char *data);
01525 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01526 
01527 static struct ast_channel_tech dahdi_tech = {
01528    .type = "DAHDI",
01529    .description = tdesc,
01530    .requester = dahdi_request,
01531    .send_digit_begin = dahdi_digit_begin,
01532    .send_digit_end = dahdi_digit_end,
01533    .send_text = dahdi_sendtext,
01534    .call = dahdi_call,
01535    .hangup = dahdi_hangup,
01536    .answer = dahdi_answer,
01537    .read = dahdi_read,
01538    .write = dahdi_write,
01539    .bridge = dahdi_bridge,
01540    .exception = dahdi_exception,
01541    .indicate = dahdi_indicate,
01542    .fixup = dahdi_fixup,
01543    .setoption = dahdi_setoption,
01544    .queryoption = dahdi_queryoption,
01545    .func_channel_read = dahdi_func_read,
01546    .func_channel_write = dahdi_func_write,
01547    .devicestate = dahdi_devicestate,
01548    .cc_callback = dahdi_cc_callback,
01549 };
01550 
01551 #define GET_CHANNEL(p) ((p)->channel)
01552 
01553 #define SIG_PRI_LIB_HANDLE_CASES \
01554    SIG_PRI:                \
01555    case SIG_BRI:              \
01556    case SIG_BRI_PTMP
01557 
01558 /*!
01559  * \internal
01560  * \brief Determine if sig_pri handles the signaling.
01561  * \since 1.8
01562  *
01563  * \param signaling Signaling to determine if is for sig_pri.
01564  *
01565  * \return TRUE if the signaling is for sig_pri.
01566  */
01567 static inline int dahdi_sig_pri_lib_handles(int signaling)
01568 {
01569    int handles;
01570 
01571    switch (signaling) {
01572    case SIG_PRI_LIB_HANDLE_CASES:
01573       handles = 1;
01574       break;
01575    default:
01576       handles = 0;
01577       break;
01578    }
01579 
01580    return handles;
01581 }
01582 
01583 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01584 {
01585    switch (sig) {
01586    case SIG_FXOLS:
01587       return ANALOG_SIG_FXOLS;
01588    case SIG_FXOGS:
01589       return ANALOG_SIG_FXOGS;
01590    case SIG_FXOKS:
01591       return ANALOG_SIG_FXOKS;
01592    case SIG_FXSLS:
01593       return ANALOG_SIG_FXSLS;
01594    case SIG_FXSGS:
01595       return ANALOG_SIG_FXSGS;
01596    case SIG_FXSKS:
01597       return ANALOG_SIG_FXSKS;
01598    case SIG_EMWINK:
01599       return ANALOG_SIG_EMWINK;
01600    case SIG_EM:
01601       return ANALOG_SIG_EM;
01602    case SIG_EM_E1:
01603       return ANALOG_SIG_EM_E1;
01604    case SIG_FEATD:
01605       return ANALOG_SIG_FEATD;
01606    case SIG_FEATDMF:
01607       return ANALOG_SIG_FEATDMF;
01608    case SIG_E911:
01609       return SIG_E911;
01610    case SIG_FGC_CAMA:
01611       return ANALOG_SIG_FGC_CAMA;
01612    case SIG_FGC_CAMAMF:
01613       return ANALOG_SIG_FGC_CAMAMF;
01614    case SIG_FEATB:
01615       return ANALOG_SIG_FEATB;
01616    case SIG_SFWINK:
01617       return ANALOG_SIG_SFWINK;
01618    case SIG_SF:
01619       return ANALOG_SIG_SF;
01620    case SIG_SF_FEATD:
01621       return ANALOG_SIG_SF_FEATD;
01622    case SIG_SF_FEATDMF:
01623       return ANALOG_SIG_SF_FEATDMF;
01624    case SIG_FEATDMF_TA:
01625       return ANALOG_SIG_FEATDMF_TA;
01626    case SIG_SF_FEATB:
01627       return ANALOG_SIG_FEATB;
01628    default:
01629       return -1;
01630    }
01631 }
01632 
01633 
01634 static int analog_tone_to_dahditone(enum analog_tone tone)
01635 {
01636    switch (tone) {
01637    case ANALOG_TONE_RINGTONE:
01638       return DAHDI_TONE_RINGTONE;
01639    case ANALOG_TONE_STUTTER:
01640       return DAHDI_TONE_STUTTER;
01641    case ANALOG_TONE_CONGESTION:
01642       return DAHDI_TONE_CONGESTION;
01643    case ANALOG_TONE_DIALTONE:
01644       return DAHDI_TONE_DIALTONE;
01645    case ANALOG_TONE_DIALRECALL:
01646       return DAHDI_TONE_DIALRECALL;
01647    case ANALOG_TONE_INFO:
01648       return DAHDI_TONE_INFO;
01649    default:
01650       return -1;
01651    }
01652 }
01653 
01654 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01655 {
01656    int index;
01657 
01658    switch (analogsub) {
01659    case ANALOG_SUB_REAL:
01660       index = SUB_REAL;
01661       break;
01662    case ANALOG_SUB_CALLWAIT:
01663       index = SUB_CALLWAIT;
01664       break;
01665    case ANALOG_SUB_THREEWAY:
01666       index = SUB_THREEWAY;
01667       break;
01668    default:
01669       ast_log(LOG_ERROR, "Unidentified sub!\n");
01670       index = SUB_REAL;
01671    }
01672 
01673    return index;
01674 }
01675 
01676 static enum analog_event dahdievent_to_analogevent(int event);
01677 static int bump_gains(struct dahdi_pvt *p);
01678 static int dahdi_setlinear(int dfd, int linear);
01679 
01680 static int my_start_cid_detect(void *pvt, int cid_signalling)
01681 {
01682    struct dahdi_pvt *p = pvt;
01683    int index = SUB_REAL;
01684    p->cs = callerid_new(cid_signalling);
01685    if (!p->cs) {
01686       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01687       return -1;
01688    }
01689    bump_gains(p);
01690    dahdi_setlinear(p->subs[index].dfd, 0);
01691 
01692    return 0;
01693 }
01694 
01695 static int my_stop_cid_detect(void *pvt)
01696 {
01697    struct dahdi_pvt *p = pvt;
01698    int index = SUB_REAL;
01699    if (p->cs)
01700       callerid_free(p->cs);
01701    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01702    return 0;
01703 }
01704 
01705 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01706 {
01707    struct dahdi_pvt *p = pvt;
01708    struct analog_pvt *analog_p = p->sig_pvt;
01709    struct pollfd poller;
01710    char *name, *num;
01711    int index = SUB_REAL;
01712    int res;
01713    unsigned char buf[256];
01714    int flags;
01715    struct ast_format tmpfmt;
01716 
01717    poller.fd = p->subs[SUB_REAL].dfd;
01718    poller.events = POLLPRI | POLLIN;
01719    poller.revents = 0;
01720 
01721    res = poll(&poller, 1, timeout);
01722 
01723    if (poller.revents & POLLPRI) {
01724       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01725       return 1;
01726    }
01727 
01728    if (poller.revents & POLLIN) {
01729       /*** NOTES ***/
01730       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01731        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01732        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01733        * a failure and die, and returning 2 means no event was received. */
01734       res = read(p->subs[index].dfd, buf, sizeof(buf));
01735       if (res < 0) {
01736          if (errno != ELAST) {
01737             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01738             callerid_free(p->cs);
01739             return -1;
01740          }
01741       }
01742 
01743       if (analog_p->ringt > 0) {
01744          if (!(--analog_p->ringt)) {
01745             /* only return if we timeout from a ring event */
01746             return -1;
01747          }
01748       }
01749 
01750       if (p->cid_signalling == CID_SIG_V23_JP) {
01751          res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01752       } else {
01753          res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01754       }
01755       if (res < 0) {
01756          /*
01757           * The previous diagnostic message output likely
01758           * explains why it failed.
01759           */
01760          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01761          return -1;
01762       }
01763 
01764       if (res == 1) {
01765          callerid_get(p->cs, &name, &num, &flags);
01766          if (name)
01767             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01768          if (num)
01769             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01770 
01771          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01772          return 0;
01773       }
01774    }
01775 
01776    *ev = ANALOG_EVENT_NONE;
01777    return 2;
01778 }
01779 
01780 static const char *event2str(int event);
01781 static int restore_gains(struct dahdi_pvt *p);
01782 
01783 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01784 {
01785    unsigned char buf[256];
01786    int distMatches;
01787    int curRingData[RING_PATTERNS];
01788    int receivedRingT;
01789    int counter1;
01790    int counter;
01791    int i;
01792    int res;
01793    int checkaftercid = 0;
01794 
01795    struct dahdi_pvt *p = pvt;
01796    struct analog_pvt *analog_p = p->sig_pvt;
01797 
01798    if (ringdata == NULL) {
01799       ringdata = curRingData;
01800    } else {
01801       checkaftercid = 1;
01802    }
01803 
01804    /* We must have a ring by now, so, if configured, lets try to listen for
01805     * distinctive ringing */
01806    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01807       /* Clear the current ring data array so we don't have old data in it. */
01808       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01809          ringdata[receivedRingT] = 0;
01810       receivedRingT = 0;
01811       if (checkaftercid && distinctiveringaftercid)
01812          ast_verb(3, "Detecting post-CID distinctive ring\n");
01813       /* Check to see if context is what it should be, if not set to be. */
01814       else if (strcmp(p->context,p->defcontext) != 0) {
01815          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01816          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01817       }
01818 
01819       for (;;) {
01820          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01821          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01822             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01823             ast_hangup(chan);
01824             return 1;
01825          }
01826          if (i & DAHDI_IOMUX_SIGEVENT) {
01827             res = dahdi_get_event(p->subs[idx].dfd);
01828             if (res == DAHDI_EVENT_NOALARM) {
01829                p->inalarm = 0;
01830                analog_p->inalarm = 0;
01831             }
01832             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01833             res = 0;
01834             /* Let us detect distinctive ring */
01835 
01836             ringdata[receivedRingT] = analog_p->ringt;
01837 
01838             if (analog_p->ringt < analog_p->ringt_base/2)
01839                break;
01840             /* Increment the ringT counter so we can match it against
01841                values in chan_dahdi.conf for distinctive ring */
01842             if (++receivedRingT == RING_PATTERNS)
01843                break;
01844          } else if (i & DAHDI_IOMUX_READ) {
01845             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01846             if (res < 0) {
01847                if (errno != ELAST) {
01848                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01849                   ast_hangup(chan);
01850                   return 1;
01851                }
01852                break;
01853             }
01854             if (analog_p->ringt > 0) {
01855                if (!(--analog_p->ringt)) {
01856                   res = -1;
01857                   break;
01858                }
01859             }
01860          }
01861       }
01862    }
01863    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01864       /* this only shows up if you have n of the dring patterns filled in */
01865       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01866       for (counter = 0; counter < 3; counter++) {
01867       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01868          distMatches = 0;
01869          /* this only shows up if you have n of the dring patterns filled in */
01870          ast_verb(3, "Checking %d,%d,%d\n",
01871                p->drings.ringnum[counter].ring[0],
01872                p->drings.ringnum[counter].ring[1],
01873                p->drings.ringnum[counter].ring[2]);
01874          for (counter1 = 0; counter1 < 3; counter1++) {
01875             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01876             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01877                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01878                ringdata[counter1]);
01879                distMatches++;
01880             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01881                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01882                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01883                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01884                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01885                distMatches++;
01886             }
01887          }
01888 
01889          if (distMatches == 3) {
01890             /* The ring matches, set the context to whatever is for distinctive ring.. */
01891             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01892             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01893             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01894             break;
01895          }
01896       }
01897    }
01898    /* Restore linear mode (if appropriate) for Caller*ID processing */
01899    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01900    restore_gains(p);
01901 
01902    return 0;
01903 }
01904 
01905 static int my_stop_callwait(void *pvt)
01906 {
01907    struct dahdi_pvt *p = pvt;
01908    p->callwaitingrepeat = 0;
01909    p->cidcwexpire = 0;
01910    p->cid_suppress_expire = 0;
01911 
01912    return 0;
01913 }
01914 
01915 static int send_callerid(struct dahdi_pvt *p);
01916 static int save_conference(struct dahdi_pvt *p);
01917 static int restore_conference(struct dahdi_pvt *p);
01918 
01919 static int my_callwait(void *pvt)
01920 {
01921    struct dahdi_pvt *p = pvt;
01922    struct ast_format tmpfmt;
01923    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01924    if (p->cidspill) {
01925       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01926       ast_free(p->cidspill);
01927    }
01928 
01929    /*
01930     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01931     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01932     */
01933    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01934       return -1;
01935    save_conference(p);
01936    /* Silence */
01937    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01938    if (!p->callwaitrings && p->callwaitingcallerid) {
01939       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01940       p->callwaitcas = 1;
01941       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01942    } else {
01943       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01944       p->callwaitcas = 0;
01945       p->cidlen = 2400 + READ_SIZE * 4;
01946    }
01947    p->cidpos = 0;
01948    send_callerid(p);
01949 
01950    return 0;
01951 }
01952 
01953 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01954 {
01955    struct dahdi_pvt *p = pvt;
01956    struct ast_format tmpfmt;
01957 
01958    ast_debug(2, "Starting cid spill\n");
01959 
01960    if (p->cidspill) {
01961       ast_log(LOG_WARNING, "cidspill already exists??\n");
01962       ast_free(p->cidspill);
01963    }
01964 
01965    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01966       if (cwcid == 0) {
01967          p->cidlen = ast_callerid_generate(p->cidspill,
01968             caller->id.name.str,
01969             caller->id.number.str,
01970             ast_format_set(&tmpfmt, AST_LAW(p), 0));
01971       } else {
01972          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01973             caller->id.name.str, caller->id.number.str);
01974          p->callwaitcas = 0;
01975          p->cidcwexpire = 0;
01976          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01977             caller->id.name.str,
01978             caller->id.number.str,
01979             ast_format_set(&tmpfmt, AST_LAW(p), 0));
01980          p->cidlen += READ_SIZE * 4;
01981       }
01982       p->cidpos = 0;
01983       p->cid_suppress_expire = 0;
01984       send_callerid(p);
01985    }
01986    return 0;
01987 }
01988 
01989 static int my_dsp_reset_and_flush_digits(void *pvt)
01990 {
01991    struct dahdi_pvt *p = pvt;
01992    if (p->dsp)
01993       ast_dsp_digitreset(p->dsp);
01994 
01995    return 0;
01996 }
01997 
01998 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01999 {
02000    struct dahdi_pvt *p = pvt;
02001 
02002    if (p->channel == CHAN_PSEUDO)
02003       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02004 
02005    if (mode == ANALOG_DIGITMODE_DTMF) {
02006       /* If we do hardware dtmf, no need for a DSP */
02007       if (p->hardwaredtmf) {
02008          if (p->dsp) {
02009             ast_dsp_free(p->dsp);
02010             p->dsp = NULL;
02011          }
02012          return 0;
02013       }
02014 
02015       if (!p->dsp) {
02016          p->dsp = ast_dsp_new();
02017          if (!p->dsp) {
02018             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02019             return -1;
02020          }
02021       }
02022 
02023       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02024    } else if (mode == ANALOG_DIGITMODE_MF) {
02025       if (!p->dsp) {
02026          p->dsp = ast_dsp_new();
02027          if (!p->dsp) {
02028             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029             return -1;
02030          }
02031       }
02032       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02033    }
02034    return 0;
02035 }
02036 
02037 static int dahdi_wink(struct dahdi_pvt *p, int index);
02038 
02039 static int my_wink(void *pvt, enum analog_sub sub)
02040 {
02041    struct dahdi_pvt *p = pvt;
02042    int index = analogsub_to_dahdisub(sub);
02043    if (index != SUB_REAL) {
02044       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02045    }
02046    return dahdi_wink(p, index);
02047 }
02048 
02049 static void wakeup_sub(struct dahdi_pvt *p, int a);
02050 
02051 static int reset_conf(struct dahdi_pvt *p);
02052 
02053 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02054 
02055 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02056 {
02057    struct ast_frame *f = *dest;
02058    struct dahdi_pvt *p = pvt;
02059    int idx = analogsub_to_dahdisub(analog_index);
02060 
02061    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02062       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02063       f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02064 
02065    if (f->subclass.integer == 'f') {
02066       if (f->frametype == AST_FRAME_DTMF_END) {
02067          /* Fax tone -- Handle and return NULL */
02068          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02069             /* If faxbuffers are configured, use them for the fax transmission */
02070             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02071                struct dahdi_bufferinfo bi = {
02072                   .txbufpolicy = p->faxbuf_policy,
02073                   .bufsize = p->bufsize,
02074                   .numbufs = p->faxbuf_no
02075                };
02076                int res;
02077 
02078                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02079                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02080                } else {
02081                   p->bufferoverrideinuse = 1;
02082                }
02083             }
02084             p->faxhandled = 1;
02085             if (p->dsp) {
02086                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02087                ast_dsp_set_features(p->dsp, p->dsp_features);
02088                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02089             }
02090             if (strcmp(ast->exten, "fax")) {
02091                const char *target_context = S_OR(ast->macrocontext, ast->context);
02092 
02093                /* We need to unlock 'ast' here because ast_exists_extension has the
02094                 * potential to start autoservice on the channel. Such action is prone
02095                 * to deadlock.
02096                 */
02097                ast_mutex_unlock(&p->lock);
02098                ast_channel_unlock(ast);
02099                if (ast_exists_extension(ast, target_context, "fax", 1,
02100                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02101                   ast_channel_lock(ast);
02102                   ast_mutex_lock(&p->lock);
02103                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02104                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02105                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02106                   if (ast_async_goto(ast, target_context, "fax", 1))
02107                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02108                } else {
02109                   ast_channel_lock(ast);
02110                   ast_mutex_lock(&p->lock);
02111                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02112                }
02113             } else {
02114                ast_debug(1, "Already in a fax extension, not redirecting\n");
02115             }
02116          } else {
02117             ast_debug(1, "Fax already handled\n");
02118          }
02119          dahdi_confmute(p, 0);
02120       }
02121       p->subs[idx].f.frametype = AST_FRAME_NULL;
02122       p->subs[idx].f.subclass.integer = 0;
02123       *dest = &p->subs[idx].f;
02124    }
02125 }
02126 
02127 static void my_lock_private(void *pvt)
02128 {
02129    struct dahdi_pvt *p = pvt;
02130    ast_mutex_lock(&p->lock);
02131 }
02132 
02133 static void my_unlock_private(void *pvt)
02134 {
02135    struct dahdi_pvt *p = pvt;
02136    ast_mutex_unlock(&p->lock);
02137 }
02138 
02139 static void my_deadlock_avoidance_private(void *pvt)
02140 {
02141    struct dahdi_pvt *p = pvt;
02142 
02143    DEADLOCK_AVOIDANCE(&p->lock);
02144 }
02145 
02146 /*!
02147  * \internal
02148  * \brief Post an AMI DAHDI channel association event.
02149  * \since 1.8
02150  *
02151  * \param p DAHDI private pointer
02152  * \param chan Channel associated with the private pointer
02153  *
02154  * \return Nothing
02155  */
02156 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02157 {
02158    char ch_name[20];
02159 
02160    if (p->channel < CHAN_PSEUDO) {
02161       /* No B channel */
02162       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02163    } else if (p->channel == CHAN_PSEUDO) {
02164       /* Pseudo channel */
02165       strcpy(ch_name, "pseudo");
02166    } else {
02167       /* Real channel */
02168       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02169    }
02170    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02171       "Channel: %s\r\n"
02172       "Uniqueid: %s\r\n"
02173       "DAHDISpan: %d\r\n"
02174       "DAHDIChannel: %s\r\n",
02175       ast_channel_name(chan),
02176       ast_channel_uniqueid(chan),
02177       p->span,
02178       ch_name);
02179 }
02180 
02181 #ifdef HAVE_PRI
02182 /*!
02183  * \internal
02184  * \brief Post an AMI DAHDI channel association event.
02185  * \since 1.8
02186  *
02187  * \param pvt DAHDI private pointer
02188  * \param chan Channel associated with the private pointer
02189  *
02190  * \return Nothing
02191  */
02192 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02193 {
02194    struct dahdi_pvt *p = pvt;
02195 
02196    dahdi_ami_channel_event(p, chan);
02197 }
02198 #endif
02199 
02200 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02201 *  returns the last value of the linear setting 
02202 */ 
02203 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02204 {
02205    struct dahdi_pvt *p = pvt;
02206    int oldval;
02207    int idx = analogsub_to_dahdisub(sub);
02208    
02209    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02210    oldval = p->subs[idx].linear;
02211    p->subs[idx].linear = linear_mode ? 1 : 0;
02212    return oldval;
02213 }
02214 
02215 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02216 {
02217    struct dahdi_pvt *p = pvt;
02218    int idx = analogsub_to_dahdisub(sub);
02219 
02220    p->subs[idx].inthreeway = inthreeway;
02221 }
02222 
02223 static int get_alarms(struct dahdi_pvt *p);
02224 static void handle_alarms(struct dahdi_pvt *p, int alms);
02225 static void my_get_and_handle_alarms(void *pvt)
02226 {
02227    int res;
02228    struct dahdi_pvt *p = pvt;
02229 
02230    res = get_alarms(p);
02231    handle_alarms(p, res);
02232 }
02233 
02234 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02235 {
02236    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02237    if (p)
02238       return p->sig_pvt;
02239    else
02240       return NULL;
02241 }
02242 
02243 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02244 {
02245    struct dahdi_pvt *p = pvt;
02246    int dahdi_sub = analogsub_to_dahdisub(sub);
02247    return p->subs[dahdi_sub].dfd;
02248 }
02249 
02250 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02251 {
02252    struct dahdi_pvt *p = pvt;
02253 
02254    /* Choose proper cadence */
02255    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02256       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02257          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02258       *cidrings = cidrings[p->distinctivering - 1];
02259    } else {
02260       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02261          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02262       *cidrings = p->sendcalleridafter;
02263    }
02264 }
02265 
02266 static void my_set_alarm(void *pvt, int in_alarm)
02267 {
02268    struct dahdi_pvt *p = pvt;
02269 
02270    p->inalarm = in_alarm;
02271 }
02272 
02273 static void my_set_dialing(void *pvt, int is_dialing)
02274 {
02275    struct dahdi_pvt *p = pvt;
02276 
02277    p->dialing = is_dialing;
02278 }
02279 
02280 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02281 static void my_set_digital(void *pvt, int is_digital)
02282 {
02283    struct dahdi_pvt *p = pvt;
02284 
02285    p->digital = is_digital;
02286 }
02287 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02288 
02289 #if defined(HAVE_SS7)
02290 static void my_set_inservice(void *pvt, int is_inservice)
02291 {
02292    struct dahdi_pvt *p = pvt;
02293 
02294    p->inservice = is_inservice;
02295 }
02296 #endif   /* defined(HAVE_SS7) */
02297 
02298 #if defined(HAVE_SS7)
02299 static void my_set_locallyblocked(void *pvt, int is_blocked)
02300 {
02301    struct dahdi_pvt *p = pvt;
02302 
02303    p->locallyblocked = is_blocked;
02304 }
02305 #endif   /* defined(HAVE_SS7) */
02306 
02307 #if defined(HAVE_SS7)
02308 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02309 {
02310    struct dahdi_pvt *p = pvt;
02311 
02312    p->remotelyblocked = is_blocked;
02313 }
02314 #endif   /* defined(HAVE_SS7) */
02315 
02316 static void my_set_ringtimeout(void *pvt, int ringt)
02317 {
02318    struct dahdi_pvt *p = pvt;
02319    p->ringt = ringt;
02320 }
02321 
02322 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02323 {
02324    struct dahdi_pvt *p = pvt;
02325 
02326    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02327       ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02328       gettimeofday(&p->waitingfordt, NULL);
02329       ast_setstate(ast, AST_STATE_OFFHOOK);
02330    }
02331 }
02332 
02333 static int my_check_waitingfordt(void *pvt)
02334 {
02335    struct dahdi_pvt *p = pvt;
02336 
02337    if (p->waitingfordt.tv_usec) {
02338       return 1;
02339    }
02340 
02341    return 0;
02342 }
02343 
02344 static void my_set_confirmanswer(void *pvt, int flag)
02345 {
02346    struct dahdi_pvt *p = pvt;
02347    p->confirmanswer = flag;
02348 }
02349 
02350 static int my_check_confirmanswer(void *pvt)
02351 {
02352    struct dahdi_pvt *p = pvt;
02353    if (p->confirmanswer) {
02354       return 1;
02355    }
02356 
02357    return 0;
02358 }
02359 
02360 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02361 {
02362    struct dahdi_pvt *p = pvt;
02363 
02364    p->callwaiting = callwaiting_enable;
02365 }
02366 
02367 static void my_cancel_cidspill(void *pvt)
02368 {
02369    struct dahdi_pvt *p = pvt;
02370 
02371    ast_free(p->cidspill);
02372    p->cidspill = NULL;
02373    restore_conference(p);
02374 }
02375 
02376 static int my_confmute(void *pvt, int mute)
02377 {
02378    struct dahdi_pvt *p = pvt;
02379    return dahdi_confmute(p, mute);
02380 }
02381 
02382 static void my_set_pulsedial(void *pvt, int flag)
02383 {
02384    struct dahdi_pvt *p = pvt;
02385    p->pulsedial = flag;
02386 }
02387 
02388 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02389 {
02390    struct dahdi_pvt *p = pvt;
02391 
02392    p->owner = new_owner;
02393 }
02394 
02395 static const char *my_get_orig_dialstring(void *pvt)
02396 {
02397    struct dahdi_pvt *p = pvt;
02398 
02399    return p->dialstring;
02400 }
02401 
02402 static void my_increase_ss_count(void)
02403 {
02404    ast_mutex_lock(&ss_thread_lock);
02405    ss_thread_count++;
02406    ast_mutex_unlock(&ss_thread_lock);
02407 }
02408 
02409 static void my_decrease_ss_count(void)
02410 {
02411    ast_mutex_lock(&ss_thread_lock);
02412    ss_thread_count--;
02413    ast_cond_signal(&ss_thread_complete);
02414    ast_mutex_unlock(&ss_thread_lock);
02415 }
02416 
02417 static void my_all_subchannels_hungup(void *pvt)
02418 {
02419    struct dahdi_pvt *p = pvt;
02420    int res, law;
02421 
02422    p->faxhandled = 0;
02423    p->didtdd = 0;
02424 
02425    if (p->dsp) {
02426       ast_dsp_free(p->dsp);
02427       p->dsp = NULL;
02428    }
02429 
02430    p->law = p->law_default;
02431    law = p->law_default;
02432    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02433    if (res < 0)
02434       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02435 
02436    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02437 
02438 #if 1
02439    {
02440    int i;
02441    p->owner = NULL;
02442    /* Cleanup owners here */
02443    for (i = 0; i < 3; i++) {
02444       p->subs[i].owner = NULL;
02445    }
02446    }
02447 #endif
02448 
02449    reset_conf(p);
02450    if (num_restart_pending == 0) {
02451       restart_monitor();
02452    }
02453 }
02454 
02455 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02456 
02457 static int my_conf_del(void *pvt, enum analog_sub sub)
02458 {
02459    struct dahdi_pvt *p = pvt;
02460    int x = analogsub_to_dahdisub(sub);
02461 
02462    return conf_del(p, &p->subs[x], x);
02463 }
02464 
02465 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02466 
02467 static int my_conf_add(void *pvt, enum analog_sub sub)
02468 {
02469    struct dahdi_pvt *p = pvt;
02470    int x = analogsub_to_dahdisub(sub);
02471 
02472    return conf_add(p, &p->subs[x], x, 0);
02473 }
02474 
02475 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02476 
02477 static int my_complete_conference_update(void *pvt, int needconference)
02478 {
02479    struct dahdi_pvt *p = pvt;
02480    int needconf = needconference;
02481    int x;
02482    int useslavenative;
02483    struct dahdi_pvt *slave = NULL;
02484 
02485    useslavenative = isslavenative(p, &slave);
02486 
02487    /* If we have a slave, add him to our conference now. or DAX
02488       if this is slave native */
02489    for (x = 0; x < MAX_SLAVES; x++) {
02490       if (p->slaves[x]) {
02491          if (useslavenative)
02492             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02493          else {
02494             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02495             needconf++;
02496          }
02497       }
02498    }
02499    /* If we're supposed to be in there, do so now */
02500    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02501       if (useslavenative)
02502          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02503       else {
02504          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02505          needconf++;
02506       }
02507    }
02508    /* If we have a master, add ourselves to his conference */
02509    if (p->master) {
02510       if (isslavenative(p->master, NULL)) {
02511          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02512       } else {
02513          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02514       }
02515    }
02516    if (!needconf) {
02517       /* Nobody is left (or should be left) in our conference.
02518          Kill it. */
02519       p->confno = -1;
02520    }
02521 
02522    return 0;
02523 }
02524 
02525 static int check_for_conference(struct dahdi_pvt *p);
02526 
02527 static int my_check_for_conference(void *pvt)
02528 {
02529    struct dahdi_pvt *p = pvt;
02530    return check_for_conference(p);
02531 }
02532 
02533 static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a,  enum analog_sub b, struct ast_channel *ast_b)
02534 {
02535    struct dahdi_pvt *p = pvt;
02536    int da, db;
02537    int tchan;
02538    int tinthreeway;
02539 
02540    da = analogsub_to_dahdisub(a);
02541    db = analogsub_to_dahdisub(b);
02542 
02543    tchan = p->subs[da].chan;
02544    p->subs[da].chan = p->subs[db].chan;
02545    p->subs[db].chan = tchan;
02546 
02547    tinthreeway = p->subs[da].inthreeway;
02548    p->subs[da].inthreeway = p->subs[db].inthreeway;
02549    p->subs[db].inthreeway = tinthreeway;
02550 
02551    p->subs[da].owner = ast_a;
02552    p->subs[db].owner = ast_b;
02553 
02554    if (ast_a)
02555       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02556    if (ast_b)
02557       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02558 
02559    wakeup_sub(p, a);
02560    wakeup_sub(p, b);
02561 
02562    return;
02563 }
02564 
02565 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02566 
02567 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02568 {
02569    struct dahdi_pvt *p = pvt;
02570    int dsub = analogsub_to_dahdisub(sub);
02571 
02572    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "");
02573 }
02574 
02575 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02576 static int dahdi_setlaw(int dfd, int law)
02577 {
02578    int res;
02579    res = ioctl(dfd, DAHDI_SETLAW, &law);
02580    if (res)
02581       return res;
02582    return 0;
02583 }
02584 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02585 
02586 #if defined(HAVE_PRI)
02587 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
02588 {
02589    struct dahdi_pvt *p = pvt;
02590    int audio;
02591    int newlaw = -1;
02592 
02593    switch (p->sig) {
02594    case SIG_PRI_LIB_HANDLE_CASES:
02595       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02596          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02597          break;
02598       }
02599       /* Fall through */
02600    default:
02601       /* Set to audio mode at this point */
02602       audio = 1;
02603       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02604          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02605             p->channel, audio, strerror(errno));
02606       }
02607       break;
02608    }
02609 
02610    if (law != SIG_PRI_DEFLAW) {
02611       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02612    }
02613 
02614    ast_copy_string(p->exten, exten, sizeof(p->exten));
02615 
02616    switch (law) {
02617       case SIG_PRI_DEFLAW:
02618          newlaw = 0;
02619          break;
02620       case SIG_PRI_ALAW:
02621          newlaw = DAHDI_LAW_ALAW;
02622          break;
02623       case SIG_PRI_ULAW:
02624          newlaw = DAHDI_LAW_MULAW;
02625          break;
02626    }
02627    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
02628 }
02629 #endif   /* defined(HAVE_PRI) */
02630 
02631 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02632 
02633 #if defined(HAVE_PRI)
02634 /*!
02635  * \internal
02636  * \brief Open the PRI channel media path.
02637  * \since 1.8
02638  *
02639  * \param p Channel private control structure.
02640  *
02641  * \return Nothing
02642  */
02643 static void my_pri_open_media(void *p)
02644 {
02645    struct dahdi_pvt *pvt = p;
02646    int res;
02647    int dfd;
02648    int set_val;
02649 
02650    dfd = pvt->subs[SUB_REAL].dfd;
02651 
02652    /* Open the media path. */
02653    set_val = 1;
02654    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02655    if (res < 0) {
02656       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02657          pvt->channel, strerror(errno));
02658    }
02659 
02660    /* Set correct companding law for this call. */
02661    res = dahdi_setlaw(dfd, pvt->law);
02662    if (res < 0) {
02663       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02664    }
02665 
02666    /* Set correct gain for this call. */
02667    if (pvt->digital) {
02668       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02669    } else {
02670       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02671          pvt->law);
02672    }
02673    if (res < 0) {
02674       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02675    }
02676 
02677    if (pvt->dsp_features && pvt->dsp) {
02678       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02679       pvt->dsp_features = 0;
02680    }
02681 }
02682 #endif   /* defined(HAVE_PRI) */
02683 
02684 #if defined(HAVE_PRI)
02685 /*!
02686  * \internal
02687  * \brief Ask DAHDI to dial the given dial string.
02688  * \since 1.8.11
02689  *
02690  * \param p Channel private control structure.
02691  * \param dial_string String to pass to DAHDI to dial.
02692  *
02693  * \note The channel private lock needs to be held when calling.
02694  *
02695  * \return Nothing
02696  */
02697 static void my_pri_dial_digits(void *p, const char *dial_string)
02698 {
02699    struct dahdi_dialoperation zo = {
02700       .op = DAHDI_DIAL_OP_APPEND,
02701    };
02702    struct dahdi_pvt *pvt = p;
02703    int res;
02704 
02705    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02706    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02707    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02708    if (res) {
02709       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02710          pvt->channel, dial_string, strerror(errno));
02711    } else {
02712       pvt->dialing = 1;
02713    }
02714 }
02715 #endif   /* defined(HAVE_PRI) */
02716 
02717 static int unalloc_sub(struct dahdi_pvt *p, int x);
02718 
02719 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02720 {
02721    struct dahdi_pvt *p = pvt;
02722 
02723    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02724 }
02725 
02726 static int alloc_sub(struct dahdi_pvt *p, int x);
02727 
02728 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02729 {
02730    struct dahdi_pvt *p = pvt;
02731 
02732    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02733 }
02734 
02735 static int has_voicemail(struct dahdi_pvt *p);
02736 
02737 static int my_has_voicemail(void *pvt)
02738 {
02739    struct dahdi_pvt *p = pvt;
02740 
02741    return has_voicemail(p);
02742 }
02743 
02744 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02745 {
02746    struct dahdi_pvt *p = pvt;
02747    int index;
02748 
02749    index = analogsub_to_dahdisub(sub);
02750 
02751    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02752 }
02753 
02754 static enum analog_event dahdievent_to_analogevent(int event)
02755 {
02756    enum analog_event res;
02757 
02758    switch (event) {
02759    case DAHDI_EVENT_ONHOOK:
02760       res = ANALOG_EVENT_ONHOOK;
02761       break;
02762    case DAHDI_EVENT_RINGOFFHOOK:
02763       res = ANALOG_EVENT_RINGOFFHOOK;
02764       break;
02765    case DAHDI_EVENT_WINKFLASH:
02766       res = ANALOG_EVENT_WINKFLASH;
02767       break;
02768    case DAHDI_EVENT_ALARM:
02769       res = ANALOG_EVENT_ALARM;
02770       break;
02771    case DAHDI_EVENT_NOALARM:
02772       res = ANALOG_EVENT_NOALARM;
02773       break;
02774    case DAHDI_EVENT_DIALCOMPLETE:
02775       res = ANALOG_EVENT_DIALCOMPLETE;
02776       break;
02777    case DAHDI_EVENT_RINGERON:
02778       res = ANALOG_EVENT_RINGERON;
02779       break;
02780    case DAHDI_EVENT_RINGEROFF:
02781       res = ANALOG_EVENT_RINGEROFF;
02782       break;
02783    case DAHDI_EVENT_HOOKCOMPLETE:
02784       res = ANALOG_EVENT_HOOKCOMPLETE;
02785       break;
02786    case DAHDI_EVENT_PULSE_START:
02787       res = ANALOG_EVENT_PULSE_START;
02788       break;
02789    case DAHDI_EVENT_POLARITY:
02790       res = ANALOG_EVENT_POLARITY;
02791       break;
02792    case DAHDI_EVENT_RINGBEGIN:
02793       res = ANALOG_EVENT_RINGBEGIN;
02794       break;
02795    case DAHDI_EVENT_EC_DISABLED:
02796       res = ANALOG_EVENT_EC_DISABLED;
02797       break;
02798    case DAHDI_EVENT_REMOVED:
02799       res = ANALOG_EVENT_REMOVED;
02800       break;
02801    case DAHDI_EVENT_NEONMWI_ACTIVE:
02802       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02803       break;
02804    case DAHDI_EVENT_NEONMWI_INACTIVE:
02805       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02806       break;
02807 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02808    case DAHDI_EVENT_TX_CED_DETECTED:
02809       res = ANALOG_EVENT_TX_CED_DETECTED;
02810       break;
02811    case DAHDI_EVENT_RX_CED_DETECTED:
02812       res = ANALOG_EVENT_RX_CED_DETECTED;
02813       break;
02814    case DAHDI_EVENT_EC_NLP_DISABLED:
02815       res = ANALOG_EVENT_EC_NLP_DISABLED;
02816       break;
02817    case DAHDI_EVENT_EC_NLP_ENABLED:
02818       res = ANALOG_EVENT_EC_NLP_ENABLED;
02819       break;
02820 #endif
02821    case DAHDI_EVENT_PULSEDIGIT:
02822       res = ANALOG_EVENT_PULSEDIGIT;
02823       break;
02824    case DAHDI_EVENT_DTMFDOWN:
02825       res = ANALOG_EVENT_DTMFDOWN;
02826       break;
02827    case DAHDI_EVENT_DTMFUP:
02828       res = ANALOG_EVENT_DTMFUP;
02829       break;
02830    default:
02831       switch(event & 0xFFFF0000) {
02832       case DAHDI_EVENT_PULSEDIGIT:
02833       case DAHDI_EVENT_DTMFDOWN:
02834       case DAHDI_EVENT_DTMFUP:
02835          /* The event includes a digit number in the low word.
02836           * Converting it to a 'enum analog_event' would remove
02837           * that information. Thus it is returned as-is.
02838           */
02839          return event;
02840       }
02841 
02842       res = ANALOG_EVENT_ERROR;
02843       break;
02844    }
02845 
02846    return res;
02847 }
02848 
02849 static inline int dahdi_wait_event(int fd);
02850 
02851 static int my_wait_event(void *pvt)
02852 {
02853    struct dahdi_pvt *p = pvt;
02854 
02855    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02856 }
02857 
02858 static int my_get_event(void *pvt)
02859 {
02860    struct dahdi_pvt *p = pvt;
02861    int res;
02862 
02863    if (p->fake_event) {
02864       res = p->fake_event;
02865       p->fake_event = 0;
02866    } else
02867       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02868 
02869    return dahdievent_to_analogevent(res);
02870 }
02871 
02872 static int my_is_off_hook(void *pvt)
02873 {
02874    struct dahdi_pvt *p = pvt;
02875    int res;
02876    struct dahdi_params par;
02877 
02878    memset(&par, 0, sizeof(par));
02879 
02880    if (p->subs[SUB_REAL].dfd > -1)
02881       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02882    else {
02883       /* Assume not off hook on CVRS */
02884       res = 0;
02885       par.rxisoffhook = 0;
02886    }
02887    if (res) {
02888       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02889    }
02890 
02891    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02892       /* When "onhook" that means no battery on the line, and thus
02893       it is out of service..., if it's on a TDM card... If it's a channel
02894       bank, there is no telling... */
02895       return (par.rxbits > -1) || par.rxisoffhook;
02896    }
02897 
02898    return par.rxisoffhook;
02899 }
02900 
02901 static void dahdi_enable_ec(struct dahdi_pvt *p);
02902 static void dahdi_disable_ec(struct dahdi_pvt *p);
02903 
02904 static int my_set_echocanceller(void *pvt, int enable)
02905 {
02906    struct dahdi_pvt *p = pvt;
02907 
02908    if (enable)
02909       dahdi_enable_ec(p);
02910    else
02911       dahdi_disable_ec(p);
02912 
02913    return 0;
02914 }
02915 
02916 static int dahdi_ring_phone(struct dahdi_pvt *p);
02917 
02918 static int my_ring(void *pvt)
02919 {
02920    struct dahdi_pvt *p = pvt;
02921 
02922    return dahdi_ring_phone(p);
02923 }
02924 
02925 static int my_flash(void *pvt)
02926 {
02927    struct dahdi_pvt *p = pvt;
02928    int func = DAHDI_FLASH;
02929    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02930 }
02931 
02932 static inline int dahdi_set_hook(int fd, int hs);
02933 
02934 static int my_off_hook(void *pvt)
02935 {
02936    struct dahdi_pvt *p = pvt;
02937    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02938 }
02939 
02940 static void my_set_needringing(void *pvt, int value)
02941 {
02942    struct dahdi_pvt *p = pvt;
02943    p->subs[SUB_REAL].needringing = value;
02944 }
02945 
02946 static void my_set_polarity(void *pvt, int value)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    if (p->channel == CHAN_PSEUDO) {
02951       return;
02952    }
02953    p->polarity = value;
02954    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02955 }
02956 
02957 static void my_start_polarityswitch(void *pvt)
02958 {
02959    struct dahdi_pvt *p = pvt;
02960 
02961    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02962       my_set_polarity(pvt, 0);
02963    }
02964 }
02965 
02966 static void my_answer_polarityswitch(void *pvt)
02967 {
02968    struct dahdi_pvt *p = pvt;
02969 
02970    if (!p->answeronpolarityswitch) {
02971       return;
02972    }
02973 
02974    my_set_polarity(pvt, 1);
02975 }
02976 
02977 static void my_hangup_polarityswitch(void *pvt)
02978 {
02979    struct dahdi_pvt *p = pvt;
02980 
02981    if (!p->hanguponpolarityswitch) {
02982       return;
02983    }
02984 
02985    if (p->answeronpolarityswitch) {
02986       my_set_polarity(pvt, 0);
02987    } else {
02988       my_set_polarity(pvt, 1);
02989    }
02990 }
02991 
02992 static int my_start(void *pvt)
02993 {
02994    struct dahdi_pvt *p = pvt;
02995    int x = DAHDI_START;
02996 
02997    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02998 }
02999 
03000 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03001 {
03002    int index = analogsub_to_dahdisub(sub);
03003    int res;
03004    struct dahdi_pvt *p = pvt;
03005    struct dahdi_dialoperation ddop;
03006 
03007    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03008       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03009       return -1;
03010    }
03011 
03012    if (sub != ANALOG_SUB_REAL) {
03013       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03014          dop->dialstr, p->channel, sub);
03015       return -1;
03016    }
03017 
03018    ddop.op = DAHDI_DIAL_OP_REPLACE;
03019    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03020 
03021    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03022 
03023    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03024    if (res == -1) {
03025       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03026    }
03027 
03028    return res;
03029 }
03030 
03031 static void dahdi_train_ec(struct dahdi_pvt *p);
03032 
03033 static int my_train_echocanceller(void *pvt)
03034 {
03035    struct dahdi_pvt *p = pvt;
03036 
03037    dahdi_train_ec(p);
03038 
03039    return 0;
03040 }
03041 
03042 static int my_is_dialing(void *pvt, enum analog_sub sub)
03043 {
03044    struct dahdi_pvt *p = pvt;
03045    int index;
03046    int x;
03047 
03048    index = analogsub_to_dahdisub(sub);
03049 
03050    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03051       ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03052       return -1;
03053    }
03054 
03055    return x;
03056 }
03057 
03058 static int my_on_hook(void *pvt)
03059 {
03060    struct dahdi_pvt *p = pvt;
03061    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03062 }
03063 
03064 #if defined(HAVE_PRI)
03065 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03066 {
03067    struct dahdi_pvt *old_chan = chan_old;
03068    struct dahdi_pvt *new_chan = chan_new;
03069 
03070    new_chan->owner = old_chan->owner;
03071    old_chan->owner = NULL;
03072    if (new_chan->owner) {
03073       new_chan->owner->tech_pvt = new_chan;
03074       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03075       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03076       old_chan->subs[SUB_REAL].owner = NULL;
03077    }
03078    /* Copy any DSP that may be present */
03079    new_chan->dsp = old_chan->dsp;
03080    new_chan->dsp_features = old_chan->dsp_features;
03081    old_chan->dsp = NULL;
03082    old_chan->dsp_features = 0;
03083 
03084    /* Transfer flags from the old channel. */
03085    new_chan->dialing = old_chan->dialing;
03086    new_chan->digital = old_chan->digital;
03087    new_chan->outgoing = old_chan->outgoing;
03088    old_chan->dialing = 0;
03089    old_chan->digital = 0;
03090    old_chan->outgoing = 0;
03091 
03092    /* More stuff to transfer to the new channel. */
03093    new_chan->law = old_chan->law;
03094    strcpy(new_chan->dialstring, old_chan->dialstring);
03095 }
03096 #endif   /* defined(HAVE_PRI) */
03097 
03098 #if defined(HAVE_PRI)
03099 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03100 {
03101    switch (tone) {
03102    case SIG_PRI_TONE_RINGTONE:
03103       return DAHDI_TONE_RINGTONE;
03104    case SIG_PRI_TONE_STUTTER:
03105       return DAHDI_TONE_STUTTER;
03106    case SIG_PRI_TONE_CONGESTION:
03107       return DAHDI_TONE_CONGESTION;
03108    case SIG_PRI_TONE_DIALTONE:
03109       return DAHDI_TONE_DIALTONE;
03110    case SIG_PRI_TONE_DIALRECALL:
03111       return DAHDI_TONE_DIALRECALL;
03112    case SIG_PRI_TONE_INFO:
03113       return DAHDI_TONE_INFO;
03114    case SIG_PRI_TONE_BUSY:
03115       return DAHDI_TONE_BUSY;
03116    default:
03117       return -1;
03118    }
03119 }
03120 #endif   /* defined(HAVE_PRI) */
03121 
03122 #if defined(HAVE_PRI)
03123 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03124 {
03125    int x;
03126 
03127    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03128    if (x) {
03129       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03130    }
03131    /* Keep track of alarm state */
03132    switch (x) {
03133    case DAHDI_EVENT_ALARM:
03134       pri_event_alarm(pri, index, 0);
03135       break;
03136    case DAHDI_EVENT_NOALARM:
03137       pri_event_noalarm(pri, index, 0);
03138       break;
03139    default:
03140       break;
03141    }
03142 }
03143 #endif   /* defined(HAVE_PRI) */
03144 
03145 #if defined(HAVE_PRI)
03146 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03147 {
03148    struct dahdi_pvt *p = pvt;
03149 
03150    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03151 }
03152 #endif   /* defined(HAVE_PRI) */
03153 
03154 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03155 /*!
03156  * \internal
03157  * \brief Set the caller id information.
03158  * \since 1.8
03159  *
03160  * \param pvt DAHDI private structure
03161  * \param caller Caller-id information to set.
03162  *
03163  * \return Nothing
03164  */
03165 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03166 {
03167    struct dahdi_pvt *p = pvt;
03168 
03169    ast_copy_string(p->cid_num,
03170       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03171       sizeof(p->cid_num));
03172    ast_copy_string(p->cid_name,
03173       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03174       sizeof(p->cid_name));
03175    ast_copy_string(p->cid_subaddr,
03176       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03177       sizeof(p->cid_subaddr));
03178    p->cid_ton = caller->id.number.plan;
03179    p->callingpres = ast_party_id_presentation(&caller->id);
03180    if (caller->id.tag) {
03181       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03182    }
03183    ast_copy_string(p->cid_ani,
03184       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03185       sizeof(p->cid_ani));
03186    p->cid_ani2 = caller->ani2;
03187 }
03188 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03189 
03190 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03191 /*!
03192  * \internal
03193  * \brief Set the Dialed Number Identifier.
03194  * \since 1.8
03195  *
03196  * \param pvt DAHDI private structure
03197  * \param dnid Dialed Number Identifier string.
03198  *
03199  * \return Nothing
03200  */
03201 static void my_set_dnid(void *pvt, const char *dnid)
03202 {
03203    struct dahdi_pvt *p = pvt;
03204 
03205    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03206 }
03207 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03208 
03209 #if defined(HAVE_PRI)
03210 /*!
03211  * \internal
03212  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03213  * \since 1.8
03214  *
03215  * \param pvt DAHDI private structure
03216  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03217  *
03218  * \return Nothing
03219  */
03220 static void my_set_rdnis(void *pvt, const char *rdnis)
03221 {
03222    struct dahdi_pvt *p = pvt;
03223 
03224    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03225 }
03226 #endif   /* defined(HAVE_PRI) */
03227 
03228 #if defined(HAVE_PRI)
03229 /*!
03230  * \internal
03231  * \brief Make a dialstring for native ISDN CC to recall properly.
03232  * \since 1.8
03233  *
03234  * \param priv Channel private control structure.
03235  * \param buf Where to put the modified dialstring.
03236  * \param buf_size Size of modified dialstring buffer.
03237  *
03238  * \details
03239  * original dialstring:
03240  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03241  *
03242  * The modified dialstring will have prefixed the channel-group section
03243  * with the ISDN channel restriction.
03244  *
03245  * buf:
03246  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03247  *
03248  * The routine will check to see if the ISDN channel restriction is already
03249  * in the original dialstring.
03250  *
03251  * \return Nothing
03252  */
03253 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03254 {
03255    char *dial;
03256    struct dahdi_pvt *pvt;
03257    AST_DECLARE_APP_ARGS(args,
03258       AST_APP_ARG(tech);   /* channel technology token */
03259       AST_APP_ARG(group);  /* channel/group token */
03260       //AST_APP_ARG(ext);  /* extension token */
03261       //AST_APP_ARG(opts); /* options token */
03262       //AST_APP_ARG(other);   /* Any remining unused arguments */
03263    );
03264 
03265    pvt = priv;
03266    dial = ast_strdupa(pvt->dialstring);
03267    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03268    if (!args.tech) {
03269       ast_copy_string(buf, pvt->dialstring, buf_size);
03270       return;
03271    }
03272    if (!args.group) {
03273       /* Append the ISDN span channel restriction to the dialstring. */
03274       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03275       return;
03276    }
03277    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03278       /* The ISDN span channel restriction is not needed or already
03279        * in the dialstring. */
03280       ast_copy_string(buf, pvt->dialstring, buf_size);
03281       return;
03282    }
03283    /* Insert the ISDN span channel restriction into the dialstring. */
03284    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03285 }
03286 #endif   /* defined(HAVE_PRI) */
03287 
03288 #if defined(HAVE_PRI)
03289 /*!
03290  * \internal
03291  * \brief Reevaluate the PRI span device state.
03292  * \since 1.8
03293  *
03294  * \param pri Asterisk D channel control structure.
03295  *
03296  * \return Nothing
03297  *
03298  * \note Assumes the pri->lock is already obtained.
03299  */
03300 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03301 {
03302    unsigned idx;
03303    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03304    unsigned in_use;     /* Number of B channels in use on the span. */
03305    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03306    enum ast_device_state new_state;
03307 
03308    /* Count the number of B channels and the number of B channels in use. */
03309    num_b_chans = 0;
03310    in_use = 0;
03311    in_alarm = 1;
03312    for (idx = pri->numchans; idx--;) {
03313       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03314          /* This is a B channel interface. */
03315          ++num_b_chans;
03316          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03317             ++in_use;
03318          }
03319          if (!pri->pvts[idx]->inalarm) {
03320             /* There is a channel that is not in alarm. */
03321             in_alarm = 0;
03322          }
03323       }
03324    }
03325 
03326    /* Update the span congestion device state and report any change. */
03327    if (in_alarm) {
03328       new_state = AST_DEVICE_UNAVAILABLE;
03329    } else {
03330       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03331    }
03332    if (pri->congestion_devstate != new_state) {
03333       pri->congestion_devstate = new_state;
03334       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03335    }
03336 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03337    /* Update the span threshold device state and report any change. */
03338    if (in_alarm) {
03339       new_state = AST_DEVICE_UNAVAILABLE;
03340    } else if (!in_use) {
03341       new_state = AST_DEVICE_NOT_INUSE;
03342    } else if (!pri->user_busy_threshold) {
03343       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03344    } else {
03345       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03346          : AST_DEVICE_BUSY;
03347    }
03348    if (pri->threshold_devstate != new_state) {
03349       pri->threshold_devstate = new_state;
03350       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03351    }
03352 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03353 }
03354 #endif   /* defined(HAVE_PRI) */
03355 
03356 #if defined(HAVE_PRI)
03357 /*!
03358  * \internal
03359  * \brief Reference this module.
03360  * \since 1.8
03361  *
03362  * \return Nothing
03363  */
03364 static void my_module_ref(void)
03365 {
03366    ast_module_ref(ast_module_info->self);
03367 }
03368 #endif   /* defined(HAVE_PRI) */
03369 
03370 #if defined(HAVE_PRI)
03371 /*!
03372  * \internal
03373  * \brief Unreference this module.
03374  * \since 1.8
03375  *
03376  * \return Nothing
03377  */
03378 static void my_module_unref(void)
03379 {
03380    ast_module_unref(ast_module_info->self);
03381 }
03382 #endif   /* defined(HAVE_PRI) */
03383 
03384 #if defined(HAVE_PRI)
03385 #if defined(HAVE_PRI_CALL_WAITING)
03386 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03387 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03388 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03389 
03390 static struct sig_pri_callback dahdi_pri_callbacks =
03391 {
03392    .handle_dchan_exception = my_handle_dchan_exception,
03393    .play_tone = my_pri_play_tone,
03394    .set_echocanceller = my_set_echocanceller,
03395    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03396    .lock_private = my_lock_private,
03397    .unlock_private = my_unlock_private,
03398    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03399    .new_ast_channel = my_new_pri_ast_channel,
03400    .fixup_chans = my_pri_fixup_chans,
03401    .set_alarm = my_set_alarm,
03402    .set_dialing = my_set_dialing,
03403    .set_digital = my_set_digital,
03404    .set_callerid = my_set_callerid,
03405    .set_dnid = my_set_dnid,
03406    .set_rdnis = my_set_rdnis,
03407    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03408 #if defined(HAVE_PRI_CALL_WAITING)
03409    .init_config = my_pri_init_config,
03410 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03411    .get_orig_dialstring = my_get_orig_dialstring,
03412    .make_cc_dialstring = my_pri_make_cc_dialstring,
03413    .update_span_devstate = dahdi_pri_update_span_devstate,
03414    .module_ref = my_module_ref,
03415    .module_unref = my_module_unref,
03416    .dial_digits = my_pri_dial_digits,
03417    .open_media = my_pri_open_media,
03418    .ami_channel_event = my_ami_channel_event,
03419 };
03420 #endif   /* defined(HAVE_PRI) */
03421 
03422 #if defined(HAVE_SS7)
03423 /*!
03424  * \internal
03425  * \brief Handle the SS7 link exception.
03426  * \since 1.8
03427  *
03428  * \param linkset Controlling linkset for the channel.
03429  * \param which Link index of the signaling channel.
03430  *
03431  * \return Nothing
03432  */
03433 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03434 {
03435    int event;
03436 
03437    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03438       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03439          linkset->span, which);
03440       return;
03441    }
03442    switch (event) {
03443    case DAHDI_EVENT_NONE:
03444       break;
03445    case DAHDI_EVENT_ALARM:
03446       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03447          event2str(event), event, linkset->span, which);
03448       sig_ss7_link_alarm(linkset, which);
03449       break;
03450    case DAHDI_EVENT_NOALARM:
03451       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03452          event2str(event), event, linkset->span, which);
03453       sig_ss7_link_noalarm(linkset, which);
03454       break;
03455    default:
03456       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03457          event2str(event), event, linkset->span, which);
03458       break;
03459    }
03460 }
03461 #endif   /* defined(HAVE_SS7) */
03462 
03463 #if defined(HAVE_SS7)
03464 static void my_ss7_set_loopback(void *pvt, int enable)
03465 {
03466    struct dahdi_pvt *p = pvt;
03467 
03468    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03469       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03470          strerror(errno));
03471    }
03472 }
03473 #endif   /* defined(HAVE_SS7) */
03474 
03475 #if defined(HAVE_SS7)
03476 /*!
03477  * \internal
03478  * \brief Create a new asterisk channel structure for SS7.
03479  * \since 1.8
03480  *
03481  * \param pvt Private channel structure.
03482  * \param state Initial state of new channel.
03483  * \param law Combanding law to use.
03484  * \param exten Dialplan extension for incoming call.
03485  * \param requestor Channel requesting this new channel.
03486  *
03487  * \retval ast_channel on success.
03488  * \retval NULL on error.
03489  */
03490 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
03491 {
03492    struct dahdi_pvt *p = pvt;
03493    int audio;
03494    int newlaw;
03495 
03496    /* Set to audio mode at this point */
03497    audio = 1;
03498    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03499       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03500          p->channel, audio, strerror(errno));
03501 
03502    if (law != SIG_SS7_DEFLAW) {
03503       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03504          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03505    }
03506 
03507    ast_copy_string(p->exten, exten, sizeof(p->exten));
03508 
03509    newlaw = -1;
03510    switch (law) {
03511    case SIG_SS7_DEFLAW:
03512       newlaw = 0;
03513       break;
03514    case SIG_SS7_ALAW:
03515       newlaw = DAHDI_LAW_ALAW;
03516       break;
03517    case SIG_SS7_ULAW:
03518       newlaw = DAHDI_LAW_MULAW;
03519       break;
03520    }
03521    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
03522 }
03523 #endif   /* defined(HAVE_SS7) */
03524 
03525 #if defined(HAVE_SS7)
03526 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03527 {
03528    switch (tone) {
03529    case SIG_SS7_TONE_RINGTONE:
03530       return DAHDI_TONE_RINGTONE;
03531    case SIG_SS7_TONE_STUTTER:
03532       return DAHDI_TONE_STUTTER;
03533    case SIG_SS7_TONE_CONGESTION:
03534       return DAHDI_TONE_CONGESTION;
03535    case SIG_SS7_TONE_DIALTONE:
03536       return DAHDI_TONE_DIALTONE;
03537    case SIG_SS7_TONE_DIALRECALL:
03538       return DAHDI_TONE_DIALRECALL;
03539    case SIG_SS7_TONE_INFO:
03540       return DAHDI_TONE_INFO;
03541    case SIG_SS7_TONE_BUSY:
03542       return DAHDI_TONE_BUSY;
03543    default:
03544       return -1;
03545    }
03546 }
03547 #endif   /* defined(HAVE_SS7) */
03548 
03549 #if defined(HAVE_SS7)
03550 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03551 {
03552    struct dahdi_pvt *p = pvt;
03553 
03554    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03555 }
03556 #endif   /* defined(HAVE_SS7) */
03557 
03558 #if defined(HAVE_SS7)
03559 static struct sig_ss7_callback dahdi_ss7_callbacks =
03560 {
03561    .lock_private = my_lock_private,
03562    .unlock_private = my_unlock_private,
03563    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03564 
03565    .set_echocanceller = my_set_echocanceller,
03566    .set_loopback = my_ss7_set_loopback,
03567 
03568    .new_ast_channel = my_new_ss7_ast_channel,
03569    .play_tone = my_ss7_play_tone,
03570 
03571    .handle_link_exception = my_handle_link_exception,
03572    .set_alarm = my_set_alarm,
03573    .set_dialing = my_set_dialing,
03574    .set_digital = my_set_digital,
03575    .set_inservice = my_set_inservice,
03576    .set_locallyblocked = my_set_locallyblocked,
03577    .set_remotelyblocked = my_set_remotelyblocked,
03578    .set_callerid = my_set_callerid,
03579    .set_dnid = my_set_dnid,
03580 };
03581 #endif   /* defined(HAVE_SS7) */
03582 
03583 /*!
03584  * \brief Send MWI state change
03585  *
03586  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03587  *      MWI state has changed on.
03588  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03589  *      whether there are messages waiting or not.
03590  *
03591  *  \return nothing
03592  *
03593  * This function does two things:
03594  *
03595  * 1) It generates an internal Asterisk event notifying any other module that
03596  *    cares about MWI that the state of a mailbox has changed.
03597  *
03598  * 2) It runs the script specified by the mwimonitornotify option to allow
03599  *    some custom handling of the state change.
03600  */
03601 static void notify_message(char *mailbox_full, int thereornot)
03602 {
03603    char s[sizeof(mwimonitornotify) + 80];
03604    struct ast_event *event;
03605    char *mailbox, *context;
03606 
03607    /* Strip off @default */
03608    context = mailbox = ast_strdupa(mailbox_full);
03609    strsep(&context, "@");
03610    if (ast_strlen_zero(context))
03611       context = "default";
03612 
03613    if (!(event = ast_event_new(AST_EVENT_MWI,
03614          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03615          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03616          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03617          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03618          AST_EVENT_IE_END))) {
03619       return;
03620    }
03621 
03622    ast_event_queue_and_cache(event);
03623 
03624    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03625       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03626       ast_safe_system(s);
03627    }
03628 }
03629 
03630 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03631 {
03632    struct dahdi_pvt *p = pvt;
03633 
03634    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03635       return;
03636 
03637    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03638       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03639       notify_message(p->mailbox, 1);
03640    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03641       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03642       notify_message(p->mailbox, 0);
03643    }
03644    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03645    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03646    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03647       ast_hangup(chan);
03648       return;
03649    }
03650 }
03651 
03652 static int my_have_progressdetect(void *pvt)
03653 {
03654    struct dahdi_pvt *p = pvt;
03655 
03656    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03657       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03658       return 1;
03659    } else {
03660       /* Don't have progress detection. */
03661       return 0;
03662    }
03663 }
03664 
03665 static struct analog_callback dahdi_analog_callbacks =
03666 {
03667    .play_tone = my_play_tone,
03668    .get_event = my_get_event,
03669    .wait_event = my_wait_event,
03670    .is_off_hook = my_is_off_hook,
03671    .set_echocanceller = my_set_echocanceller,
03672    .ring = my_ring,
03673    .flash = my_flash,
03674    .off_hook = my_off_hook,
03675    .dial_digits = my_dial_digits,
03676    .train_echocanceller = my_train_echocanceller,
03677    .on_hook = my_on_hook,
03678    .is_dialing = my_is_dialing,
03679    .allocate_sub = my_allocate_sub,
03680    .unallocate_sub = my_unallocate_sub,
03681    .swap_subs = my_swap_subchannels,
03682    .has_voicemail = my_has_voicemail,
03683    .check_for_conference = my_check_for_conference,
03684    .conf_add = my_conf_add,
03685    .conf_del = my_conf_del,
03686    .complete_conference_update = my_complete_conference_update,
03687    .start = my_start,
03688    .all_subchannels_hungup = my_all_subchannels_hungup,
03689    .lock_private = my_lock_private,
03690    .unlock_private = my_unlock_private,
03691    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03692    .handle_dtmf = my_handle_dtmf,
03693    .wink = my_wink,
03694    .new_ast_channel = my_new_analog_ast_channel,
03695    .dsp_set_digitmode = my_dsp_set_digitmode,
03696    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03697    .send_callerid = my_send_callerid,
03698    .callwait = my_callwait,
03699    .stop_callwait = my_stop_callwait,
03700    .get_callerid = my_get_callerid,
03701    .start_cid_detect = my_start_cid_detect,
03702    .stop_cid_detect = my_stop_cid_detect,
03703    .handle_notify_message = my_handle_notify_message,
03704    .increase_ss_count = my_increase_ss_count,
03705    .decrease_ss_count = my_decrease_ss_count,
03706    .distinctive_ring = my_distinctive_ring,
03707    .set_linear_mode = my_set_linear_mode,
03708    .set_inthreeway = my_set_inthreeway,
03709    .get_and_handle_alarms = my_get_and_handle_alarms,
03710    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03711    .get_sub_fd = my_get_sub_fd,
03712    .set_cadence = my_set_cadence,
03713    .set_alarm = my_set_alarm,
03714    .set_dialing = my_set_dialing,
03715    .set_ringtimeout = my_set_ringtimeout,
03716    .set_waitingfordt = my_set_waitingfordt,
03717    .check_waitingfordt = my_check_waitingfordt,
03718    .set_confirmanswer = my_set_confirmanswer,
03719    .check_confirmanswer = my_check_confirmanswer,
03720    .set_callwaiting = my_set_callwaiting,
03721    .cancel_cidspill = my_cancel_cidspill,
03722    .confmute = my_confmute,
03723    .set_pulsedial = my_set_pulsedial,
03724    .set_new_owner = my_set_new_owner,
03725    .get_orig_dialstring = my_get_orig_dialstring,
03726    .set_needringing = my_set_needringing,
03727    .set_polarity = my_set_polarity,
03728    .start_polarityswitch = my_start_polarityswitch,
03729    .answer_polarityswitch = my_answer_polarityswitch,
03730    .hangup_polarityswitch = my_hangup_polarityswitch,
03731    .have_progressdetect = my_have_progressdetect,
03732 };
03733 
03734 /*! Round robin search locations. */
03735 static struct dahdi_pvt *round_robin[32];
03736 
03737 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03738 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03739 {
03740    int res;
03741    if (p->subs[SUB_REAL].owner == ast)
03742       res = 0;
03743    else if (p->subs[SUB_CALLWAIT].owner == ast)
03744       res = 1;
03745    else if (p->subs[SUB_THREEWAY].owner == ast)
03746       res = 2;
03747    else {
03748       res = -1;
03749       if (!nullok)
03750          ast_log(LOG_WARNING,
03751             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03752             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03753    }
03754    return res;
03755 }
03756 
03757 /*!
03758  * \internal
03759  * \brief Obtain the specified subchannel owner lock if the owner exists.
03760  *
03761  * \param pvt Channel private struct.
03762  * \param sub_idx Subchannel owner to lock.
03763  *
03764  * \note Assumes the pvt->lock is already obtained.
03765  *
03766  * \note
03767  * Because deadlock avoidance may have been necessary, you need to confirm
03768  * the state of things before continuing.
03769  *
03770  * \return Nothing
03771  */
03772 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03773 {
03774    for (;;) {
03775       if (!pvt->subs[sub_idx].owner) {
03776          /* No subchannel owner pointer */
03777          break;
03778       }
03779       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03780          /* Got subchannel owner lock */
03781          break;
03782       }
03783       /* We must unlock the private to avoid the possibility of a deadlock */
03784       DEADLOCK_AVOIDANCE(&pvt->lock);
03785    }
03786 }
03787 
03788 static void wakeup_sub(struct dahdi_pvt *p, int a)
03789 {
03790    dahdi_lock_sub_owner(p, a);
03791    if (p->subs[a].owner) {
03792       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03793       ast_channel_unlock(p->subs[a].owner);
03794    }
03795 }
03796 
03797 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03798 {
03799    for (;;) {
03800       if (p->owner) {
03801          if (ast_channel_trylock(p->owner)) {
03802             DEADLOCK_AVOIDANCE(&p->lock);
03803          } else {
03804             ast_queue_frame(p->owner, f);
03805             ast_channel_unlock(p->owner);
03806             break;
03807          }
03808       } else
03809          break;
03810    }
03811 }
03812 
03813 static void handle_clear_alarms(struct dahdi_pvt *p)
03814 {
03815    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03816       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03817       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03818    }
03819    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03820       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03821       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03822    }
03823 }
03824 
03825 #ifdef HAVE_OPENR2
03826 
03827 static int dahdi_r2_answer(struct dahdi_pvt *p)
03828 {
03829    int res = 0;
03830    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03831    * and does not has support for openr2_chan_answer_call_with_mode
03832    *  */
03833 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03834    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03835    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03836    if (!double_answer) {
03837       /* this still can result in double answer if the channel context
03838       * was configured that way */
03839       res = openr2_chan_answer_call(p->r2chan);
03840    } else if (wants_double_answer) {
03841       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03842    } else {
03843       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03844    }
03845 #else
03846    res = openr2_chan_answer_call(p->r2chan);
03847 #endif
03848    return res;
03849 }
03850 
03851 
03852 
03853 /* should be called with the ast_channel locked */
03854 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03855 {
03856    openr2_calling_party_category_t cat;
03857    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03858    struct dahdi_pvt *p = c->tech_pvt;
03859    if (ast_strlen_zero(catstr)) {
03860       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03861             ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03862       return p->mfcr2_category;
03863    }
03864    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03865       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03866             catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03867       return p->mfcr2_category;
03868    }
03869    ast_debug(1, "Using category %s\n", catstr);
03870    return cat;
03871 }
03872 
03873 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03874 {
03875    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03876    ast_mutex_lock(&p->lock);
03877    if (p->mfcr2call) {
03878       ast_mutex_unlock(&p->lock);
03879       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03880          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03881          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03882          the other end will see our seize as a forced release and drop the call, we will see an invalid
03883          pattern that will be seen and treated as protocol error. */
03884       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03885       return;
03886    }
03887    p->mfcr2call = 1;
03888    /* better safe than sorry ... */
03889    p->cid_name[0] = '\0';
03890    p->cid_num[0] = '\0';
03891    p->cid_subaddr[0] = '\0';
03892    p->rdnis[0] = '\0';
03893    p->exten[0] = '\0';
03894    p->mfcr2_ani_index = '\0';
03895    p->mfcr2_dnis_index = '\0';
03896    p->mfcr2_dnis_matched = 0;
03897    p->mfcr2_answer_pending = 0;
03898    p->mfcr2_call_accepted = 0;
03899    ast_mutex_unlock(&p->lock);
03900    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03901 }
03902 
03903 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03904 {
03905    int res;
03906    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03907    ast_mutex_lock(&p->lock);
03908    p->inalarm = alarm ? 1 : 0;
03909    if (p->inalarm) {
03910       res = get_alarms(p);
03911       handle_alarms(p, res);
03912    } else {
03913       handle_clear_alarms(p);
03914    }
03915    ast_mutex_unlock(&p->lock);
03916 }
03917 
03918 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03919 {
03920    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03921 }
03922 
03923 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03924 {
03925    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03926    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03927    if (p->owner) {
03928       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03929       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03930    }
03931    ast_mutex_lock(&p->lock);
03932    p->mfcr2call = 0;
03933    ast_mutex_unlock(&p->lock);
03934 }
03935 
03936 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03937 {
03938    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03939       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03940          p->channel, openr2_proto_get_disconnect_string(cause));
03941       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03942       openr2_chan_set_idle(p->r2chan);
03943       ast_mutex_lock(&p->lock);
03944       p->mfcr2call = 0;
03945       ast_mutex_unlock(&p->lock);
03946    }
03947 }
03948 
03949 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03950 {
03951    struct dahdi_pvt *p;
03952    struct ast_channel *c;
03953    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03954          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03955          openr2_proto_get_category_string(category));
03956    p = openr2_chan_get_client_data(r2chan);
03957    /* if collect calls are not allowed and this is a collect call, reject it! */
03958    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03959       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03960       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03961       return;
03962    }
03963    ast_mutex_lock(&p->lock);
03964    p->mfcr2_recvd_category = category;
03965    /* if we're not supposed to use CID, clear whatever we have */
03966    if (!p->use_callerid) {
03967       ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
03968       p->cid_num[0] = 0;
03969       p->cid_name[0] = 0;
03970    }
03971    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03972    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03973       ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
03974       p->exten[0] = 's';
03975       p->exten[1] = 0;
03976    }
03977    ast_mutex_unlock(&p->lock);
03978    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03979       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03980             p->channel, p->exten, p->context);
03981       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03982       return;
03983    }
03984    if (!p->mfcr2_accept_on_offer) {
03985       /* The user wants us to start the PBX thread right away without accepting the call first */
03986       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03987       if (c) {
03988          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03989             the call or reject it and detect the tone off condition of the other end, all of this
03990             will be done in the PBX thread now */
03991          return;
03992       }
03993       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03994       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03995    } else if (p->mfcr2_charge_calls) {
03996       ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03997       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03998    } else {
03999       ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04000       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04001    }
04002 }
04003 
04004 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04005 {
04006    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04007    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04008    ast_mutex_lock(&p->lock);
04009    p->mfcr2call = 0;
04010    ast_mutex_unlock(&p->lock);
04011 }
04012 
04013 static void dahdi_enable_ec(struct dahdi_pvt *p);
04014 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04015 {
04016    struct dahdi_pvt *p = NULL;
04017    struct ast_channel *c = NULL;
04018    p = openr2_chan_get_client_data(r2chan);
04019    dahdi_enable_ec(p);
04020    p->mfcr2_call_accepted = 1;
04021    /* if it's an incoming call ... */
04022    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04023       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04024       /* If accept on offer is not set, it means at this point the PBX thread is already
04025          launched (was launched in the 'on call offered' handler) and therefore this callback
04026          is being executed already in the PBX thread rather than the monitor thread, don't launch
04027          any other thread, just disable the openr2 reading and answer the call if needed */
04028       if (!p->mfcr2_accept_on_offer) {
04029          openr2_chan_disable_read(r2chan);
04030          if (p->mfcr2_answer_pending) {
04031             ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04032             dahdi_r2_answer(p);
04033          }
04034          return;
04035       }
04036       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04037       if (c) {
04038          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04039             library to forget about it */
04040          openr2_chan_disable_read(r2chan);
04041          return;
04042       }
04043       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04044       /* failed to create the channel, bail out and report it as an out of order line */
04045       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04046       return;
04047    }
04048    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04049    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04050    p->subs[SUB_REAL].needringing = 1;
04051    p->dialing = 0;
04052    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04053    openr2_chan_disable_read(r2chan);
04054 }
04055 
04056 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04057 {
04058    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04059    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04060    p->subs[SUB_REAL].needanswer = 1;
04061 }
04062 
04063 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04064 {
04065    /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04066 }
04067 
04068 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04069 {
04070    switch (cause) {
04071    case OR2_CAUSE_BUSY_NUMBER:
04072       return AST_CAUSE_BUSY;
04073    case OR2_CAUSE_NETWORK_CONGESTION:
04074       return AST_CAUSE_CONGESTION;
04075    case OR2_CAUSE_OUT_OF_ORDER:
04076       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04077    case OR2_CAUSE_UNALLOCATED_NUMBER:
04078       return AST_CAUSE_UNREGISTERED;
04079    case OR2_CAUSE_NO_ANSWER:
04080       return AST_CAUSE_NO_ANSWER;
04081    case OR2_CAUSE_NORMAL_CLEARING:
04082       return AST_CAUSE_NORMAL_CLEARING;
04083    case OR2_CAUSE_UNSPECIFIED:
04084    default:
04085       return AST_CAUSE_NOTDEFINED;
04086    }
04087 }
04088 
04089 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04090 {
04091    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04092    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04093    ast_mutex_lock(&p->lock);
04094    if (!p->owner) {
04095       ast_mutex_unlock(&p->lock);
04096       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04097       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04098       return;
04099    }
04100    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04101       be done in dahdi_hangup */
04102    if (p->owner->_state == AST_STATE_UP) {
04103       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04104       ast_mutex_unlock(&p->lock);
04105    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04106       /* being the forward side we must report what happened to the call to whoever requested it */
04107       switch (cause) {
04108       case OR2_CAUSE_BUSY_NUMBER:
04109          p->subs[SUB_REAL].needbusy = 1;
04110          break;
04111       case OR2_CAUSE_NETWORK_CONGESTION:
04112       case OR2_CAUSE_OUT_OF_ORDER:
04113       case OR2_CAUSE_UNALLOCATED_NUMBER:
04114       case OR2_CAUSE_NO_ANSWER:
04115       case OR2_CAUSE_UNSPECIFIED:
04116       case OR2_CAUSE_NORMAL_CLEARING:
04117          p->subs[SUB_REAL].needcongestion = 1;
04118          break;
04119       default:
04120          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04121       }
04122       ast_mutex_unlock(&p->lock);
04123    } else {
04124       ast_mutex_unlock(&p->lock);
04125       /* being the backward side and not UP yet, we only need to request hangup */
04126       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04127       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04128    }
04129 }
04130 
04131 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04132 {
04133    switch (level) {
04134    case OR2_LOG_NOTICE:
04135       ast_verbose("%s", logmessage);
04136       break;
04137    case OR2_LOG_WARNING:
04138       ast_log(LOG_WARNING, "%s", logmessage);
04139       break;
04140    case OR2_LOG_ERROR:
04141       ast_log(LOG_ERROR, "%s", logmessage);
04142       break;
04143    case OR2_LOG_STACK_TRACE:
04144    case OR2_LOG_MF_TRACE:
04145    case OR2_LOG_CAS_TRACE:
04146    case OR2_LOG_DEBUG:
04147    case OR2_LOG_EX_DEBUG:
04148       ast_debug(1, "%s", logmessage);
04149       break;
04150    default:
04151       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04152       ast_debug(1, "%s", logmessage);
04153       break;
04154    }
04155 }
04156 
04157 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04158 {
04159    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04160    ast_mutex_lock(&p->lock);
04161    p->remotelyblocked = 1;
04162    ast_mutex_unlock(&p->lock);
04163    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04164 }
04165 
04166 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04167 {
04168    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04169    ast_mutex_lock(&p->lock);
04170    p->remotelyblocked = 0;
04171    ast_mutex_unlock(&p->lock);
04172    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04173 }
04174 
04175 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04176    __attribute__((format (printf, 3, 0)));
04177 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04178 {
04179 #define CONTEXT_TAG "Context - "
04180    char logmsg[256];
04181    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04182    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04183    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04184    dahdi_r2_write_log(level, completemsg);
04185 #undef CONTEXT_TAG
04186 }
04187 
04188 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04189    __attribute__((format (printf, 3, 0)));
04190 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04191 {
04192 #define CHAN_TAG "Chan "
04193    char logmsg[256];
04194    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04195    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04196    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04197    dahdi_r2_write_log(level, completemsg);
04198 }
04199 
04200 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04201 {
04202    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04203    /* if 'immediate' is set, let's stop requesting DNIS */
04204    if (p->immediate) {
04205       return 0;
04206    }
04207    p->exten[p->mfcr2_dnis_index] = digit;
04208    p->rdnis[p->mfcr2_dnis_index] = digit;
04209    p->mfcr2_dnis_index++;
04210    p->exten[p->mfcr2_dnis_index] = 0;
04211    p->rdnis[p->mfcr2_dnis_index] = 0;
04212    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04213    if ((p->mfcr2_dnis_matched ||
04214        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04215        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04216       return 0;
04217    }
04218    /* otherwise keep going */
04219    return 1;
04220 }
04221 
04222 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04223 {
04224    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04225    p->cid_num[p->mfcr2_ani_index] = digit;
04226    p->cid_name[p->mfcr2_ani_index] = digit;
04227    p->mfcr2_ani_index++;
04228    p->cid_num[p->mfcr2_ani_index] = 0;
04229    p->cid_name[p->mfcr2_ani_index] = 0;
04230 }
04231 
04232 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04233 {
04234    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04235 }
04236 
04237 static openr2_event_interface_t dahdi_r2_event_iface = {
04238    .on_call_init = dahdi_r2_on_call_init,
04239    .on_call_offered = dahdi_r2_on_call_offered,
04240    .on_call_accepted = dahdi_r2_on_call_accepted,
04241    .on_call_answered = dahdi_r2_on_call_answered,
04242    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04243    .on_call_end = dahdi_r2_on_call_end,
04244    .on_call_read = dahdi_r2_on_call_read,
04245    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04246    .on_os_error = dahdi_r2_on_os_error,
04247    .on_protocol_error = dahdi_r2_on_protocol_error,
04248    .on_line_blocked = dahdi_r2_on_line_blocked,
04249    .on_line_idle = dahdi_r2_on_line_idle,
04250    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04251    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04252    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04253    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04254    /* so far we do nothing with billing pulses */
04255    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04256 };
04257 
04258 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04259 {
04260    return AST_ALAW(sample);
04261 }
04262 
04263 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04264 {
04265    return AST_LIN2A(sample);
04266 }
04267 
04268 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04269    dahdi_r2_alaw_to_linear,
04270    dahdi_r2_linear_to_alaw
04271 };
04272 
04273 #endif /* HAVE_OPENR2 */
04274 
04275 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04276 {
04277    int tchan;
04278    int tinthreeway;
04279    struct ast_channel *towner;
04280 
04281    ast_debug(1, "Swapping %d and %d\n", a, b);
04282 
04283    tchan = p->subs[a].chan;
04284    towner = p->subs[a].owner;
04285    tinthreeway = p->subs[a].inthreeway;
04286 
04287    p->subs[a].chan = p->subs[b].chan;
04288    p->subs[a].owner = p->subs[b].owner;
04289    p->subs[a].inthreeway = p->subs[b].inthreeway;
04290 
04291    p->subs[b].chan = tchan;
04292    p->subs[b].owner = towner;
04293    p->subs[b].inthreeway = tinthreeway;
04294 
04295    if (p->subs[a].owner)
04296       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04297    if (p->subs[b].owner)
04298       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04299    wakeup_sub(p, a);
04300    wakeup_sub(p, b);
04301 }
04302 
04303 static int dahdi_open(char *fn)
04304 {
04305    int fd;
04306    int isnum;
04307    int chan = 0;
04308    int bs;
04309    int x;
04310    isnum = 1;
04311    for (x = 0; x < strlen(fn); x++) {
04312       if (!isdigit(fn[x])) {
04313          isnum = 0;
04314          break;
04315       }
04316    }
04317    if (isnum) {
04318       chan = atoi(fn);
04319       if (chan < 1) {
04320          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04321          return -1;
04322       }
04323       fn = "/dev/dahdi/channel";
04324    }
04325    fd = open(fn, O_RDWR | O_NONBLOCK);
04326    if (fd < 0) {
04327       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04328       return -1;
04329    }
04330    if (chan) {
04331       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04332          x = errno;
04333          close(fd);
04334          errno = x;
04335          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04336          return -1;
04337       }
04338    }
04339    bs = READ_SIZE;
04340    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04341       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04342       x = errno;
04343       close(fd);
04344       errno = x;
04345       return -1;
04346    }
04347    return fd;
04348 }
04349 
04350 static void dahdi_close(int fd)
04351 {
04352    if (fd > 0)
04353       close(fd);
04354 }
04355 
04356 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04357 {
04358    dahdi_close(chan_pvt->subs[sub_num].dfd);
04359    chan_pvt->subs[sub_num].dfd = -1;
04360 }
04361 
04362 #if defined(HAVE_PRI)
04363 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04364 {
04365    dahdi_close(pri->pri.fds[fd_num]);
04366    pri->pri.fds[fd_num] = -1;
04367 }
04368 #endif   /* defined(HAVE_PRI) */
04369 
04370 #if defined(HAVE_SS7)
04371 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04372 {
04373    dahdi_close(ss7->ss7.fds[fd_num]);
04374    ss7->ss7.fds[fd_num] = -1;
04375 }
04376 #endif   /* defined(HAVE_SS7) */
04377 
04378 static int dahdi_setlinear(int dfd, int linear)
04379 {
04380    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04381 }
04382 
04383 
04384 static int alloc_sub(struct dahdi_pvt *p, int x)
04385 {
04386    struct dahdi_bufferinfo bi;
04387    int res;
04388    if (p->subs[x].dfd >= 0) {
04389       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04390       return -1;
04391    }
04392 
04393    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04394    if (p->subs[x].dfd <= -1) {
04395       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04396       return -1;
04397    }
04398 
04399    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04400    if (!res) {
04401       bi.txbufpolicy = p->buf_policy;
04402       bi.rxbufpolicy = p->buf_policy;
04403       bi.numbufs = p->buf_no;
04404       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04405       if (res < 0) {
04406          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04407       }
04408    } else
04409       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04410 
04411    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04412       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04413       dahdi_close_sub(p, x);
04414       p->subs[x].dfd = -1;
04415       return -1;
04416    }
04417    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04418    return 0;
04419 }
04420 
04421 static int unalloc_sub(struct dahdi_pvt *p, int x)
04422 {
04423    if (!x) {
04424       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04425       return -1;
04426    }
04427    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04428    dahdi_close_sub(p, x);
04429    p->subs[x].linear = 0;
04430    p->subs[x].chan = 0;
04431    p->subs[x].owner = NULL;
04432    p->subs[x].inthreeway = 0;
04433    p->polarity = POLARITY_IDLE;
04434    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04435    return 0;
04436 }
04437 
04438 static int digit_to_dtmfindex(char digit)
04439 {
04440    if (isdigit(digit))
04441       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04442    else if (digit >= 'A' && digit <= 'D')
04443       return DAHDI_TONE_DTMF_A + (digit - 'A');
04444    else if (digit >= 'a' && digit <= 'd')
04445       return DAHDI_TONE_DTMF_A + (digit - 'a');
04446    else if (digit == '*')
04447       return DAHDI_TONE_DTMF_s;
04448    else if (digit == '#')
04449       return DAHDI_TONE_DTMF_p;
04450    else
04451       return -1;
04452 }
04453 
04454 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04455 {
04456    struct dahdi_pvt *pvt;
04457    int idx;
04458    int dtmf = -1;
04459    int res;
04460 
04461    pvt = chan->tech_pvt;
04462 
04463    ast_mutex_lock(&pvt->lock);
04464 
04465    idx = dahdi_get_index(chan, pvt, 0);
04466 
04467    if ((idx != SUB_REAL) || !pvt->owner)
04468       goto out;
04469 
04470 #ifdef HAVE_PRI
04471    switch (pvt->sig) {
04472    case SIG_PRI_LIB_HANDLE_CASES:
04473       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04474       if (!res)
04475          goto out;
04476       break;
04477    default:
04478       break;
04479    }
04480 #endif
04481    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04482       goto out;
04483 
04484    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04485       struct dahdi_dialoperation zo = {
04486          .op = DAHDI_DIAL_OP_APPEND,
04487       };
04488 
04489       zo.dialstr[0] = 'T';
04490       zo.dialstr[1] = digit;
04491       zo.dialstr[2] = '\0';
04492       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04493          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04494       else
04495          pvt->dialing = 1;
04496    } else {
04497       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04498       pvt->dialing = 1;
04499       pvt->begindigit = digit;
04500    }
04501 
04502 out:
04503    ast_mutex_unlock(&pvt->lock);
04504 
04505    return 0;
04506 }
04507 
04508 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04509 {
04510    struct dahdi_pvt *pvt;
04511    int res = 0;
04512    int idx;
04513    int x;
04514 
04515    pvt = chan->tech_pvt;
04516 
04517    ast_mutex_lock(&pvt->lock);
04518 
04519    idx = dahdi_get_index(chan, pvt, 0);
04520 
04521    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04522       goto out;
04523 
04524 #ifdef HAVE_PRI
04525    /* This means that the digit was already sent via PRI signalling */
04526    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04527       goto out;
04528    }
04529 #endif
04530 
04531    if (pvt->begindigit) {
04532       x = -1;
04533       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04534       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04535       pvt->dialing = 0;
04536       pvt->begindigit = 0;
04537    }
04538 
04539 out:
04540    ast_mutex_unlock(&pvt->lock);
04541 
04542    return res;
04543 }
04544 
04545 static const char * const events[] = {
04546    "No event",
04547    "On hook",
04548    "Ring/Answered",
04549    "Wink/Flash",
04550    "Alarm",
04551    "No more alarm",
04552    "HDLC Abort",
04553    "HDLC Overrun",
04554    "HDLC Bad FCS",
04555    "Dial Complete",
04556    "Ringer On",
04557    "Ringer Off",
04558    "Hook Transition Complete",
04559    "Bits Changed",
04560    "Pulse Start",
04561    "Timer Expired",
04562    "Timer Ping",
04563    "Polarity Reversal",
04564    "Ring Begin",
04565 };
04566 
04567 static struct {
04568    int alarm;
04569    char *name;
04570 } alarms[] = {
04571    { DAHDI_ALARM_RED, "Red Alarm" },
04572    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04573    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04574    { DAHDI_ALARM_RECOVER, "Recovering" },
04575    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04576    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04577    { DAHDI_ALARM_NONE, "None" },
04578 };
04579 
04580 static char *alarm2str(int alm)
04581 {
04582    int x;
04583    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04584       if (alarms[x].alarm & alm)
04585          return alarms[x].name;
04586    }
04587    return alm ? "Unknown Alarm" : "No Alarm";
04588 }
04589 
04590 static const char *event2str(int event)
04591 {
04592    static char buf[256];
04593    if ((event < (ARRAY_LEN(events))) && (event > -1))
04594       return events[event];
04595    sprintf(buf, "Event %d", event); /* safe */
04596    return buf;
04597 }
04598 
04599 static char *dahdi_sig2str(int sig)
04600 {
04601    static char buf[256];
04602    switch (sig) {
04603    case SIG_EM:
04604       return "E & M Immediate";
04605    case SIG_EMWINK:
04606       return "E & M Wink";
04607    case SIG_EM_E1:
04608       return "E & M E1";
04609    case SIG_FEATD:
04610       return "Feature Group D (DTMF)";
04611    case SIG_FEATDMF:
04612       return "Feature Group D (MF)";
04613    case SIG_FEATDMF_TA:
04614       return "Feature Groud D (MF) Tandem Access";
04615    case SIG_FEATB:
04616       return "Feature Group B (MF)";
04617    case SIG_E911:
04618       return "E911 (MF)";
04619    case SIG_FGC_CAMA:
04620       return "FGC/CAMA (Dialpulse)";
04621    case SIG_FGC_CAMAMF:
04622       return "FGC/CAMA (MF)";
04623    case SIG_FXSLS:
04624       return "FXS Loopstart";
04625    case SIG_FXSGS:
04626       return "FXS Groundstart";
04627    case SIG_FXSKS:
04628       return "FXS Kewlstart";
04629    case SIG_FXOLS:
04630       return "FXO Loopstart";
04631    case SIG_FXOGS:
04632       return "FXO Groundstart";
04633    case SIG_FXOKS:
04634       return "FXO Kewlstart";
04635    case SIG_PRI:
04636       return "ISDN PRI";
04637    case SIG_BRI:
04638       return "ISDN BRI Point to Point";
04639    case SIG_BRI_PTMP:
04640       return "ISDN BRI Point to MultiPoint";
04641    case SIG_SS7:
04642       return "SS7";
04643    case SIG_MFCR2:
04644       return "MFC/R2";
04645    case SIG_SF:
04646       return "SF (Tone) Immediate";
04647    case SIG_SFWINK:
04648       return "SF (Tone) Wink";
04649    case SIG_SF_FEATD:
04650       return "SF (Tone) with Feature Group D (DTMF)";
04651    case SIG_SF_FEATDMF:
04652       return "SF (Tone) with Feature Group D (MF)";
04653    case SIG_SF_FEATB:
04654       return "SF (Tone) with Feature Group B (MF)";
04655    case 0:
04656       return "Pseudo";
04657    default:
04658       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04659       return buf;
04660    }
04661 }
04662 
04663 #define sig2str dahdi_sig2str
04664 
04665 static int analog_lib_handles(int signalling, int radio, int oprmode)
04666 {
04667    switch (signalling) {
04668    case SIG_FXOLS:
04669    case SIG_FXOGS:
04670    case SIG_FXOKS:
04671    case SIG_FXSLS:
04672    case SIG_FXSGS:
04673    case SIG_FXSKS:
04674    case SIG_EMWINK:
04675    case SIG_EM:
04676    case SIG_EM_E1:
04677    case SIG_FEATD:
04678    case SIG_FEATDMF:
04679    case SIG_E911:
04680    case SIG_FGC_CAMA:
04681    case SIG_FGC_CAMAMF:
04682    case SIG_FEATB:
04683    case SIG_SFWINK:
04684    case SIG_SF:
04685    case SIG_SF_FEATD:
04686    case SIG_SF_FEATDMF:
04687    case SIG_FEATDMF_TA:
04688    case SIG_SF_FEATB:
04689       break;
04690    default:
04691       /* The rest of the function should cover the remainder of signalling types */
04692       return 0;
04693    }
04694 
04695    if (radio)
04696       return 0;
04697 
04698    if (oprmode)
04699       return 0;
04700 
04701    return 1;
04702 }
04703 
04704 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04705 {
04706    /* If the conference already exists, and we're already in it
04707       don't bother doing anything */
04708    struct dahdi_confinfo zi;
04709 
04710    memset(&zi, 0, sizeof(zi));
04711    zi.chan = 0;
04712 
04713    if (slavechannel > 0) {
04714       /* If we have only one slave, do a digital mon */
04715       zi.confmode = DAHDI_CONF_DIGITALMON;
04716       zi.confno = slavechannel;
04717    } else {
04718       if (!idx) {
04719          /* Real-side and pseudo-side both participate in conference */
04720          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04721             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04722       } else
04723          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04724       zi.confno = p->confno;
04725    }
04726    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04727       return 0;
04728    if (c->dfd < 0)
04729       return 0;
04730    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04731       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04732       return -1;
04733    }
04734    if (slavechannel < 1) {
04735       p->confno = zi.confno;
04736    }
04737    c->curconf = zi;
04738    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04739    return 0;
04740 }
04741 
04742 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04743 {
04744    /* If they're listening to our channel, they're ours */
04745    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04746       return 1;
04747    /* If they're a talker on our (allocated) conference, they're ours */
04748    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04749       return 1;
04750    return 0;
04751 }
04752 
04753 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04754 {
04755    struct dahdi_confinfo zi;
04756    if (/* Can't delete if there's no dfd */
04757       (c->dfd < 0) ||
04758       /* Don't delete from the conference if it's not our conference */
04759       !isourconf(p, c)
04760       /* Don't delete if we don't think it's conferenced at all (implied) */
04761       ) return 0;
04762    memset(&zi, 0, sizeof(zi));
04763    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04764       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04765       return -1;
04766    }
04767    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04768    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04769    return 0;
04770 }
04771 
04772 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04773 {
04774    int x;
04775    int useslavenative;
04776    struct dahdi_pvt *slave = NULL;
04777    /* Start out optimistic */
04778    useslavenative = 1;
04779    /* Update conference state in a stateless fashion */
04780    for (x = 0; x < 3; x++) {
04781       /* Any three-way calling makes slave native mode *definitely* out
04782          of the question */
04783       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04784          useslavenative = 0;
04785    }
04786    /* If we don't have any 3-way calls, check to see if we have
04787       precisely one slave */
04788    if (useslavenative) {
04789       for (x = 0; x < MAX_SLAVES; x++) {
04790          if (p->slaves[x]) {
04791             if (slave) {
04792                /* Whoops already have a slave!  No
04793                   slave native and stop right away */
04794                slave = NULL;
04795                useslavenative = 0;
04796                break;
04797             } else {
04798                /* We have one slave so far */
04799                slave = p->slaves[x];
04800             }
04801          }
04802       }
04803    }
04804    /* If no slave, slave native definitely out */
04805    if (!slave)
04806       useslavenative = 0;
04807    else if (slave->law != p->law) {
04808       useslavenative = 0;
04809       slave = NULL;
04810    }
04811    if (out)
04812       *out = slave;
04813    return useslavenative;
04814 }
04815 
04816 static int reset_conf(struct dahdi_pvt *p)
04817 {
04818    p->confno = -1;
04819    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04820    if (p->subs[SUB_REAL].dfd > -1) {
04821       struct dahdi_confinfo zi;
04822 
04823       memset(&zi, 0, sizeof(zi));
04824       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04825          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04826    }
04827    return 0;
04828 }
04829 
04830 static int update_conf(struct dahdi_pvt *p)
04831 {
04832    int needconf = 0;
04833    int x;
04834    int useslavenative;
04835    struct dahdi_pvt *slave = NULL;
04836 
04837    useslavenative = isslavenative(p, &slave);
04838    /* Start with the obvious, general stuff */
04839    for (x = 0; x < 3; x++) {
04840       /* Look for three way calls */
04841       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04842          conf_add(p, &p->subs[x], x, 0);
04843          needconf++;
04844       } else {
04845          conf_del(p, &p->subs[x], x);
04846       }
04847    }
04848    /* If we have a slave, add him to our conference now. or DAX
04849       if this is slave native */
04850    for (x = 0; x < MAX_SLAVES; x++) {
04851       if (p->slaves[x]) {
04852          if (useslavenative)
04853             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04854          else {
04855             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04856             needconf++;
04857          }
04858       }
04859    }
04860    /* If we're supposed to be in there, do so now */
04861    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04862       if (useslavenative)
04863          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04864       else {
04865          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04866          needconf++;
04867       }
04868    }
04869    /* If we have a master, add ourselves to his conference */
04870    if (p->master) {
04871       if (isslavenative(p->master, NULL)) {
04872          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04873       } else {
04874          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04875       }
04876    }
04877    if (!needconf) {
04878       /* Nobody is left (or should be left) in our conference.
04879          Kill it. */
04880       p->confno = -1;
04881    }
04882    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04883    return 0;
04884 }
04885 
04886 static void dahdi_enable_ec(struct dahdi_pvt *p)
04887 {
04888    int res;
04889    if (!p)
04890       return;
04891    if (p->echocanon) {
04892       ast_debug(1, "Echo cancellation already on\n");
04893       return;
04894    }
04895    if (p->digital) {
04896       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04897       return;
04898    }
04899    if (p->echocancel.head.tap_length) {
04900 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04901       switch (p->sig) {
04902 #if defined(HAVE_PRI)
04903       case SIG_PRI_LIB_HANDLE_CASES:
04904          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04905             /*
04906              * PRI nobch pseudo channel.  Does not need ec anyway.
04907              * Does not handle ioctl(DAHDI_AUDIOMODE)
04908              */
04909             return;
04910          }
04911          /* Fall through */
04912 #endif   /* defined(HAVE_PRI) */
04913 #if defined(HAVE_SS7)
04914       case SIG_SS7:
04915 #endif   /* defined(HAVE_SS7) */
04916          {
04917             int x = 1;
04918 
04919             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04920             if (res)
04921                ast_log(LOG_WARNING,
04922                   "Unable to enable audio mode on channel %d (%s)\n",
04923                   p->channel, strerror(errno));
04924          }
04925          break;
04926       default:
04927          break;
04928       }
04929 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04930       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04931       if (res) {
04932          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04933       } else {
04934          p->echocanon = 1;
04935          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04936       }
04937    } else
04938       ast_debug(1, "No echo cancellation requested\n");
04939 }
04940 
04941 static void dahdi_train_ec(struct dahdi_pvt *p)
04942 {
04943    int x;
04944    int res;
04945 
04946    if (p && p->echocanon && p->echotraining) {
04947       x = p->echotraining;
04948       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04949       if (res)
04950          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04951       else
04952          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04953    } else {
04954       ast_debug(1, "No echo training requested\n");
04955    }
04956 }
04957 
04958 static void dahdi_disable_ec(struct dahdi_pvt *p)
04959 {
04960    int res;
04961 
04962    if (p->echocanon) {
04963       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04964 
04965       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04966 
04967       if (res)
04968          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04969       else
04970          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04971    }
04972 
04973    p->echocanon = 0;
04974 }
04975 
04976 /* perform a dynamic range compression transform on the given sample */
04977 static int drc_sample(int sample, float drc)
04978 {
04979    float neg;
04980    float shallow, steep;
04981    float max = SHRT_MAX;
04982    
04983    neg = (sample < 0 ? -1 : 1);
04984    steep = drc*sample;
04985    shallow = neg*(max-max/drc)+(float)sample/drc;
04986    if (abs(steep) < abs(shallow)) {
04987       sample = steep;
04988    }
04989    else {
04990       sample = shallow;
04991    }
04992 
04993    return sample;
04994 }
04995 
04996 
04997 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04998 {
04999    int j;
05000    int k;
05001 
05002    float linear_gain = pow(10.0, gain / 20.0);
05003 
05004    switch (law) {
05005    case DAHDI_LAW_ALAW:
05006       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05007          if (gain || drc) {
05008             k = AST_ALAW(j);
05009             if (drc) {
05010                k = drc_sample(k, drc);
05011             }
05012             k = (float)k*linear_gain;
05013             if (k > 32767) k = 32767;
05014             if (k < -32767) k = -32767;
05015             g->txgain[j] = AST_LIN2A(k);
05016          } else {
05017             g->txgain[j] = j;
05018          }
05019       }
05020       break;
05021    case DAHDI_LAW_MULAW:
05022       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05023          if (gain || drc) {
05024             k = AST_MULAW(j);
05025             if (drc) {
05026                k = drc_sample(k, drc);
05027             }
05028             k = (float)k*linear_gain;
05029             if (k > 32767) k = 32767;
05030             if (k < -32767) k = -32767;
05031             g->txgain[j] = AST_LIN2MU(k);
05032 
05033          } else {
05034             g->txgain[j] = j;
05035          }
05036       }
05037       break;
05038    }
05039 }
05040 
05041 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05042 {
05043    int j;
05044    int k;
05045    float linear_gain = pow(10.0, gain / 20.0);
05046 
05047    switch (law) {
05048    case DAHDI_LAW_ALAW:
05049       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05050          if (gain || drc) {
05051             k = AST_ALAW(j);
05052             if (drc) {
05053                k = drc_sample(k, drc);
05054             }
05055             k = (float)k*linear_gain;
05056             if (k > 32767) k = 32767;
05057             if (k < -32767) k = -32767;
05058             g->rxgain[j] = AST_LIN2A(k);
05059          } else {
05060             g->rxgain[j] = j;
05061          }
05062       }
05063       break;
05064    case DAHDI_LAW_MULAW:
05065       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05066          if (gain || drc) {
05067             k = AST_MULAW(j);
05068             if (drc) {
05069                k = drc_sample(k, drc);
05070             }
05071             k = (float)k*linear_gain;
05072             if (k > 32767) k = 32767;
05073             if (k < -32767) k = -32767;
05074             g->rxgain[j] = AST_LIN2MU(k);
05075          } else {
05076             g->rxgain[j] = j;
05077          }
05078       }
05079       break;
05080    }
05081 }
05082 
05083 static int set_actual_txgain(int fd, float gain, float drc, int law)
05084 {
05085    struct dahdi_gains g;
05086    int res;
05087 
05088    memset(&g, 0, sizeof(g));
05089    res = ioctl(fd, DAHDI_GETGAINS, &g);
05090    if (res) {
05091       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05092       return res;
05093    }
05094 
05095    fill_txgain(&g, gain, drc, law);
05096 
05097    return ioctl(fd, DAHDI_SETGAINS, &g);
05098 }
05099 
05100 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05101 {
05102    struct dahdi_gains g;
05103    int res;
05104 
05105    memset(&g, 0, sizeof(g));
05106    res = ioctl(fd, DAHDI_GETGAINS, &g);
05107    if (res) {
05108       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05109       return res;
05110    }
05111 
05112    fill_rxgain(&g, gain, drc, law);
05113 
05114    return ioctl(fd, DAHDI_SETGAINS, &g);
05115 }
05116 
05117 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05118 {
05119    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05120 }
05121 
05122 static int bump_gains(struct dahdi_pvt *p)
05123 {
05124    int res;
05125 
05126    /* Bump receive gain by value stored in cid_rxgain */
05127    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05128    if (res) {
05129       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05130       return -1;
05131    }
05132 
05133    return 0;
05134 }
05135 
05136 static int restore_gains(struct dahdi_pvt *p)
05137 {
05138    int res;
05139 
05140    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05141    if (res) {
05142       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05143       return -1;
05144    }
05145 
05146    return 0;
05147 }
05148 
05149 static inline int dahdi_set_hook(int fd, int hs)
05150 {
05151    int x, res;
05152 
05153    x = hs;
05154    res = ioctl(fd, DAHDI_HOOK, &x);
05155 
05156    if (res < 0) {
05157       if (errno == EINPROGRESS)
05158          return 0;
05159       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05160       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05161    }
05162 
05163    return res;
05164 }
05165 
05166 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05167 {
05168    int x, res;
05169 
05170    x = muted;
05171 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05172    switch (p->sig) {
05173 #if defined(HAVE_PRI)
05174    case SIG_PRI_LIB_HANDLE_CASES:
05175       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05176          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05177          break;
05178       }
05179       /* Fall through */
05180 #endif   /* defined(HAVE_PRI) */
05181 #if defined(HAVE_SS7)
05182    case SIG_SS7:
05183 #endif   /* defined(HAVE_SS7) */
05184       {
05185          int y = 1;
05186 
05187          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05188          if (res)
05189             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05190                p->channel, strerror(errno));
05191       }
05192       break;
05193    default:
05194       break;
05195    }
05196 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05197    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05198    if (res < 0)
05199       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05200    return res;
05201 }
05202 
05203 static int save_conference(struct dahdi_pvt *p)
05204 {
05205    struct dahdi_confinfo c;
05206    int res;
05207    if (p->saveconf.confmode) {
05208       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05209       return -1;
05210    }
05211    p->saveconf.chan = 0;
05212    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05213    if (res) {
05214       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05215       p->saveconf.confmode = 0;
05216       return -1;
05217    }
05218    memset(&c, 0, sizeof(c));
05219    c.confmode = DAHDI_CONF_NORMAL;
05220    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05221    if (res) {
05222       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05223       return -1;
05224    }
05225    ast_debug(1, "Disabled conferencing\n");
05226    return 0;
05227 }
05228 
05229 static int restore_conference(struct dahdi_pvt *p)
05230 {
05231    int res;
05232    if (p->saveconf.confmode) {
05233       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05234       p->saveconf.confmode = 0;
05235       if (res) {
05236          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05237          return -1;
05238       }
05239       ast_debug(1, "Restored conferencing\n");
05240    }
05241    return 0;
05242 }
05243 
05244 static int send_cwcidspill(struct dahdi_pvt *p)
05245 {
05246    struct ast_format tmpfmt;
05247 
05248    p->callwaitcas = 0;
05249    p->cidcwexpire = 0;
05250    p->cid_suppress_expire = 0;
05251    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05252       return -1;
05253    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05254    /* Make sure we account for the end */
05255    p->cidlen += READ_SIZE * 4;
05256    p->cidpos = 0;
05257    send_callerid(p);
05258    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05259    return 0;
05260 }
05261 
05262 static int has_voicemail(struct dahdi_pvt *p)
05263 {
05264    int new_msgs;
05265    struct ast_event *event;
05266    char *mailbox, *context;
05267 
05268    mailbox = context = ast_strdupa(p->mailbox);
05269    strsep(&context, "@");
05270    if (ast_strlen_zero(context))
05271       context = "default";
05272 
05273    event = ast_event_get_cached(AST_EVENT_MWI,
05274       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05275       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05276       AST_EVENT_IE_END);
05277 
05278    if (event) {
05279       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05280       ast_event_destroy(event);
05281    } else
05282       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05283 
05284    return new_msgs;
05285 }
05286 
05287 
05288 
05289 static int send_callerid(struct dahdi_pvt *p)
05290 {
05291    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05292    int res;
05293    /* Take out of linear mode if necessary */
05294    if (p->subs[SUB_REAL].linear) {
05295       p->subs[SUB_REAL].linear = 0;
05296       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05297    }
05298    while (p->cidpos < p->cidlen) {
05299       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05300       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05301       if (res < 0) {
05302          if (errno == EAGAIN)
05303             return 0;
05304          else {
05305             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05306             return -1;
05307          }
05308       }
05309       if (!res)
05310          return 0;
05311       p->cidpos += res;
05312    }
05313    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05314    ast_free(p->cidspill);
05315    p->cidspill = NULL;
05316    if (p->callwaitcas) {
05317       /* Wait for CID/CW to expire */
05318       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05319       p->cid_suppress_expire = p->cidcwexpire;
05320    } else
05321       restore_conference(p);
05322    return 0;
05323 }
05324 
05325 static int dahdi_callwait(struct ast_channel *ast)
05326 {
05327    struct dahdi_pvt *p = ast->tech_pvt;
05328    struct ast_format tmpfmt;
05329    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05330    if (p->cidspill) {
05331       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05332       ast_free(p->cidspill);
05333    }
05334 
05335    /*
05336     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05337     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05338     */
05339    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05340       return -1;
05341    save_conference(p);
05342    /* Silence */
05343    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05344    if (!p->callwaitrings && p->callwaitingcallerid) {
05345       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05346       p->callwaitcas = 1;
05347       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05348    } else {
05349       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05350       p->callwaitcas = 0;
05351       p->cidlen = 2400 + READ_SIZE * 4;
05352    }
05353    p->cidpos = 0;
05354    send_callerid(p);
05355 
05356    return 0;
05357 }
05358 
05359 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05360 {
05361    struct dahdi_pvt *p = ast->tech_pvt;
05362    int x, res, mysig;
05363    char *dest;
05364    AST_DECLARE_APP_ARGS(args,
05365       AST_APP_ARG(group);  /* channel/group token */
05366       AST_APP_ARG(ext); /* extension token */
05367       //AST_APP_ARG(opts); /* options token */
05368       AST_APP_ARG(other);  /* Any remining unused arguments */
05369    );
05370 
05371    ast_mutex_lock(&p->lock);
05372    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05373 
05374    /* Split the dialstring */
05375    dest = ast_strdupa(rdest);
05376    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05377    if (!args.ext) {
05378       args.ext = "";
05379    }
05380 
05381 #if defined(HAVE_PRI)
05382    if (dahdi_sig_pri_lib_handles(p->sig)) {
05383       char *subaddr;
05384 
05385       sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05386 
05387       /* Remove any subaddress for uniformity with incoming calls. */
05388       subaddr = strchr(p->exten, ':');
05389       if (subaddr) {
05390          *subaddr = '\0';
05391       }
05392    } else
05393 #endif   /* defined(HAVE_PRI) */
05394    {
05395       ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05396    }
05397 
05398    if ((ast->_state == AST_STATE_BUSY)) {
05399       p->subs[SUB_REAL].needbusy = 1;
05400       ast_mutex_unlock(&p->lock);
05401       return 0;
05402    }
05403    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05404       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05405       ast_mutex_unlock(&p->lock);
05406       return -1;
05407    }
05408    p->waitingfordt.tv_sec = 0;
05409    p->dialednone = 0;
05410    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05411    {
05412       /* Special pseudo -- automatically up */
05413       ast_setstate(ast, AST_STATE_UP);
05414       ast_mutex_unlock(&p->lock);
05415       return 0;
05416    }
05417    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05418    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05419    if (res)
05420       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05421    p->outgoing = 1;
05422 
05423    if (IS_DIGITAL(ast->transfercapability)){
05424       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05425    } else {
05426       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05427    }  
05428 
05429 #ifdef HAVE_PRI
05430    if (dahdi_sig_pri_lib_handles(p->sig)) {
05431       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05432          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05433       ast_mutex_unlock(&p->lock);
05434       return res;
05435    }
05436 #endif
05437 
05438 #if defined(HAVE_SS7)
05439    if (p->sig == SIG_SS7) {
05440       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05441       ast_mutex_unlock(&p->lock);
05442       return res;
05443    }
05444 #endif   /* defined(HAVE_SS7) */
05445 
05446    /* If this is analog signalling we can exit here */
05447    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05448       p->callwaitrings = 0;
05449       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05450       ast_mutex_unlock(&p->lock);
05451       return res;
05452    }
05453 
05454    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05455    switch (mysig) {
05456    case 0:
05457       /* Special pseudo -- automatically up*/
05458       ast_setstate(ast, AST_STATE_UP);
05459       break;
05460    case SIG_MFCR2:
05461       break;
05462    default:
05463       ast_debug(1, "not yet implemented\n");
05464       ast_mutex_unlock(&p->lock);
05465       return -1;
05466    }
05467 
05468 #ifdef HAVE_OPENR2
05469    if (p->mfcr2) {
05470       openr2_calling_party_category_t chancat;
05471       int callres = 0;
05472       char *c, *l;
05473 
05474       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05475       p->dialdest[0] = '\0';
05476 
05477       c = args.ext;
05478       if (!p->hidecallerid) {
05479          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05480       } else {
05481          l = NULL;
05482       }
05483       if (strlen(c) < p->stripmsd) {
05484          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05485          ast_mutex_unlock(&p->lock);
05486          return -1;
05487       }
05488       p->dialing = 1;
05489       chancat = dahdi_r2_get_channel_category(ast);
05490       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05491       if (-1 == callres) {
05492          ast_mutex_unlock(&p->lock);
05493          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05494          return -1;
05495       }
05496       p->mfcr2_call_accepted = 0;
05497       p->mfcr2_progress_sent = 0;
05498       ast_setstate(ast, AST_STATE_DIALING);
05499    }
05500 #endif /* HAVE_OPENR2 */
05501    ast_mutex_unlock(&p->lock);
05502    return 0;
05503 }
05504 
05505 /*!
05506  * \internal
05507  * \brief Insert the given chan_dahdi interface structure into the interface list.
05508  * \since 1.8
05509  *
05510  * \param pvt chan_dahdi private interface structure to insert.
05511  *
05512  * \details
05513  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05514  * Any duplicates are inserted after the existing entries.
05515  *
05516  * \note The new interface must not already be in the list.
05517  *
05518  * \return Nothing
05519  */
05520 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05521 {
05522    struct dahdi_pvt *cur;
05523 
05524    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05525 
05526    /* Find place in middle of list for the new interface. */
05527    for (cur = iflist; cur; cur = cur->next) {
05528       if (pvt->channel < cur->channel) {
05529          /* New interface goes before the current interface. */
05530          pvt->prev = cur->prev;
05531          pvt->next = cur;
05532          if (cur->prev) {
05533             /* Insert into the middle of the list. */
05534             cur->prev->next = pvt;
05535          } else {
05536             /* Insert at head of list. */
05537             iflist = pvt;
05538          }
05539          cur->prev = pvt;
05540          return;
05541       }
05542    }
05543 
05544    /* New interface goes onto the end of the list */
05545    pvt->prev = ifend;
05546    pvt->next = NULL;
05547    if (ifend) {
05548       ifend->next = pvt;
05549    }
05550    ifend = pvt;
05551    if (!iflist) {
05552       /* List was empty */
05553       iflist = pvt;
05554    }
05555 }
05556 
05557 /*!
05558  * \internal
05559  * \brief Extract the given chan_dahdi interface structure from the interface list.
05560  * \since 1.8
05561  *
05562  * \param pvt chan_dahdi private interface structure to extract.
05563  *
05564  * \note
05565  * The given interface structure can be either in the interface list or a stand alone
05566  * structure that has not been put in the list if the next and prev pointers are NULL.
05567  *
05568  * \return Nothing
05569  */
05570 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05571 {
05572    /* Extract from the forward chain. */
05573    if (pvt->prev) {
05574       pvt->prev->next = pvt->next;
05575    } else if (iflist == pvt) {
05576       /* Node is at the head of the list. */
05577       iflist = pvt->next;
05578    }
05579 
05580    /* Extract from the reverse chain. */
05581    if (pvt->next) {
05582       pvt->next->prev = pvt->prev;
05583    } else if (ifend == pvt) {
05584       /* Node is at the end of the list. */
05585       ifend = pvt->prev;
05586    }
05587 
05588    /* Node is no longer in the list. */
05589    pvt->which_iflist = DAHDI_IFLIST_NONE;
05590    pvt->prev = NULL;
05591    pvt->next = NULL;
05592 }
05593 
05594 #if defined(HAVE_PRI)
05595 /*!
05596  * \internal
05597  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05598  * \since 1.8
05599  *
05600  * \param pri sig_pri span control structure holding no B channel list.
05601  * \param pvt chan_dahdi private interface structure to insert.
05602  *
05603  * \details
05604  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05605  * Any duplicates are inserted after the existing entries.
05606  *
05607  * \note The new interface must not already be in the list.
05608  *
05609  * \return Nothing
05610  */
05611 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05612 {
05613    struct dahdi_pvt *cur;
05614 
05615    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05616 
05617    /* Find place in middle of list for the new interface. */
05618    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05619       if (pvt->channel < cur->channel) {
05620          /* New interface goes before the current interface. */
05621          pvt->prev = cur->prev;
05622          pvt->next = cur;
05623          if (cur->prev) {
05624             /* Insert into the middle of the list. */
05625             cur->prev->next = pvt;
05626          } else {
05627             /* Insert at head of list. */
05628             pri->no_b_chan_iflist = pvt;
05629          }
05630          cur->prev = pvt;
05631          return;
05632       }
05633    }
05634 
05635    /* New interface goes onto the end of the list */
05636    pvt->prev = pri->no_b_chan_end;
05637    pvt->next = NULL;
05638    if (pri->no_b_chan_end) {
05639       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05640    }
05641    pri->no_b_chan_end = pvt;
05642    if (!pri->no_b_chan_iflist) {
05643       /* List was empty */
05644       pri->no_b_chan_iflist = pvt;
05645    }
05646 }
05647 #endif   /* defined(HAVE_PRI) */
05648 
05649 #if defined(HAVE_PRI)
05650 /*!
05651  * \internal
05652  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05653  * \since 1.8
05654  *
05655  * \param pri sig_pri span control structure holding no B channel list.
05656  * \param pvt chan_dahdi private interface structure to extract.
05657  *
05658  * \note
05659  * The given interface structure can be either in the interface list or a stand alone
05660  * structure that has not been put in the list if the next and prev pointers are NULL.
05661  *
05662  * \return Nothing
05663  */
05664 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05665 {
05666    /* Extract from the forward chain. */
05667    if (pvt->prev) {
05668       pvt->prev->next = pvt->next;
05669    } else if (pri->no_b_chan_iflist == pvt) {
05670       /* Node is at the head of the list. */
05671       pri->no_b_chan_iflist = pvt->next;
05672    }
05673 
05674    /* Extract from the reverse chain. */
05675    if (pvt->next) {
05676       pvt->next->prev = pvt->prev;
05677    } else if (pri->no_b_chan_end == pvt) {
05678       /* Node is at the end of the list. */
05679       pri->no_b_chan_end = pvt->prev;
05680    }
05681 
05682    /* Node is no longer in the list. */
05683    pvt->which_iflist = DAHDI_IFLIST_NONE;
05684    pvt->prev = NULL;
05685    pvt->next = NULL;
05686 }
05687 #endif   /* defined(HAVE_PRI) */
05688 
05689 #if defined(HAVE_PRI)
05690 /*!
05691  * \internal
05692  * \brief Unlink the channel interface from the PRI private pointer array.
05693  * \since 1.8
05694  *
05695  * \param pvt chan_dahdi private interface structure to unlink.
05696  *
05697  * \return Nothing
05698  */
05699 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05700 {
05701    unsigned idx;
05702    struct sig_pri_span *pri;
05703 
05704    pri = pvt->pri;
05705    if (!pri) {
05706       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05707       return;
05708    }
05709    ast_mutex_lock(&pri->lock);
05710    for (idx = 0; idx < pri->numchans; ++idx) {
05711       if (pri->pvts[idx] == pvt->sig_pvt) {
05712          pri->pvts[idx] = NULL;
05713          ast_mutex_unlock(&pri->lock);
05714          return;
05715       }
05716    }
05717    ast_mutex_unlock(&pri->lock);
05718 }
05719 #endif   /* defined(HAVE_PRI) */
05720 
05721 #if defined(HAVE_SS7)
05722 /*!
05723  * \internal
05724  * \brief Unlink the channel interface from the SS7 private pointer array.
05725  * \since 1.8
05726  *
05727  * \param pvt chan_dahdi private interface structure to unlink.
05728  *
05729  * \return Nothing
05730  */
05731 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05732 {
05733    unsigned idx;
05734    struct sig_ss7_linkset *ss7;
05735 
05736    ss7 = pvt->ss7;
05737    if (!ss7) {
05738       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05739       return;
05740    }
05741    ast_mutex_lock(&ss7->lock);
05742    for (idx = 0; idx < ss7->numchans; ++idx) {
05743       if (ss7->pvts[idx] == pvt->sig_pvt) {
05744          ss7->pvts[idx] = NULL;
05745          ast_mutex_unlock(&ss7->lock);
05746          return;
05747       }
05748    }
05749    ast_mutex_unlock(&ss7->lock);
05750 }
05751 #endif   /* defined(HAVE_SS7) */
05752 
05753 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05754 {
05755    if (cur->next && cur->next->span == cur->span) {
05756       return cur->next;
05757    } else if (cur->prev && cur->prev->span == cur->span) {
05758       return cur->prev;
05759    }
05760 
05761    return NULL;
05762 }
05763 
05764 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05765 {
05766    struct dahdi_pvt *p = pvt;
05767 
05768    if (p->manages_span_alarms) {
05769       struct dahdi_pvt *next = find_next_iface_in_span(p);
05770       if (next) {
05771          next->manages_span_alarms = 1;
05772       }
05773    }
05774 
05775    /* Remove channel from the list */
05776 #if defined(HAVE_PRI)
05777    dahdi_unlink_pri_pvt(p);
05778 #endif   /* defined(HAVE_PRI) */
05779 #if defined(HAVE_SS7)
05780    dahdi_unlink_ss7_pvt(p);
05781 #endif   /* defined(HAVE_SS7) */
05782    switch (pvt->which_iflist) {
05783    case DAHDI_IFLIST_NONE:
05784       break;
05785    case DAHDI_IFLIST_MAIN:
05786       dahdi_iflist_extract(p);
05787       break;
05788 #if defined(HAVE_PRI)
05789    case DAHDI_IFLIST_NO_B_CHAN:
05790       if (p->pri) {
05791          dahdi_nobch_extract(p->pri, p);
05792       }
05793       break;
05794 #endif   /* defined(HAVE_PRI) */
05795    }
05796 
05797    if (p->sig_pvt) {
05798       if (analog_lib_handles(p->sig, 0, 0)) {
05799          analog_delete(p->sig_pvt);
05800       }
05801       switch (p->sig) {
05802 #if defined(HAVE_PRI)
05803       case SIG_PRI_LIB_HANDLE_CASES:
05804          sig_pri_chan_delete(p->sig_pvt);
05805          break;
05806 #endif   /* defined(HAVE_PRI) */
05807 #if defined(HAVE_SS7)
05808       case SIG_SS7:
05809          sig_ss7_chan_delete(p->sig_pvt);
05810          break;
05811 #endif   /* defined(HAVE_SS7) */
05812       default:
05813          break;
05814       }
05815    }
05816    ast_free(p->cidspill);
05817    if (p->use_smdi)
05818       ast_smdi_interface_unref(p->smdi_iface);
05819    if (p->mwi_event_sub)
05820       ast_event_unsubscribe(p->mwi_event_sub);
05821    if (p->vars) {
05822       ast_variables_destroy(p->vars);
05823    }
05824    if (p->cc_params) {
05825       ast_cc_config_params_destroy(p->cc_params);
05826    }
05827    ast_mutex_destroy(&p->lock);
05828    dahdi_close_sub(p, SUB_REAL);
05829    if (p->owner)
05830       p->owner->tech_pvt = NULL;
05831    ast_free(p);
05832 }
05833 
05834 static void destroy_channel(struct dahdi_pvt *cur, int now)
05835 {
05836    int i;
05837 
05838    if (!now) {
05839       /* Do not destroy the channel now if it is owned by someone. */
05840       if (cur->owner) {
05841          return;
05842       }
05843       for (i = 0; i < 3; i++) {
05844          if (cur->subs[i].owner) {
05845             return;
05846          }
05847       }
05848    }
05849    destroy_dahdi_pvt(cur);
05850 }
05851 
05852 static void destroy_all_channels(void)
05853 {
05854    int chan;
05855 #if defined(HAVE_PRI)
05856    unsigned span;
05857    struct sig_pri_span *pri;
05858 #endif   /* defined(HAVE_PRI) */
05859    struct dahdi_pvt *p;
05860 
05861    while (num_restart_pending) {
05862       usleep(1);
05863    }
05864 
05865    ast_mutex_lock(&iflock);
05866    /* Destroy all the interfaces and free their memory */
05867    while (iflist) {
05868       p = iflist;
05869 
05870       chan = p->channel;
05871 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05872       {
05873          char db_chan_name[20];
05874          char db_answer[5];
05875          char state;
05876          int why = -1;
05877 
05878          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05879          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05880             sscanf(db_answer, "%1c:%30d", &state, &why);
05881          }
05882          if (!why) {
05883             /* SRVST persistence is not required */
05884             ast_db_del(db_chan_name, SRVST_DBKEY);
05885          }
05886       }
05887 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05888       /* Free associated memory */
05889       destroy_dahdi_pvt(p);
05890       ast_verb(3, "Unregistered channel %d\n", chan);
05891    }
05892    ifcount = 0;
05893    ast_mutex_unlock(&iflock);
05894 
05895 #if defined(HAVE_PRI)
05896    /* Destroy all of the no B channel interface lists */
05897    for (span = 0; span < NUM_SPANS; ++span) {
05898       if (!pris[span].dchannels[0]) {
05899          break;
05900       }
05901       pri = &pris[span].pri;
05902       ast_mutex_lock(&pri->lock);
05903       while (pri->no_b_chan_iflist) {
05904          p = pri->no_b_chan_iflist;
05905 
05906          /* Free associated memory */
05907          destroy_dahdi_pvt(p);
05908       }
05909       ast_mutex_unlock(&pri->lock);
05910    }
05911 #endif   /* defined(HAVE_PRI) */
05912 }
05913 
05914 #if defined(HAVE_PRI)
05915 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05916 
05917 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05918 {
05919    /* Data will be our digit string */
05920    struct dahdi_pvt *p;
05921 
05922    if (ast_strlen_zero(digits)) {
05923       ast_debug(1, "No digit string sent to application!\n");
05924       return -1;
05925    }
05926 
05927    p = (struct dahdi_pvt *)chan->tech_pvt;
05928 
05929    if (!p) {
05930       ast_debug(1, "Unable to find technology private\n");
05931       return -1;
05932    }
05933 
05934    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05935 
05936    return 0;
05937 }
05938 #endif   /* defined(HAVE_PRI) */
05939 
05940 #if defined(HAVE_PRI)
05941 #if defined(HAVE_PRI_PROG_W_CAUSE)
05942 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05943 
05944 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05945 {
05946    /* Data will be our digit string */
05947    struct dahdi_pvt *pvt;
05948    char *parse;
05949    int res = -1;
05950    AST_DECLARE_APP_ARGS(args,
05951       AST_APP_ARG(destination);
05952       AST_APP_ARG(original);
05953       AST_APP_ARG(reason);
05954    );
05955 
05956    if (ast_strlen_zero(data)) {
05957       ast_debug(1, "No data sent to application!\n");
05958       return -1;
05959    }
05960    if (chan->tech != &dahdi_tech) {
05961       ast_debug(1, "Only DAHDI technology accepted!\n");
05962       return -1;
05963    }
05964    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05965    if (!pvt) {
05966       ast_debug(1, "Unable to find technology private\n");
05967       return -1;
05968    }
05969    switch (pvt->sig) {
05970    case SIG_PRI_LIB_HANDLE_CASES:
05971       break;
05972    default:
05973       ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
05974          ast_channel_name(chan));
05975       return -1;
05976    }
05977 
05978    parse = ast_strdupa(data);
05979    AST_STANDARD_APP_ARGS(args, parse);
05980 
05981    if (ast_strlen_zero(args.destination)) {
05982       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05983       return -1;
05984    }
05985 
05986    if (ast_strlen_zero(args.original)) {
05987       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05988       args.original = NULL;
05989    }
05990 
05991    if (ast_strlen_zero(args.reason)) {
05992       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05993       args.reason = NULL;
05994    }
05995 
05996    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05997       args.original, args.reason);
05998 
05999    return res;
06000 }
06001 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06002 #endif   /* defined(HAVE_PRI) */
06003 
06004 #if defined(HAVE_OPENR2)
06005 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06006 
06007 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06008 {
06009    /* data is whether to accept with charge or no charge */
06010    openr2_call_mode_t accept_mode;
06011    int res, timeout, maxloops;
06012    struct ast_frame *f;
06013    struct dahdi_pvt *p;
06014    char *parse;
06015    AST_DECLARE_APP_ARGS(args,
06016          AST_APP_ARG(charge);
06017    );
06018 
06019    if (ast_strlen_zero(data)) {
06020       ast_debug(1, "No data sent to application!\n");
06021       return -1;
06022    }
06023 
06024    if (chan->tech != &dahdi_tech) {
06025       ast_debug(1, "Only DAHDI technology accepted!\n");
06026       return -1;
06027    }
06028 
06029    p = (struct dahdi_pvt *)chan->tech_pvt;
06030    if (!p) {
06031       ast_debug(1, "Unable to find technology private!\n");
06032       return -1;
06033    }
06034 
06035    parse = ast_strdupa(data);
06036    AST_STANDARD_APP_ARGS(args, parse);
06037 
06038    if (ast_strlen_zero(args.charge)) {
06039       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06040       return -1;
06041    }
06042 
06043    ast_mutex_lock(&p->lock);
06044    if (!p->mfcr2 || !p->mfcr2call) {
06045       ast_mutex_unlock(&p->lock);
06046       ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06047       return -1;
06048    }
06049 
06050    if (p->mfcr2_call_accepted) {
06051       ast_mutex_unlock(&p->lock);
06052       ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06053       return 0;
06054    }
06055    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06056    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06057       ast_mutex_unlock(&p->lock);
06058       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06059       return -1;
06060    }
06061    ast_mutex_unlock(&p->lock);
06062 
06063    res = 0;
06064    timeout = 100;
06065    maxloops = 50; /* wait up to 5 seconds */
06066    /* we need to read() until the call is accepted */
06067    while (maxloops > 0) {
06068       maxloops--;
06069       if (ast_check_hangup(chan)) {
06070          break;
06071       }
06072       res = ast_waitfor(chan, timeout);
06073       if (res < 0) {
06074          ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06075          res = -1;
06076          break;
06077       }
06078       if (res == 0) {
06079          continue;
06080       }
06081       f = ast_read(chan);
06082       if (!f) {
06083          ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06084          res = -1;
06085          break;
06086       }
06087       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06088          ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06089          ast_frfree(f);
06090          res = -1;
06091          break;
06092       }
06093       ast_frfree(f);
06094       ast_mutex_lock(&p->lock);
06095       if (p->mfcr2_call_accepted) {
06096          ast_mutex_unlock(&p->lock);
06097          ast_debug(1, "Accepted MFC/R2 call!\n");
06098          break;
06099       }
06100       ast_mutex_unlock(&p->lock);
06101    }
06102    if (res == -1) {
06103       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06104    }
06105    return res;
06106 }
06107 
06108 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06109 {
06110    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06111    switch (cause) {
06112    case AST_CAUSE_USER_BUSY:
06113    case AST_CAUSE_CALL_REJECTED:
06114    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06115       r2cause = OR2_CAUSE_BUSY_NUMBER;
06116       break;
06117 
06118    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06119    case AST_CAUSE_SWITCH_CONGESTION:
06120       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06121       break;
06122 
06123    case AST_CAUSE_UNALLOCATED:
06124       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06125       break;
06126 
06127    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06128    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06129       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06130       break;
06131 
06132    case AST_CAUSE_NO_ANSWER:
06133    case AST_CAUSE_NO_USER_RESPONSE:
06134       r2cause = OR2_CAUSE_NO_ANSWER;
06135       break;
06136 
06137    default:
06138       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06139       break;
06140    }
06141    ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06142          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06143    return r2cause;
06144 }
06145 #endif
06146 
06147 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06148 {
06149    if (p->bufferoverrideinuse) {
06150       /* faxbuffers are in use, revert them */
06151       struct dahdi_bufferinfo bi = {
06152          .txbufpolicy = p->buf_policy,
06153          .rxbufpolicy = p->buf_policy,
06154          .bufsize = p->bufsize,
06155          .numbufs = p->buf_no
06156       };
06157       int bpres;
06158 
06159       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06160          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06161       }
06162       p->bufferoverrideinuse = 0;
06163       return bpres;
06164    }
06165 
06166    return -1;
06167 }
06168 
06169 static int dahdi_hangup(struct ast_channel *ast)
06170 {
06171    int res = 0;
06172    int idx,x;
06173    int law;
06174    /*static int restore_gains(struct dahdi_pvt *p);*/
06175    struct dahdi_pvt *p = ast->tech_pvt;
06176    struct dahdi_params par;
06177 
06178    ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06179    if (!ast->tech_pvt) {
06180       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06181       return 0;
06182    }
06183 
06184    ast_mutex_lock(&p->lock);
06185    p->exten[0] = '\0';
06186    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06187       dahdi_confmute(p, 0);
06188       restore_gains(p);
06189       p->ignoredtmf = 0;
06190       p->waitingfordt.tv_sec = 0;
06191 
06192       res = analog_hangup(p->sig_pvt, ast);
06193       revert_fax_buffers(p, ast);
06194 
06195       goto hangup_out;
06196    } else {
06197       p->cid_num[0] = '\0';
06198       p->cid_name[0] = '\0';
06199       p->cid_subaddr[0] = '\0';
06200    }
06201 
06202 #if defined(HAVE_PRI)
06203    if (dahdi_sig_pri_lib_handles(p->sig)) {
06204       x = 1;
06205       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06206 
06207       dahdi_confmute(p, 0);
06208       p->muting = 0;
06209       restore_gains(p);
06210       if (p->dsp) {
06211          ast_dsp_free(p->dsp);
06212          p->dsp = NULL;
06213       }
06214       p->ignoredtmf = 0;
06215 
06216       /* Real channel, do some fixup */
06217       p->subs[SUB_REAL].owner = NULL;
06218       p->subs[SUB_REAL].needbusy = 0;
06219       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06220 
06221       p->owner = NULL;
06222       p->cid_tag[0] = '\0';
06223       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06224       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06225       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06226       p->outgoing = 0;
06227       p->digital = 0;
06228       p->faxhandled = 0;
06229       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06230 
06231       revert_fax_buffers(p, ast);
06232 
06233       p->law = p->law_default;
06234       law = p->law_default;
06235       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06236       if (res < 0) {
06237          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06238             p->channel, strerror(errno));
06239       }
06240 
06241       sig_pri_hangup(p->sig_pvt, ast);
06242 
06243       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06244       dahdi_disable_ec(p);
06245 
06246       x = 0;
06247       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06248       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06249 
06250       p->rdnis[0] = '\0';
06251       update_conf(p);
06252       reset_conf(p);
06253 
06254       /* Restore data mode */
06255       x = 0;
06256       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06257 
06258       if (num_restart_pending == 0) {
06259          restart_monitor();
06260       }
06261       goto hangup_out;
06262    }
06263 #endif   /* defined(HAVE_PRI) */
06264 
06265 #if defined(HAVE_SS7)
06266    if (p->sig == SIG_SS7) {
06267       x = 1;
06268       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06269 
06270       dahdi_confmute(p, 0);
06271       p->muting = 0;
06272       restore_gains(p);
06273       if (p->dsp) {
06274          ast_dsp_free(p->dsp);
06275          p->dsp = NULL;
06276       }
06277       p->ignoredtmf = 0;
06278 
06279       /* Real channel, do some fixup */
06280       p->subs[SUB_REAL].owner = NULL;
06281       p->subs[SUB_REAL].needbusy = 0;
06282       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06283 
06284       p->owner = NULL;
06285       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06286       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06287       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06288       p->outgoing = 0;
06289       p->digital = 0;
06290       p->faxhandled = 0;
06291       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06292 
06293       revert_fax_buffers(p, ast);
06294 
06295       p->law = p->law_default;
06296       law = p->law_default;
06297       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06298       if (res < 0) {
06299          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06300             p->channel, strerror(errno));
06301       }
06302 
06303       sig_ss7_hangup(p->sig_pvt, ast);
06304 
06305       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06306       dahdi_disable_ec(p);
06307 
06308       x = 0;
06309       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06310       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06311 
06312       update_conf(p);
06313       reset_conf(p);
06314 
06315       /* Restore data mode */
06316       x = 0;
06317       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06318 
06319       if (num_restart_pending == 0) {
06320          restart_monitor();
06321       }
06322       goto hangup_out;
06323    }
06324 #endif   /* defined(HAVE_SS7) */
06325 
06326    idx = dahdi_get_index(ast, p, 1);
06327 
06328    dahdi_confmute(p, 0);
06329    p->muting = 0;
06330    restore_gains(p);
06331    if (p->origcid_num) {
06332       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06333       ast_free(p->origcid_num);
06334       p->origcid_num = NULL;
06335    }
06336    if (p->origcid_name) {
06337       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06338       ast_free(p->origcid_name);
06339       p->origcid_name = NULL;
06340    }
06341    if (p->dsp)
06342       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06343 
06344    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06345       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06346    p->ignoredtmf = 0;
06347 
06348    if (idx > -1) {
06349       /* Real channel, do some fixup */
06350       p->subs[idx].owner = NULL;
06351       p->subs[idx].needanswer = 0;
06352       p->subs[idx].needflash = 0;
06353       p->subs[idx].needringing = 0;
06354       p->subs[idx].needbusy = 0;
06355       p->subs[idx].needcongestion = 0;
06356       p->subs[idx].linear = 0;
06357       p->polarity = POLARITY_IDLE;
06358       dahdi_setlinear(p->subs[idx].dfd, 0);
06359       if (idx == SUB_REAL) {
06360          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06361             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06362             if (p->subs[SUB_CALLWAIT].inthreeway) {
06363                /* We had flipped over to answer a callwait and now it's gone */
06364                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06365                /* Move to the call-wait, but un-own us until they flip back. */
06366                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06367                unalloc_sub(p, SUB_CALLWAIT);
06368                p->owner = NULL;
06369             } else {
06370                /* The three way hung up, but we still have a call wait */
06371                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06372                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06373                unalloc_sub(p, SUB_THREEWAY);
06374                if (p->subs[SUB_REAL].inthreeway) {
06375                   /* This was part of a three way call.  Immediately make way for
06376                      another call */
06377                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06378                   p->owner = p->subs[SUB_REAL].owner;
06379                } else {
06380                   /* This call hasn't been completed yet...  Set owner to NULL */
06381                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06382                   p->owner = NULL;
06383                }
06384                p->subs[SUB_REAL].inthreeway = 0;
06385             }
06386          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06387             /* Move to the call-wait and switch back to them. */
06388             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06389             unalloc_sub(p, SUB_CALLWAIT);
06390             p->owner = p->subs[SUB_REAL].owner;
06391             if (p->owner->_state != AST_STATE_UP)
06392                p->subs[SUB_REAL].needanswer = 1;
06393             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06394                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06395          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06396             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06397             unalloc_sub(p, SUB_THREEWAY);
06398             if (p->subs[SUB_REAL].inthreeway) {
06399                /* This was part of a three way call.  Immediately make way for
06400                   another call */
06401                ast_debug(1, "Call was complete, setting owner to former third call\n");
06402                p->owner = p->subs[SUB_REAL].owner;
06403             } else {
06404                /* This call hasn't been completed yet...  Set owner to NULL */
06405                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06406                p->owner = NULL;
06407             }
06408             p->subs[SUB_REAL].inthreeway = 0;
06409          }
06410       } else if (idx == SUB_CALLWAIT) {
06411          /* Ditch the holding callwait call, and immediately make it availabe */
06412          if (p->subs[SUB_CALLWAIT].inthreeway) {
06413             /* This is actually part of a three way, placed on hold.  Place the third part
06414                on music on hold now */
06415             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06416                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06417                   S_OR(p->mohsuggest, NULL),
06418                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06419             }
06420             p->subs[SUB_THREEWAY].inthreeway = 0;
06421             /* Make it the call wait now */
06422             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06423             unalloc_sub(p, SUB_THREEWAY);
06424          } else
06425             unalloc_sub(p, SUB_CALLWAIT);
06426       } else if (idx == SUB_THREEWAY) {
06427          if (p->subs[SUB_CALLWAIT].inthreeway) {
06428             /* The other party of the three way call is currently in a call-wait state.
06429                Start music on hold for them, and take the main guy out of the third call */
06430             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06431                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06432                   S_OR(p->mohsuggest, NULL),
06433                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06434             }
06435             p->subs[SUB_CALLWAIT].inthreeway = 0;
06436          }
06437          p->subs[SUB_REAL].inthreeway = 0;
06438          /* If this was part of a three way call index, let us make
06439             another three way call */
06440          unalloc_sub(p, SUB_THREEWAY);
06441       } else {
06442          /* This wasn't any sort of call, but how are we an index? */
06443          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06444       }
06445    }
06446 
06447    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06448       p->owner = NULL;
06449       p->ringt = 0;
06450       p->distinctivering = 0;
06451       p->confirmanswer = 0;
06452       p->outgoing = 0;
06453       p->digital = 0;
06454       p->faxhandled = 0;
06455       p->pulsedial = 0;
06456       if (p->dsp) {
06457          ast_dsp_free(p->dsp);
06458          p->dsp = NULL;
06459       }
06460 
06461       revert_fax_buffers(p, ast);
06462 
06463       p->law = p->law_default;
06464       law = p->law_default;
06465       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06466       if (res < 0)
06467          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06468       /* Perform low level hangup if no owner left */
06469 #ifdef HAVE_OPENR2
06470       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06471          ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06472          /* If it's an incoming call, check the mfcr2_forced_release setting */
06473          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06474             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06475          } else {
06476             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06477             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06478             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06479                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06480             dahdi_r2_disconnect_call(p, r2cause);
06481          }
06482       } else if (p->mfcr2call) {
06483          ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06484          /* since ast_request() was called but not ast_call() we have not yet dialed
06485          and the openr2 stack will not call on_call_end callback, we need to unset
06486          the mfcr2call flag and bump the monitor count so the monitor thread can take
06487          care of this channel events from now on */
06488          p->mfcr2call = 0;
06489       }
06490 #endif
06491       switch (p->sig) {
06492       case SIG_SS7:
06493       case SIG_MFCR2:
06494       case SIG_PRI_LIB_HANDLE_CASES:
06495       case 0:
06496          break;
06497       default:
06498          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06499          break;
06500       }
06501       if (res < 0) {
06502          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06503       }
06504       switch (p->sig) {
06505       case SIG_FXOGS:
06506       case SIG_FXOLS:
06507       case SIG_FXOKS:
06508          memset(&par, 0, sizeof(par));
06509          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06510          if (!res) {
06511             struct analog_pvt *analog_p = p->sig_pvt;
06512 #if 0
06513             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06514 #endif
06515             /* If they're off hook, try playing congestion */
06516             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06517                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06518             else
06519                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06520             analog_p->fxsoffhookstate = par.rxisoffhook;
06521          }
06522          break;
06523       case SIG_FXSGS:
06524       case SIG_FXSLS:
06525       case SIG_FXSKS:
06526          /* Make sure we're not made available for at least two seconds assuming
06527          we were actually used for an inbound or outbound call. */
06528          if (ast->_state != AST_STATE_RESERVED) {
06529             time(&p->guardtime);
06530             p->guardtime += 2;
06531          }
06532          break;
06533       default:
06534          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06535          break;
06536       }
06537       if (p->sig)
06538          dahdi_disable_ec(p);
06539       x = 0;
06540       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06541       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06542       p->didtdd = 0;
06543       p->callwaitcas = 0;
06544       p->callwaiting = p->permcallwaiting;
06545       p->hidecallerid = p->permhidecallerid;
06546       p->waitingfordt.tv_sec = 0;
06547       p->dialing = 0;
06548       p->rdnis[0] = '\0';
06549       update_conf(p);
06550       reset_conf(p);
06551       /* Restore data mode */
06552       switch (p->sig) {
06553       case SIG_PRI_LIB_HANDLE_CASES:
06554       case SIG_SS7:
06555          x = 0;
06556          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06557          break;
06558       default:
06559          break;
06560       }
06561       if (num_restart_pending == 0)
06562          restart_monitor();
06563    }
06564 
06565    p->callwaitingrepeat = 0;
06566    p->cidcwexpire = 0;
06567    p->cid_suppress_expire = 0;
06568    p->oprmode = 0;
06569 hangup_out:
06570    ast->tech_pvt = NULL;
06571    ast_free(p->cidspill);
06572    p->cidspill = NULL;
06573 
06574    ast_mutex_unlock(&p->lock);
06575    ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06576 
06577    ast_mutex_lock(&iflock);
06578    if (p->restartpending) {
06579       num_restart_pending--;
06580    }
06581 
06582    if (p->destroy) {
06583       destroy_channel(p, 0);
06584    }
06585    ast_mutex_unlock(&iflock);
06586 
06587    ast_module_unref(ast_module_info->self);
06588    return 0;
06589 }
06590 
06591 static int dahdi_answer(struct ast_channel *ast)
06592 {
06593    struct dahdi_pvt *p = ast->tech_pvt;
06594    int res = 0;
06595    int idx;
06596    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06597    ast_mutex_lock(&p->lock);
06598    idx = dahdi_get_index(ast, p, 0);
06599    if (idx < 0)
06600       idx = SUB_REAL;
06601    /* nothing to do if a radio channel */
06602    if ((p->radio || (p->oprmode < 0))) {
06603       ast_mutex_unlock(&p->lock);
06604       return 0;
06605    }
06606 
06607    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06608       res = analog_answer(p->sig_pvt, ast);
06609       ast_mutex_unlock(&p->lock);
06610       return res;
06611    }
06612 
06613    switch (p->sig) {
06614 #if defined(HAVE_PRI)
06615    case SIG_PRI_LIB_HANDLE_CASES:
06616       res = sig_pri_answer(p->sig_pvt, ast);
06617       break;
06618 #endif   /* defined(HAVE_PRI) */
06619 #if defined(HAVE_SS7)
06620    case SIG_SS7:
06621       res = sig_ss7_answer(p->sig_pvt, ast);
06622       break;
06623 #endif   /* defined(HAVE_SS7) */
06624 #ifdef HAVE_OPENR2
06625    case SIG_MFCR2:
06626       if (!p->mfcr2_call_accepted) {
06627          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06628             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06629          p->mfcr2_answer_pending = 1;
06630          if (p->mfcr2_charge_calls) {
06631             ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06632             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06633          } else {
06634             ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06635             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06636          }
06637       } else {
06638          ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06639          dahdi_r2_answer(p);
06640       }
06641       break;
06642 #endif
06643    case 0:
06644       ast_mutex_unlock(&p->lock);
06645       return 0;
06646    default:
06647       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06648       res = -1;
06649       break;
06650    }
06651    ast_mutex_unlock(&p->lock);
06652    return res;
06653 }
06654 
06655 static void disable_dtmf_detect(struct dahdi_pvt *p)
06656 {
06657    int val = 0;
06658 
06659    p->ignoredtmf = 1;
06660 
06661    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06662 
06663    if (!p->hardwaredtmf && p->dsp) {
06664       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06665       ast_dsp_set_features(p->dsp, p->dsp_features);
06666    }
06667 }
06668 
06669 static void enable_dtmf_detect(struct dahdi_pvt *p)
06670 {
06671    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06672 
06673    if (p->channel == CHAN_PSEUDO)
06674       return;
06675 
06676    p->ignoredtmf = 0;
06677 
06678    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06679 
06680    if (!p->hardwaredtmf && p->dsp) {
06681       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06682       ast_dsp_set_features(p->dsp, p->dsp_features);
06683    }
06684 }
06685 
06686 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06687 {
06688    char *cp;
06689    struct dahdi_pvt *p = chan->tech_pvt;
06690 
06691    /* all supported options require data */
06692    if (!p || !data || (*datalen < 1)) {
06693       errno = EINVAL;
06694       return -1;
06695    }
06696 
06697    switch (option) {
06698    case AST_OPTION_DIGIT_DETECT:
06699       cp = (char *) data;
06700       *cp = p->ignoredtmf ? 0 : 1;
06701       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06702       break;
06703    case AST_OPTION_FAX_DETECT:
06704       cp = (char *) data;
06705       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06706       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06707       break;
06708    case AST_OPTION_CC_AGENT_TYPE:
06709 #if defined(HAVE_PRI)
06710 #if defined(HAVE_PRI_CCSS)
06711       if (dahdi_sig_pri_lib_handles(p->sig)) {
06712          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06713          break;
06714       }
06715 #endif   /* defined(HAVE_PRI_CCSS) */
06716 #endif   /* defined(HAVE_PRI) */
06717       return -1;
06718    default:
06719       return -1;
06720    }
06721 
06722    errno = 0;
06723 
06724    return 0;
06725 }
06726 
06727 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06728 {
06729    char *cp;
06730    signed char *scp;
06731    int x;
06732    int idx;
06733    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06734    struct oprmode *oprmode;
06735 
06736 
06737    /* all supported options require data */
06738    if (!p || !data || (datalen < 1)) {
06739       errno = EINVAL;
06740       return -1;
06741    }
06742 
06743    switch (option) {
06744    case AST_OPTION_TXGAIN:
06745       scp = (signed char *) data;
06746       idx = dahdi_get_index(chan, p, 0);
06747       if (idx < 0) {
06748          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06749          return -1;
06750       }
06751       ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06752       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06753    case AST_OPTION_RXGAIN:
06754       scp = (signed char *) data;
06755       idx = dahdi_get_index(chan, p, 0);
06756       if (idx < 0) {
06757          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06758          return -1;
06759       }
06760       ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06761       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06762    case AST_OPTION_TONE_VERIFY:
06763       if (!p->dsp)
06764          break;
06765       cp = (char *) data;
06766       switch (*cp) {
06767       case 1:
06768          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06769          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06770          break;
06771       case 2:
06772          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06773          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06774          break;
06775       default:
06776          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06777          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06778          break;
06779       }
06780       break;
06781    case AST_OPTION_TDD:
06782       /* turn on or off TDD */
06783       cp = (char *) data;
06784       p->mate = 0;
06785       if (!*cp) { /* turn it off */
06786          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06787          if (p->tdd)
06788             tdd_free(p->tdd);
06789          p->tdd = 0;
06790          break;
06791       }
06792       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06793          (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06794       dahdi_disable_ec(p);
06795       /* otherwise, turn it on */
06796       if (!p->didtdd) { /* if havent done it yet */
06797          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06798          unsigned char *buf;
06799          int size, res, fd, len;
06800          struct pollfd fds[1];
06801 
06802          buf = mybuf;
06803          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06804          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06805          len = 40000;
06806          idx = dahdi_get_index(chan, p, 0);
06807          if (idx < 0) {
06808             ast_log(LOG_WARNING, "No index in TDD?\n");
06809             return -1;
06810          }
06811          fd = p->subs[idx].dfd;
06812          while (len) {
06813             if (ast_check_hangup(chan))
06814                return -1;
06815             size = len;
06816             if (size > READ_SIZE)
06817                size = READ_SIZE;
06818             fds[0].fd = fd;
06819             fds[0].events = POLLPRI | POLLOUT;
06820             fds[0].revents = 0;
06821             res = poll(fds, 1, -1);
06822             if (!res) {
06823                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06824                continue;
06825             }
06826             /* if got exception */
06827             if (fds[0].revents & POLLPRI)
06828                return -1;
06829             if (!(fds[0].revents & POLLOUT)) {
06830                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06831                continue;
06832             }
06833             res = write(fd, buf, size);
06834             if (res != size) {
06835                if (res == -1) return -1;
06836                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06837                break;
06838             }
06839             len -= size;
06840             buf += size;
06841          }
06842          p->didtdd = 1; /* set to have done it now */
06843       }
06844       if (*cp == 2) { /* Mate mode */
06845          if (p->tdd)
06846             tdd_free(p->tdd);
06847          p->tdd = 0;
06848          p->mate = 1;
06849          break;
06850       }
06851       if (!p->tdd) { /* if we don't have one yet */
06852          p->tdd = tdd_new(); /* allocate one */
06853       }
06854       break;
06855    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06856       if (!p->dsp)
06857          break;
06858       cp = (char *) data;
06859       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06860          *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
06861       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06862       break;
06863    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06864 #if defined(HAVE_PRI)
06865       if (dahdi_sig_pri_lib_handles(p->sig)
06866          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06867          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06868          break;
06869       }
06870 #endif   /* defined(HAVE_PRI) */
06871 
06872       cp = (char *) data;
06873       if (!*cp) {
06874          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
06875          x = 0;
06876          dahdi_disable_ec(p);
06877       } else {
06878          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
06879          x = 1;
06880       }
06881       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06882          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06883       break;
06884    case AST_OPTION_OPRMODE:  /* Operator services mode */
06885       oprmode = (struct oprmode *) data;
06886       /* We don't support operator mode across technologies */
06887       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06888          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06889                chan->tech->type, oprmode->peer->tech->type);
06890          errno = EINVAL;
06891          return -1;
06892       }
06893       pp = oprmode->peer->tech_pvt;
06894       p->oprmode = pp->oprmode = 0;
06895       /* setup peers */
06896       p->oprpeer = pp;
06897       pp->oprpeer = p;
06898       /* setup modes, if any */
06899       if (oprmode->mode)
06900       {
06901          pp->oprmode = oprmode->mode;
06902          p->oprmode = -oprmode->mode;
06903       }
06904       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06905          oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
06906       break;
06907    case AST_OPTION_ECHOCAN:
06908       cp = (char *) data;
06909       if (*cp) {
06910          ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
06911          dahdi_enable_ec(p);
06912       } else {
06913          ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
06914          dahdi_disable_ec(p);
06915       }
06916       break;
06917    case AST_OPTION_DIGIT_DETECT:
06918       cp = (char *) data;
06919       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06920       if (*cp) {
06921          enable_dtmf_detect(p);
06922       } else {
06923          disable_dtmf_detect(p);
06924       }
06925       break;
06926    case AST_OPTION_FAX_DETECT:
06927       cp = (char *) data;
06928       if (p->dsp) {
06929          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06930          if (*cp) {
06931             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06932          } else {
06933             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06934          }
06935          ast_dsp_set_features(p->dsp, p->dsp_features);
06936       }
06937       break;
06938    default:
06939       return -1;
06940    }
06941    errno = 0;
06942 
06943    return 0;
06944 }
06945 
06946 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06947 {
06948    struct dahdi_pvt *p = chan->tech_pvt;
06949    int res = 0;
06950 
06951    if (!p) {
06952       /* No private structure! */
06953       *buf = '\0';
06954       return -1;
06955    }
06956 
06957    if (!strcasecmp(data, "rxgain")) {
06958       ast_mutex_lock(&p->lock);
06959       snprintf(buf, len, "%f", p->rxgain);
06960       ast_mutex_unlock(&p->lock);
06961    } else if (!strcasecmp(data, "txgain")) {
06962       ast_mutex_lock(&p->lock);
06963       snprintf(buf, len, "%f", p->txgain);
06964       ast_mutex_unlock(&p->lock);
06965    } else if (!strcasecmp(data, "dahdi_channel")) {
06966       ast_mutex_lock(&p->lock);
06967       snprintf(buf, len, "%d", p->channel);
06968       ast_mutex_unlock(&p->lock);
06969    } else if (!strcasecmp(data, "dahdi_span")) {
06970       ast_mutex_lock(&p->lock);
06971       snprintf(buf, len, "%d", p->span);
06972       ast_mutex_unlock(&p->lock);
06973    } else if (!strcasecmp(data, "dahdi_type")) {
06974       ast_mutex_lock(&p->lock);
06975       switch (p->sig) {
06976 #if defined(HAVE_OPENR2)
06977       case SIG_MFCR2:
06978          ast_copy_string(buf, "mfc/r2", len);
06979          break;
06980 #endif   /* defined(HAVE_OPENR2) */
06981 #if defined(HAVE_PRI)
06982       case SIG_PRI_LIB_HANDLE_CASES:
06983          ast_copy_string(buf, "pri", len);
06984          break;
06985 #endif   /* defined(HAVE_PRI) */
06986       case 0:
06987          ast_copy_string(buf, "pseudo", len);
06988          break;
06989 #if defined(HAVE_SS7)
06990       case SIG_SS7:
06991          ast_copy_string(buf, "ss7", len);
06992          break;
06993 #endif   /* defined(HAVE_SS7) */
06994       default:
06995          /* The only thing left is analog ports. */
06996          ast_copy_string(buf, "analog", len);
06997          break;
06998       }
06999       ast_mutex_unlock(&p->lock);
07000 #if defined(HAVE_PRI)
07001 #if defined(HAVE_PRI_REVERSE_CHARGE)
07002    } else if (!strcasecmp(data, "reversecharge")) {
07003       ast_mutex_lock(&p->lock);
07004       switch (p->sig) {
07005       case SIG_PRI_LIB_HANDLE_CASES:
07006          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07007          break;
07008       default:
07009          *buf = '\0';
07010          res = -1;
07011          break;
07012       }
07013       ast_mutex_unlock(&p->lock);
07014 #endif
07015 #if defined(HAVE_PRI_SETUP_KEYPAD)
07016    } else if (!strcasecmp(data, "keypad_digits")) {
07017       ast_mutex_lock(&p->lock);
07018       switch (p->sig) {
07019       case SIG_PRI_LIB_HANDLE_CASES:
07020          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07021             len);
07022          break;
07023       default:
07024          *buf = '\0';
07025          res = -1;
07026          break;
07027       }
07028       ast_mutex_unlock(&p->lock);
07029 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07030    } else if (!strcasecmp(data, "no_media_path")) {
07031       ast_mutex_lock(&p->lock);
07032       switch (p->sig) {
07033       case SIG_PRI_LIB_HANDLE_CASES:
07034          /*
07035           * TRUE if the call is on hold or is call waiting because
07036           * there is no media path available.
07037           */
07038          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07039          break;
07040       default:
07041          *buf = '\0';
07042          res = -1;
07043          break;
07044       }
07045       ast_mutex_unlock(&p->lock);
07046 #endif   /* defined(HAVE_PRI) */
07047    } else {
07048       *buf = '\0';
07049       res = -1;
07050    }
07051 
07052    return res;
07053 }
07054 
07055 
07056 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07057 {
07058    int res;
07059    char policy_str[21] = "";
07060 
07061    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07062       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07063       return 1;
07064    }
07065    if (*num_buffers < 0) {
07066       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07067       return -1;
07068    }
07069    if (!strcasecmp(policy_str, "full")) {
07070       *policy = DAHDI_POLICY_WHEN_FULL;
07071    } else if (!strcasecmp(policy_str, "immediate")) {
07072       *policy = DAHDI_POLICY_IMMEDIATE;
07073 #if defined(HAVE_DAHDI_HALF_FULL)
07074    } else if (!strcasecmp(policy_str, "half")) {
07075       *policy = DAHDI_POLICY_HALF_FULL;
07076 #endif
07077    } else {
07078       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07079       return -1;
07080    }
07081 
07082    return 0;
07083 }
07084 
07085 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07086 {
07087    struct dahdi_pvt *p = chan->tech_pvt;
07088    int res = 0;
07089 
07090    if (!p) {
07091       /* No private structure! */
07092       return -1;
07093    }
07094 
07095    if (!strcasecmp(data, "buffers")) {
07096       int num_bufs, policy;
07097 
07098       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07099          struct dahdi_bufferinfo bi = {
07100             .txbufpolicy = policy,
07101             .rxbufpolicy = policy,
07102             .bufsize = p->bufsize,
07103             .numbufs = num_bufs,
07104          };
07105          int bpres;
07106 
07107          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07108             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07109          } else {
07110             p->bufferoverrideinuse = 1;
07111          }
07112       } else {
07113          res = -1;
07114       }
07115    } else if (!strcasecmp(data, "echocan_mode")) {
07116       if (!strcasecmp(value, "on")) {
07117          ast_mutex_lock(&p->lock);
07118          dahdi_enable_ec(p);
07119          ast_mutex_unlock(&p->lock);
07120       } else if (!strcasecmp(value, "off")) {
07121          ast_mutex_lock(&p->lock);
07122          dahdi_disable_ec(p);
07123          ast_mutex_unlock(&p->lock);
07124 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07125       } else if (!strcasecmp(value, "fax")) {
07126          int blah = 1;
07127 
07128          ast_mutex_lock(&p->lock);
07129          if (!p->echocanon) {
07130             dahdi_enable_ec(p);
07131          }
07132          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07133             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07134          }
07135          ast_mutex_unlock(&p->lock);
07136       } else if (!strcasecmp(value, "voice")) {
07137          int blah = 0;
07138 
07139          ast_mutex_lock(&p->lock);
07140          if (!p->echocanon) {
07141             dahdi_enable_ec(p);
07142          }
07143          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07144             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07145          }
07146          ast_mutex_unlock(&p->lock);
07147 #endif
07148       } else {
07149          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07150          res = -1;
07151       }
07152    } else {
07153       res = -1;
07154    }
07155 
07156    return res;
07157 }
07158 
07159 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07160 {
07161    /* Unlink a specific slave or all slaves/masters from a given master */
07162    int x;
07163    int hasslaves;
07164    if (!master)
07165       return;
07166    if (needlock) {
07167       ast_mutex_lock(&master->lock);
07168       if (slave) {
07169          while (ast_mutex_trylock(&slave->lock)) {
07170             DEADLOCK_AVOIDANCE(&master->lock);
07171          }
07172       }
07173    }
07174    hasslaves = 0;
07175    for (x = 0; x < MAX_SLAVES; x++) {
07176       if (master->slaves[x]) {
07177          if (!slave || (master->slaves[x] == slave)) {
07178             /* Take slave out of the conference */
07179             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07180             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07181             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07182             master->slaves[x]->master = NULL;
07183             master->slaves[x] = NULL;
07184          } else
07185             hasslaves = 1;
07186       }
07187       if (!hasslaves)
07188          master->inconference = 0;
07189    }
07190    if (!slave) {
07191       if (master->master) {
07192          /* Take master out of the conference */
07193          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07194          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07195          hasslaves = 0;
07196          for (x = 0; x < MAX_SLAVES; x++) {
07197             if (master->master->slaves[x] == master)
07198                master->master->slaves[x] = NULL;
07199             else if (master->master->slaves[x])
07200                hasslaves = 1;
07201          }
07202          if (!hasslaves)
07203             master->master->inconference = 0;
07204       }
07205       master->master = NULL;
07206    }
07207    update_conf(master);
07208    if (needlock) {
07209       if (slave)
07210          ast_mutex_unlock(&slave->lock);
07211       ast_mutex_unlock(&master->lock);
07212    }
07213 }
07214 
07215 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07216    int x;
07217    if (!slave || !master) {
07218       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07219       return;
07220    }
07221    for (x = 0; x < MAX_SLAVES; x++) {
07222       if (!master->slaves[x]) {
07223          master->slaves[x] = slave;
07224          break;
07225       }
07226    }
07227    if (x >= MAX_SLAVES) {
07228       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07229       master->slaves[MAX_SLAVES - 1] = slave;
07230    }
07231    if (slave->master)
07232       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07233    slave->master = master;
07234 
07235    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07236 }
07237 
07238 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)
07239 {
07240    struct ast_channel *who;
07241    struct dahdi_pvt *p0, *p1, *op0, *op1;
07242    struct dahdi_pvt *master = NULL, *slave = NULL;
07243    struct ast_frame *f;
07244    int inconf = 0;
07245    int nothingok = 1;
07246    int ofd0, ofd1;
07247    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07248    int os0 = -1, os1 = -1;
07249    int priority = 0;
07250    struct ast_channel *oc0, *oc1;
07251    enum ast_bridge_result res;
07252 #ifdef PRI_2BCT
07253    int triedtopribridge = 0;
07254    q931_call *q931c0;
07255    q931_call *q931c1;
07256 #endif
07257 
07258    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07259       There is code below to handle it properly until DTMF is actually seen,
07260       but due to currently unresolved issues it's ignored...
07261    */
07262 
07263    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07264       return AST_BRIDGE_FAILED_NOWARN;
07265 
07266    ast_channel_lock(c0);
07267    while (ast_channel_trylock(c1)) {
07268       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07269    }
07270 
07271    p0 = c0->tech_pvt;
07272    p1 = c1->tech_pvt;
07273    /* cant do pseudo-channels here */
07274    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07275       ast_channel_unlock(c0);
07276       ast_channel_unlock(c1);
07277       return AST_BRIDGE_FAILED_NOWARN;
07278    }
07279 
07280    oi0 = dahdi_get_index(c0, p0, 0);
07281    oi1 = dahdi_get_index(c1, p1, 0);
07282    if ((oi0 < 0) || (oi1 < 0)) {
07283       ast_channel_unlock(c0);
07284       ast_channel_unlock(c1);
07285       return AST_BRIDGE_FAILED;
07286    }
07287 
07288    op0 = p0 = c0->tech_pvt;
07289    op1 = p1 = c1->tech_pvt;
07290    ofd0 = c0->fds[0];
07291    ofd1 = c1->fds[0];
07292    oc0 = p0->owner;
07293    oc1 = p1->owner;
07294 
07295    if (ast_mutex_trylock(&p0->lock)) {
07296       /* Don't block, due to potential for deadlock */
07297       ast_channel_unlock(c0);
07298       ast_channel_unlock(c1);
07299       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07300       return AST_BRIDGE_RETRY;
07301    }
07302    if (ast_mutex_trylock(&p1->lock)) {
07303       /* Don't block, due to potential for deadlock */
07304       ast_mutex_unlock(&p0->lock);
07305       ast_channel_unlock(c0);
07306       ast_channel_unlock(c1);
07307       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07308       return AST_BRIDGE_RETRY;
07309    }
07310 
07311    if ((p0->callwaiting && p0->callwaitingcallerid)
07312       || (p1->callwaiting && p1->callwaitingcallerid)) {
07313       /*
07314        * Call Waiting Caller ID requires DTMF detection to know if it
07315        * can send the CID spill.
07316        *
07317        * For now, don't attempt to native bridge if either channel
07318        * needs DTMF detection.  There is code below to handle it
07319        * properly until DTMF is actually seen, but due to currently
07320        * unresolved issues it's ignored...
07321        */
07322       ast_mutex_unlock(&p0->lock);
07323       ast_mutex_unlock(&p1->lock);
07324       ast_channel_unlock(c0);
07325       ast_channel_unlock(c1);
07326       return AST_BRIDGE_FAILED_NOWARN;
07327    }
07328 
07329 #if defined(HAVE_PRI)
07330    if ((dahdi_sig_pri_lib_handles(p0->sig)
07331          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07332       || (dahdi_sig_pri_lib_handles(p1->sig)
07333          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07334       /*
07335        * PRI nobch channels (hold and call waiting) are equivalent to
07336        * pseudo channels and cannot be done here.
07337        */
07338       ast_mutex_unlock(&p0->lock);
07339       ast_mutex_unlock(&p1->lock);
07340       ast_channel_unlock(c0);
07341       ast_channel_unlock(c1);
07342       return AST_BRIDGE_FAILED_NOWARN;
07343    }
07344 #endif   /* defined(HAVE_PRI) */
07345 
07346    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07347       if (p0->owner && p1->owner) {
07348          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07349          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07350             master = p0;
07351             slave = p1;
07352             inconf = 1;
07353          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07354             master = p1;
07355             slave = p0;
07356             inconf = 1;
07357          } else {
07358             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07359             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07360                p0->channel,
07361                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07362                p0->subs[SUB_REAL].inthreeway, p0->channel,
07363                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07364                p1->subs[SUB_REAL].inthreeway);
07365          }
07366          nothingok = 0;
07367       }
07368    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07369       if (p1->subs[SUB_THREEWAY].inthreeway) {
07370          master = p1;
07371          slave = p0;
07372          nothingok = 0;
07373       }
07374    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07375       if (p0->subs[SUB_THREEWAY].inthreeway) {
07376          master = p0;
07377          slave = p1;
07378          nothingok = 0;
07379       }
07380    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07381       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07382          don't put us in anything */
07383       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07384          master = p1;
07385          slave = p0;
07386          nothingok = 0;
07387       }
07388    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07389       /* Same as previous */
07390       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07391          master = p0;
07392          slave = p1;
07393          nothingok = 0;
07394       }
07395    }
07396    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07397       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07398    if (master && slave) {
07399       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07400          in an active threeway call with a channel that is ringing, we should
07401          indicate ringing. */
07402       if ((oi1 == SUB_THREEWAY) &&
07403          p1->subs[SUB_THREEWAY].inthreeway &&
07404          p1->subs[SUB_REAL].owner &&
07405          p1->subs[SUB_REAL].inthreeway &&
07406          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07407          ast_debug(1,
07408             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07409             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07410          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07411          os1 = p1->subs[SUB_REAL].owner->_state;
07412       } else {
07413          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07414             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07415          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07416       }
07417       if ((oi0 == SUB_THREEWAY) &&
07418          p0->subs[SUB_THREEWAY].inthreeway &&
07419          p0->subs[SUB_REAL].owner &&
07420          p0->subs[SUB_REAL].inthreeway &&
07421          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07422          ast_debug(1,
07423             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07424             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07425          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07426          os0 = p0->subs[SUB_REAL].owner->_state;
07427       } else {
07428          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07429             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07430          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07431       }
07432       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07433          if (!p0->echocanbridged || !p1->echocanbridged) {
07434             /* Disable echo cancellation if appropriate */
07435             dahdi_disable_ec(p0);
07436             dahdi_disable_ec(p1);
07437          }
07438       }
07439       dahdi_link(slave, master);
07440       master->inconference = inconf;
07441    } else if (!nothingok)
07442       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07443 
07444    update_conf(p0);
07445    update_conf(p1);
07446    t0 = p0->subs[SUB_REAL].inthreeway;
07447    t1 = p1->subs[SUB_REAL].inthreeway;
07448 
07449    ast_mutex_unlock(&p0->lock);
07450    ast_mutex_unlock(&p1->lock);
07451 
07452    ast_channel_unlock(c0);
07453    ast_channel_unlock(c1);
07454 
07455    /* Native bridge failed */
07456    if ((!master || !slave) && !nothingok) {
07457       dahdi_enable_ec(p0);
07458       dahdi_enable_ec(p1);
07459       return AST_BRIDGE_FAILED;
07460    }
07461 
07462    ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07463 
07464    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07465       disable_dtmf_detect(op0);
07466 
07467    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07468       disable_dtmf_detect(op1);
07469 
07470    for (;;) {
07471       struct ast_channel *c0_priority[2] = {c0, c1};
07472       struct ast_channel *c1_priority[2] = {c1, c0};
07473 
07474       /* Here's our main loop...  Start by locking things, looking for private parts,
07475          and then balking if anything is wrong */
07476 
07477       ast_channel_lock(c0);
07478       while (ast_channel_trylock(c1)) {
07479          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07480       }
07481 
07482       p0 = c0->tech_pvt;
07483       p1 = c1->tech_pvt;
07484 
07485       if (op0 == p0)
07486          i0 = dahdi_get_index(c0, p0, 1);
07487       if (op1 == p1)
07488          i1 = dahdi_get_index(c1, p1, 1);
07489 
07490       ast_channel_unlock(c0);
07491       ast_channel_unlock(c1);
07492 
07493       if (!timeoutms ||
07494          (op0 != p0) ||
07495          (op1 != p1) ||
07496          (ofd0 != c0->fds[0]) ||
07497          (ofd1 != c1->fds[0]) ||
07498          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07499          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07500          (oc0 != p0->owner) ||
07501          (oc1 != p1->owner) ||
07502          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07503          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07504          (oi0 != i0) ||
07505          (oi1 != i1)) {
07506          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07507             op0->channel, oi0, op1->channel, oi1);
07508          res = AST_BRIDGE_RETRY;
07509          goto return_from_bridge;
07510       }
07511 
07512 #ifdef PRI_2BCT
07513       if (!triedtopribridge) {
07514          triedtopribridge = 1;
07515          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07516             ast_mutex_lock(&p0->pri->lock);
07517             switch (p0->sig) {
07518             case SIG_PRI_LIB_HANDLE_CASES:
07519                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07520                break;
07521             default:
07522                q931c0 = NULL;
07523                break;
07524             }
07525             switch (p1->sig) {
07526             case SIG_PRI_LIB_HANDLE_CASES:
07527                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07528                break;
07529             default:
07530                q931c1 = NULL;
07531                break;
07532             }
07533             if (q931c0 && q931c1) {
07534                pri_channel_bridge(q931c0, q931c1);
07535             }
07536             ast_mutex_unlock(&p0->pri->lock);
07537          }
07538       }
07539 #endif
07540 
07541       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07542       if (!who) {
07543          ast_debug(1, "Ooh, empty read...\n");
07544          continue;
07545       }
07546       f = ast_read(who);
07547       switch (f ? f->frametype : AST_FRAME_CONTROL) {
07548       case AST_FRAME_CONTROL:
07549          *fo = f;
07550          *rc = who;
07551          res = AST_BRIDGE_COMPLETE;
07552          goto return_from_bridge;
07553       case AST_FRAME_DTMF_END:
07554          if ((who == c0) && p0->pulsedial) {
07555             ast_write(c1, f);
07556          } else if ((who == c1) && p1->pulsedial) {
07557             ast_write(c0, f);
07558          } else {
07559             *fo = f;
07560             *rc = who;
07561             res = AST_BRIDGE_COMPLETE;
07562             goto return_from_bridge;
07563          }
07564          break;
07565       case AST_FRAME_TEXT:
07566          if (who == c0) {
07567             ast_write(c1, f);
07568          } else {
07569             ast_write(c0, f);
07570          }
07571          break;
07572       case AST_FRAME_VOICE:
07573          /* Native bridge handles voice frames in hardware. */
07574       case AST_FRAME_NULL:
07575          break;
07576       default:
07577          ast_debug(1, "Chan '%s' is discarding frame of frametype:%d\n",
07578             ast_channel_name(who), f->frametype);
07579          break;
07580       }
07581       ast_frfree(f);
07582 
07583       /* Swap who gets priority */
07584       priority = !priority;
07585    }
07586 
07587 return_from_bridge:
07588    if (op0 == p0)
07589       dahdi_enable_ec(p0);
07590 
07591    if (op1 == p1)
07592       dahdi_enable_ec(p1);
07593 
07594    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07595       enable_dtmf_detect(op0);
07596 
07597    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07598       enable_dtmf_detect(op1);
07599 
07600    dahdi_unlink(slave, master, 1);
07601 
07602    return res;
07603 }
07604 
07605 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07606 {
07607    struct dahdi_pvt *p = newchan->tech_pvt;
07608    int x;
07609 
07610    ast_mutex_lock(&p->lock);
07611 
07612    ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07613    if (p->owner == oldchan) {
07614       p->owner = newchan;
07615    }
07616    for (x = 0; x < 3; x++) {
07617       if (p->subs[x].owner == oldchan) {
07618          if (!x) {
07619             dahdi_unlink(NULL, p, 0);
07620          }
07621          p->subs[x].owner = newchan;
07622       }
07623    }
07624    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07625       analog_fixup(oldchan, newchan, p->sig_pvt);
07626 #if defined(HAVE_PRI)
07627    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07628       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07629 #endif   /* defined(HAVE_PRI) */
07630 #if defined(HAVE_SS7)
07631    } else if (p->sig == SIG_SS7) {
07632       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07633 #endif   /* defined(HAVE_SS7) */
07634    }
07635    update_conf(p);
07636 
07637    ast_mutex_unlock(&p->lock);
07638 
07639    if (newchan->_state == AST_STATE_RINGING) {
07640       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07641    }
07642    return 0;
07643 }
07644 
07645 static int dahdi_ring_phone(struct dahdi_pvt *p)
07646 {
07647    int x;
07648    int res;
07649    /* Make sure our transmit state is on hook */
07650    x = 0;
07651    x = DAHDI_ONHOOK;
07652    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07653    do {
07654       x = DAHDI_RING;
07655       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07656       if (res) {
07657          switch (errno) {
07658          case EBUSY:
07659          case EINTR:
07660             /* Wait just in case */
07661             usleep(10000);
07662             continue;
07663          case EINPROGRESS:
07664             res = 0;
07665             break;
07666          default:
07667             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07668             res = 0;
07669          }
07670       }
07671    } while (res);
07672    return res;
07673 }
07674 
07675 static void *analog_ss_thread(void *data);
07676 
07677 static int attempt_transfer(struct dahdi_pvt *p)
07678 {
07679    /* In order to transfer, we need at least one of the channels to
07680       actually be in a call bridge.  We can't conference two applications
07681       together (but then, why would we want to?) */
07682    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07683       /* The three-way person we're about to transfer to could still be in MOH, so
07684          stop if now if appropriate */
07685       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07686          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07687       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07688          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07689       }
07690       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07691          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07692       }
07693        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07694          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07695                ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07696          return -1;
07697       }
07698       /* Orphan the channel after releasing the lock */
07699       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07700       unalloc_sub(p, SUB_THREEWAY);
07701    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07702       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07703       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07704          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07705       }
07706       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07707          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07708       }
07709       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07710          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07711                ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07712          return -1;
07713       }
07714       /* Three-way is now the REAL */
07715       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07716       ast_channel_unlock(p->subs[SUB_REAL].owner);
07717       unalloc_sub(p, SUB_THREEWAY);
07718       /* Tell the caller not to hangup */
07719       return 1;
07720    } else {
07721       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07722          ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07723       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07724       return -1;
07725    }
07726    return 0;
07727 }
07728 
07729 static int check_for_conference(struct dahdi_pvt *p)
07730 {
07731    struct dahdi_confinfo ci;
07732    /* Fine if we already have a master, etc */
07733    if (p->master || (p->confno > -1))
07734       return 0;
07735    memset(&ci, 0, sizeof(ci));
07736    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07737       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07738       return 0;
07739    }
07740    /* If we have no master and don't have a confno, then
07741       if we're in a conference, it's probably a MeetMe room or
07742       some such, so don't let us 3-way out! */
07743    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07744       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07745       return 1;
07746    }
07747    return 0;
07748 }
07749 
07750 /*! Checks channel for alarms
07751  * \param p a channel to check for alarms.
07752  * \returns the alarms on the span to which the channel belongs, or alarms on
07753  *          the channel if no span alarms.
07754  */
07755 static int get_alarms(struct dahdi_pvt *p)
07756 {
07757    int res;
07758    struct dahdi_spaninfo zi;
07759    struct dahdi_params params;
07760 
07761    memset(&zi, 0, sizeof(zi));
07762    zi.spanno = p->span;
07763 
07764    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07765       if (zi.alarms != DAHDI_ALARM_NONE)
07766          return zi.alarms;
07767    } else {
07768       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07769       return 0;
07770    }
07771 
07772    /* No alarms on the span. Check for channel alarms. */
07773    memset(&params, 0, sizeof(params));
07774    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07775       return params.chan_alarms;
07776 
07777    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07778 
07779    return DAHDI_ALARM_NONE;
07780 }
07781 
07782 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07783 {
07784    struct dahdi_pvt *p = ast->tech_pvt;
07785    struct ast_frame *f = *dest;
07786 
07787    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07788       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07789       f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07790 
07791    if (p->confirmanswer) {
07792       if (f->frametype == AST_FRAME_DTMF_END) {
07793          ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07794          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07795             of a DTMF digit */
07796          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07797          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07798          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07799          p->confirmanswer = 0;
07800       } else {
07801          p->subs[idx].f.frametype = AST_FRAME_NULL;
07802          p->subs[idx].f.subclass.integer = 0;
07803       }
07804       *dest = &p->subs[idx].f;
07805    } else if (p->callwaitcas) {
07806       if (f->frametype == AST_FRAME_DTMF_END) {
07807          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07808             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07809             ast_free(p->cidspill);
07810             p->cidspill = NULL;
07811             send_cwcidspill(p);
07812          }
07813          p->callwaitcas = 0;
07814       }
07815       p->subs[idx].f.frametype = AST_FRAME_NULL;
07816       p->subs[idx].f.subclass.integer = 0;
07817       *dest = &p->subs[idx].f;
07818    } else if (f->subclass.integer == 'f') {
07819       if (f->frametype == AST_FRAME_DTMF_END) {
07820          /* Fax tone -- Handle and return NULL */
07821          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07822             /* If faxbuffers are configured, use them for the fax transmission */
07823             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07824                struct dahdi_bufferinfo bi = {
07825                   .txbufpolicy = p->faxbuf_policy,
07826                   .bufsize = p->bufsize,
07827                   .numbufs = p->faxbuf_no
07828                };
07829                int res;
07830 
07831                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07832                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07833                } else {
07834                   p->bufferoverrideinuse = 1;
07835                }
07836             }
07837             p->faxhandled = 1;
07838             if (p->dsp) {
07839                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07840                ast_dsp_set_features(p->dsp, p->dsp_features);
07841                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07842             }
07843             if (strcmp(ast->exten, "fax")) {
07844                const char *target_context = S_OR(ast->macrocontext, ast->context);
07845 
07846                /* We need to unlock 'ast' here because ast_exists_extension has the
07847                 * potential to start autoservice on the channel. Such action is prone
07848                 * to deadlock.
07849                 */
07850                ast_mutex_unlock(&p->lock);
07851                ast_channel_unlock(ast);
07852                if (ast_exists_extension(ast, target_context, "fax", 1,
07853                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07854                   ast_channel_lock(ast);
07855                   ast_mutex_lock(&p->lock);
07856                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
07857                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07858                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07859                   if (ast_async_goto(ast, target_context, "fax", 1))
07860                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
07861                } else {
07862                   ast_channel_lock(ast);
07863                   ast_mutex_lock(&p->lock);
07864                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07865                }
07866             } else {
07867                ast_debug(1, "Already in a fax extension, not redirecting\n");
07868             }
07869          } else {
07870             ast_debug(1, "Fax already handled\n");
07871          }
07872          dahdi_confmute(p, 0);
07873       }
07874       p->subs[idx].f.frametype = AST_FRAME_NULL;
07875       p->subs[idx].f.subclass.integer = 0;
07876       *dest = &p->subs[idx].f;
07877    }
07878 }
07879 
07880 static void handle_alarms(struct dahdi_pvt *p, int alms)
07881 {
07882    const char *alarm_str = alarm2str(alms);
07883 
07884    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07885       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07886       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07887                  "Alarm: %s\r\n"
07888                  "Channel: %d\r\n",
07889                  alarm_str, p->channel);
07890    }
07891 
07892    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07893       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07894       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07895                  "Alarm: %s\r\n"
07896                  "Span: %d\r\n",
07897                  alarm_str, p->span);
07898    }
07899 }
07900 
07901 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07902 {
07903    int res, x;
07904    int idx, mysig;
07905    char *c;
07906    struct dahdi_pvt *p = ast->tech_pvt;
07907    pthread_t threadid;
07908    struct ast_channel *chan;
07909    struct ast_frame *f;
07910 
07911    idx = dahdi_get_index(ast, p, 0);
07912    mysig = p->sig;
07913    if (p->outsigmod > -1)
07914       mysig = p->outsigmod;
07915    p->subs[idx].f.frametype = AST_FRAME_NULL;
07916    p->subs[idx].f.subclass.integer = 0;
07917    p->subs[idx].f.datalen = 0;
07918    p->subs[idx].f.samples = 0;
07919    p->subs[idx].f.mallocd = 0;
07920    p->subs[idx].f.offset = 0;
07921    p->subs[idx].f.src = "dahdi_handle_event";
07922    p->subs[idx].f.data.ptr = NULL;
07923    f = &p->subs[idx].f;
07924 
07925    if (idx < 0)
07926       return &p->subs[idx].f;
07927    if (p->fake_event) {
07928       res = p->fake_event;
07929       p->fake_event = 0;
07930    } else
07931       res = dahdi_get_event(p->subs[idx].dfd);
07932 
07933    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07934 
07935    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07936       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07937       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07938 #if defined(HAVE_PRI)
07939       if (dahdi_sig_pri_lib_handles(p->sig)
07940          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07941          && p->pri
07942          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07943          /* absorb event */
07944       } else
07945 #endif   /* defined(HAVE_PRI) */
07946       {
07947          /* Unmute conference */
07948          dahdi_confmute(p, 0);
07949          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07950          p->subs[idx].f.subclass.integer = res & 0xff;
07951          dahdi_handle_dtmf(ast, idx, &f);
07952       }
07953       return f;
07954    }
07955 
07956    if (res & DAHDI_EVENT_DTMFDOWN) {
07957       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07958 #if defined(HAVE_PRI)
07959       if (dahdi_sig_pri_lib_handles(p->sig)
07960          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07961          && p->pri
07962          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07963          /* absorb event */
07964       } else
07965 #endif   /* defined(HAVE_PRI) */
07966       {
07967          /* Mute conference */
07968          dahdi_confmute(p, 1);
07969          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07970          p->subs[idx].f.subclass.integer = res & 0xff;
07971          dahdi_handle_dtmf(ast, idx, &f);
07972       }
07973       return &p->subs[idx].f;
07974    }
07975 
07976    switch (res) {
07977    case DAHDI_EVENT_EC_DISABLED:
07978       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07979       p->echocanon = 0;
07980       break;
07981 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07982    case DAHDI_EVENT_TX_CED_DETECTED:
07983       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07984       break;
07985    case DAHDI_EVENT_RX_CED_DETECTED:
07986       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07987       break;
07988    case DAHDI_EVENT_EC_NLP_DISABLED:
07989       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07990       break;
07991    case DAHDI_EVENT_EC_NLP_ENABLED:
07992       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07993       break;
07994 #endif
07995    case DAHDI_EVENT_BITSCHANGED:
07996 #ifdef HAVE_OPENR2
07997       if (p->sig != SIG_MFCR2) {
07998          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07999       } else {
08000          ast_debug(1, "bits changed in chan %d\n", p->channel);
08001          openr2_chan_handle_cas(p->r2chan);
08002       }
08003 #else
08004       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08005 #endif
08006    case DAHDI_EVENT_PULSE_START:
08007       /* Stop tone if there's a pulse start and the PBX isn't started */
08008       if (!ast->pbx)
08009          tone_zone_play_tone(p->subs[idx].dfd, -1);
08010       break;
08011    case DAHDI_EVENT_DIALCOMPLETE:
08012       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08013 #if defined(HAVE_PRI)
08014       if (dahdi_sig_pri_lib_handles(p->sig)) {
08015          if (p->inalarm) {
08016             break;
08017          }
08018          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08019             ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08020                ast_channel_name(ast), strerror(errno));
08021             return NULL;
08022          }
08023          if (x) {
08024             /* Still dialing in DAHDI driver */
08025             break;
08026          }
08027          /*
08028           * The ast channel is locked and the private may be locked more
08029           * than once.
08030           */
08031          sig_pri_dial_complete(p->sig_pvt, ast);
08032          break;
08033       }
08034 #endif   /* defined(HAVE_PRI) */
08035 #ifdef HAVE_OPENR2
08036       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08037          /* we don't need to do anything for this event for R2 signaling
08038             if the call is being setup */
08039          break;
08040       }
08041 #endif
08042       if (p->inalarm) break;
08043       if ((p->radio || (p->oprmode < 0))) break;
08044       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08045          ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08046          return NULL;
08047       }
08048       if (!x) { /* if not still dialing in driver */
08049          dahdi_enable_ec(p);
08050          if (p->echobreak) {
08051             dahdi_train_ec(p);
08052             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08053             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08054             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08055             p->echobreak = 0;
08056          } else {
08057             p->dialing = 0;
08058             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08059                /* if thru with dialing after offhook */
08060                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08061                   ast_setstate(ast, AST_STATE_UP);
08062                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064                   break;
08065                } else { /* if to state wait for offhook to dial rest */
08066                   /* we now wait for off hook */
08067                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08068                }
08069             }
08070             if (ast->_state == AST_STATE_DIALING) {
08071                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08072                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08073                } else if (p->confirmanswer || (!p->dialednone
08074                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08075                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08076                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08077                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08078                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08079                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08080                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08081                      || (mysig == SIG_SF_FEATB)))) {
08082                   ast_setstate(ast, AST_STATE_RINGING);
08083                } else if (!p->answeronpolarityswitch) {
08084                   ast_setstate(ast, AST_STATE_UP);
08085                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08086                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08087                   /* If aops=0 and hops=1, this is necessary */
08088                   p->polarity = POLARITY_REV;
08089                } else {
08090                   /* Start clean, so we can catch the change to REV polarity when party answers */
08091                   p->polarity = POLARITY_IDLE;
08092                }
08093             }
08094          }
08095       }
08096       break;
08097    case DAHDI_EVENT_ALARM:
08098       switch (p->sig) {
08099 #if defined(HAVE_PRI)
08100       case SIG_PRI_LIB_HANDLE_CASES:
08101          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08102          break;
08103 #endif   /* defined(HAVE_PRI) */
08104 #if defined(HAVE_SS7)
08105       case SIG_SS7:
08106          sig_ss7_set_alarm(p->sig_pvt, 1);
08107          break;
08108 #endif   /* defined(HAVE_SS7) */
08109       default:
08110          p->inalarm = 1;
08111          break;
08112       }
08113       res = get_alarms(p);
08114       handle_alarms(p, res);
08115 #ifdef HAVE_PRI
08116       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08117          /* fall through intentionally */
08118       } else {
08119          break;
08120       }
08121 #endif
08122 #if defined(HAVE_SS7)
08123       if (p->sig == SIG_SS7)
08124          break;
08125 #endif   /* defined(HAVE_SS7) */
08126 #ifdef HAVE_OPENR2
08127       if (p->sig == SIG_MFCR2)
08128          break;
08129 #endif
08130    case DAHDI_EVENT_ONHOOK:
08131       if (p->radio) {
08132          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08134          break;
08135       }
08136       if (p->oprmode < 0)
08137       {
08138          if (p->oprmode != -1) break;
08139          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08140          {
08141             /* Make sure it starts ringing */
08142             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08143             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08144             save_conference(p->oprpeer);
08145             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08146          }
08147          break;
08148       }
08149       switch (p->sig) {
08150       case SIG_FXOLS:
08151       case SIG_FXOGS:
08152       case SIG_FXOKS:
08153          /* Check for some special conditions regarding call waiting */
08154          if (idx == SUB_REAL) {
08155             /* The normal line was hung up */
08156             if (p->subs[SUB_CALLWAIT].owner) {
08157                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08158                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08159                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08160                unalloc_sub(p, SUB_CALLWAIT);
08161 #if 0
08162                p->subs[idx].needanswer = 0;
08163                p->subs[idx].needringing = 0;
08164 #endif
08165                p->callwaitingrepeat = 0;
08166                p->cidcwexpire = 0;
08167                p->cid_suppress_expire = 0;
08168                p->owner = NULL;
08169                /* Don't start streaming audio yet if the incoming call isn't up yet */
08170                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08171                   p->dialing = 1;
08172                dahdi_ring_phone(p);
08173             } else if (p->subs[SUB_THREEWAY].owner) {
08174                unsigned int mssinceflash;
08175                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08176                   the private structure -- not especially easy or clean */
08177                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08178                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08179                   DLA_UNLOCK(&p->lock);
08180                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08181                   /* We can grab ast and p in that order, without worry.  We should make sure
08182                      nothing seriously bad has happened though like some sort of bizarre double
08183                      masquerade! */
08184                   DLA_LOCK(&p->lock);
08185                   if (p->owner != ast) {
08186                      ast_log(LOG_WARNING, "This isn't good...\n");
08187                      return NULL;
08188                   }
08189                }
08190                if (!p->subs[SUB_THREEWAY].owner) {
08191                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08192                   return NULL;
08193                }
08194                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08195                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08196                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08197                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08198                      hanging up.  Hangup both channels now */
08199                   if (p->subs[SUB_THREEWAY].owner)
08200                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08201                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08202                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08203                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08204                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08205                   if (p->transfer) {
08206                      /* In any case this isn't a threeway call anymore */
08207                      p->subs[SUB_REAL].inthreeway = 0;
08208                      p->subs[SUB_THREEWAY].inthreeway = 0;
08209                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08210                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08211                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08212                         /* Swap subs and dis-own channel */
08213                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08214                         p->owner = NULL;
08215                         /* Ring the phone */
08216                         dahdi_ring_phone(p);
08217                      } else {
08218                         if ((res = attempt_transfer(p)) < 0) {
08219                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08220                            if (p->subs[SUB_THREEWAY].owner)
08221                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222                         } else if (res) {
08223                            /* Don't actually hang up at this point */
08224                            if (p->subs[SUB_THREEWAY].owner)
08225                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08226                            break;
08227                         }
08228                      }
08229                   } else {
08230                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08231                      if (p->subs[SUB_THREEWAY].owner)
08232                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233                   }
08234                } else {
08235                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08236                   /* Swap subs and dis-own channel */
08237                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08238                   p->owner = NULL;
08239                   /* Ring the phone */
08240                   dahdi_ring_phone(p);
08241                }
08242             }
08243          } else {
08244             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08245          }
08246          /* Fall through */
08247       default:
08248          dahdi_disable_ec(p);
08249          return NULL;
08250       }
08251       break;
08252    case DAHDI_EVENT_RINGOFFHOOK:
08253       if (p->inalarm) break;
08254       if (p->oprmode < 0)
08255       {
08256          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08257          {
08258             /* Make sure it stops ringing */
08259             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08260             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08261             restore_conference(p->oprpeer);
08262          }
08263          break;
08264       }
08265       if (p->radio)
08266       {
08267          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08268          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08269          break;
08270       }
08271       /* for E911, its supposed to wait for offhook then dial
08272          the second half of the dial string */
08273       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08274          c = strchr(p->dialdest, '/');
08275          if (c)
08276             c++;
08277          else
08278             c = p->dialdest;
08279          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08280          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08281          if (strlen(p->dop.dialstr) > 4) {
08282             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08283             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08284             p->echorest[sizeof(p->echorest) - 1] = '\0';
08285             p->echobreak = 1;
08286             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08287          } else
08288             p->echobreak = 0;
08289          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08290             int saveerr = errno;
08291 
08292             x = DAHDI_ONHOOK;
08293             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08294             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08295             return NULL;
08296             }
08297          p->dialing = 1;
08298          return &p->subs[idx].f;
08299       }
08300       switch (p->sig) {
08301       case SIG_FXOLS:
08302       case SIG_FXOGS:
08303       case SIG_FXOKS:
08304          switch (ast->_state) {
08305          case AST_STATE_RINGING:
08306             dahdi_enable_ec(p);
08307             dahdi_train_ec(p);
08308             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08309             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08310             /* Make sure it stops ringing */
08311             p->subs[SUB_REAL].needringing = 0;
08312             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08313             ast_debug(1, "channel %d answered\n", p->channel);
08314 
08315             /* Cancel any running CallerID spill */
08316             ast_free(p->cidspill);
08317             p->cidspill = NULL;
08318             restore_conference(p);
08319 
08320             p->dialing = 0;
08321             p->callwaitcas = 0;
08322             if (p->confirmanswer) {
08323                /* Ignore answer if "confirm answer" is enabled */
08324                p->subs[idx].f.frametype = AST_FRAME_NULL;
08325                p->subs[idx].f.subclass.integer = 0;
08326             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08327                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08328                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08329                if (res < 0) {
08330                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08331                   p->dop.dialstr[0] = '\0';
08332                   return NULL;
08333                } else {
08334                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08335                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08336                   p->subs[idx].f.subclass.integer = 0;
08337                   p->dialing = 1;
08338                }
08339                p->dop.dialstr[0] = '\0';
08340                ast_setstate(ast, AST_STATE_DIALING);
08341             } else
08342                ast_setstate(ast, AST_STATE_UP);
08343             return &p->subs[idx].f;
08344          case AST_STATE_DOWN:
08345             ast_setstate(ast, AST_STATE_RING);
08346             ast->rings = 1;
08347             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08348             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08349             ast_debug(1, "channel %d picked up\n", p->channel);
08350             return &p->subs[idx].f;
08351          case AST_STATE_UP:
08352             /* Make sure it stops ringing */
08353             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08354             /* Okay -- probably call waiting*/
08355             if (ast_bridged_channel(p->owner))
08356                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08357             p->subs[idx].needunhold = 1;
08358             break;
08359          case AST_STATE_RESERVED:
08360             /* Start up dialtone */
08361             if (has_voicemail(p))
08362                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08363             else
08364                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08365             break;
08366          default:
08367             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08368          }
08369          break;
08370       case SIG_FXSLS:
08371       case SIG_FXSGS:
08372       case SIG_FXSKS:
08373          if (ast->_state == AST_STATE_RING) {
08374             p->ringt = p->ringt_base;
08375          }
08376 
08377          /* If we get a ring then we cannot be in
08378           * reversed polarity. So we reset to idle */
08379          ast_debug(1, "Setting IDLE polarity due "
08380             "to ring. Old polarity was %d\n",
08381             p->polarity);
08382          p->polarity = POLARITY_IDLE;
08383 
08384          /* Fall through */
08385       case SIG_EM:
08386       case SIG_EM_E1:
08387       case SIG_EMWINK:
08388       case SIG_FEATD:
08389       case SIG_FEATDMF:
08390       case SIG_FEATDMF_TA:
08391       case SIG_E911:
08392       case SIG_FGC_CAMA:
08393       case SIG_FGC_CAMAMF:
08394       case SIG_FEATB:
08395       case SIG_SF:
08396       case SIG_SFWINK:
08397       case SIG_SF_FEATD:
08398       case SIG_SF_FEATDMF:
08399       case SIG_SF_FEATB:
08400          if (ast->_state == AST_STATE_PRERING)
08401             ast_setstate(ast, AST_STATE_RING);
08402          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08403             ast_debug(1, "Ring detected\n");
08404             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08405             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08406          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08407             ast_debug(1, "Line answered\n");
08408             if (p->confirmanswer) {
08409                p->subs[idx].f.frametype = AST_FRAME_NULL;
08410                p->subs[idx].f.subclass.integer = 0;
08411             } else {
08412                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08413                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08414                ast_setstate(ast, AST_STATE_UP);
08415             }
08416          } else if (ast->_state != AST_STATE_RING)
08417             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08418          break;
08419       default:
08420          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08421       }
08422       break;
08423    case DAHDI_EVENT_RINGBEGIN:
08424       switch (p->sig) {
08425       case SIG_FXSLS:
08426       case SIG_FXSGS:
08427       case SIG_FXSKS:
08428          if (ast->_state == AST_STATE_RING) {
08429             p->ringt = p->ringt_base;
08430          }
08431          break;
08432       }
08433       break;
08434    case DAHDI_EVENT_RINGERON:
08435       break;
08436    case DAHDI_EVENT_NOALARM:
08437       switch (p->sig) {
08438 #if defined(HAVE_PRI)
08439       case SIG_PRI_LIB_HANDLE_CASES:
08440          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08441          break;
08442 #endif   /* defined(HAVE_PRI) */
08443 #if defined(HAVE_SS7)
08444       case SIG_SS7:
08445          sig_ss7_set_alarm(p->sig_pvt, 0);
08446          break;
08447 #endif   /* defined(HAVE_SS7) */
08448       default:
08449          p->inalarm = 0;
08450          break;
08451       }
08452       handle_clear_alarms(p);
08453       break;
08454    case DAHDI_EVENT_WINKFLASH:
08455       if (p->inalarm) break;
08456       if (p->radio) break;
08457       if (p->oprmode < 0) break;
08458       if (p->oprmode > 1)
08459       {
08460          struct dahdi_params par;
08461 
08462          memset(&par, 0, sizeof(par));
08463          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08464          {
08465             if (!par.rxisoffhook)
08466             {
08467                /* Make sure it stops ringing */
08468                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08469                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08470                save_conference(p);
08471                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08472             }
08473          }
08474          break;
08475       }
08476       /* Remember last time we got a flash-hook */
08477       p->flashtime = ast_tvnow();
08478       switch (mysig) {
08479       case SIG_FXOLS:
08480       case SIG_FXOGS:
08481       case SIG_FXOKS:
08482          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08483             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08484 
08485          /* Cancel any running CallerID spill */
08486          ast_free(p->cidspill);
08487          p->cidspill = NULL;
08488          restore_conference(p);
08489          p->callwaitcas = 0;
08490 
08491          if (idx != SUB_REAL) {
08492             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08493             goto winkflashdone;
08494          }
08495 
08496          if (p->subs[SUB_CALLWAIT].owner) {
08497             /* Swap to call-wait */
08498             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08499             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08500             p->owner = p->subs[SUB_REAL].owner;
08501             ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08502             if (p->owner->_state == AST_STATE_RINGING) {
08503                ast_setstate(p->owner, AST_STATE_UP);
08504                p->subs[SUB_REAL].needanswer = 1;
08505             }
08506             p->callwaitingrepeat = 0;
08507             p->cidcwexpire = 0;
08508             p->cid_suppress_expire = 0;
08509             /* Start music on hold if appropriate */
08510             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08511                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08512                   S_OR(p->mohsuggest, NULL),
08513                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08514             }
08515             p->subs[SUB_CALLWAIT].needhold = 1;
08516             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08517                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08518                   S_OR(p->mohsuggest, NULL),
08519                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08520             }
08521             p->subs[SUB_REAL].needunhold = 1;
08522          } else if (!p->subs[SUB_THREEWAY].owner) {
08523             if (!p->threewaycalling) {
08524                /* Just send a flash if no 3-way calling */
08525                p->subs[SUB_REAL].needflash = 1;
08526                goto winkflashdone;
08527             } else if (!check_for_conference(p)) {
08528                char cid_num[256];
08529                char cid_name[256];
08530 
08531                cid_num[0] = 0;
08532                cid_name[0] = 0;
08533                if (p->dahditrcallerid && p->owner) {
08534                   if (p->owner->caller.id.number.valid
08535                      && p->owner->caller.id.number.str) {
08536                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08537                         sizeof(cid_num));
08538                   }
08539                   if (p->owner->caller.id.name.valid
08540                      && p->owner->caller.id.name.str) {
08541                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08542                         sizeof(cid_name));
08543                   }
08544                }
08545                /* XXX This section needs much more error checking!!! XXX */
08546                /* Start a 3-way call if feasible */
08547                if (!((ast->pbx) ||
08548                   (ast->_state == AST_STATE_UP) ||
08549                   (ast->_state == AST_STATE_RING))) {
08550                   ast_debug(1, "Flash when call not up or ringing\n");
08551                   goto winkflashdone;
08552                }
08553                if (alloc_sub(p, SUB_THREEWAY)) {
08554                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08555                   goto winkflashdone;
08556                }
08557                /* Make new channel */
08558                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08559                if (p->dahditrcallerid) {
08560                   if (!p->origcid_num)
08561                      p->origcid_num = ast_strdup(p->cid_num);
08562                   if (!p->origcid_name)
08563                      p->origcid_name = ast_strdup(p->cid_name);
08564                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08565                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08566                }
08567                /* Swap things around between the three-way and real call */
08568                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08569                /* Disable echo canceller for better dialing */
08570                dahdi_disable_ec(p);
08571                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08572                if (res)
08573                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08574                p->owner = chan;
08575                if (!chan) {
08576                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08577                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08578                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08579                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08580                   dahdi_enable_ec(p);
08581                   ast_hangup(chan);
08582                } else {
08583                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08584 
08585                   /* Start music on hold if appropriate */
08586                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08587                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08588                         S_OR(p->mohsuggest, NULL),
08589                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08590                   }
08591                   p->subs[SUB_THREEWAY].needhold = 1;
08592                }
08593             }
08594          } else {
08595             /* Already have a 3 way call */
08596             if (p->subs[SUB_THREEWAY].inthreeway) {
08597                /* Call is already up, drop the last person */
08598                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08599                /* If the primary call isn't answered yet, use it */
08600                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08601                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08602                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08603                   p->owner = p->subs[SUB_REAL].owner;
08604                }
08605                /* Drop the last call and stop the conference */
08606                ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08607                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08608                p->subs[SUB_REAL].inthreeway = 0;
08609                p->subs[SUB_THREEWAY].inthreeway = 0;
08610             } else {
08611                /* Lets see what we're up to */
08612                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08613                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08614                   int otherindex = SUB_THREEWAY;
08615 
08616                   ast_verb(3, "Building conference call with %s and %s\n",
08617                      ast_channel_name(p->subs[SUB_THREEWAY].owner),
08618                      ast_channel_name(p->subs[SUB_REAL].owner));
08619                   /* Put them in the threeway, and flip */
08620                   p->subs[SUB_THREEWAY].inthreeway = 1;
08621                   p->subs[SUB_REAL].inthreeway = 1;
08622                   if (ast->_state == AST_STATE_UP) {
08623                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08624                      otherindex = SUB_REAL;
08625                   }
08626                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08627                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08628                   p->subs[otherindex].needunhold = 1;
08629                   p->owner = p->subs[SUB_REAL].owner;
08630                } else {
08631                   ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08632                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08633                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08634                   p->owner = p->subs[SUB_REAL].owner;
08635                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08636                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08637                   p->subs[SUB_REAL].needunhold = 1;
08638                   dahdi_enable_ec(p);
08639                }
08640             }
08641          }
08642 winkflashdone:
08643          update_conf(p);
08644          break;
08645       case SIG_EM:
08646       case SIG_EM_E1:
08647       case SIG_FEATD:
08648       case SIG_SF:
08649       case SIG_SFWINK:
08650       case SIG_SF_FEATD:
08651       case SIG_FXSLS:
08652       case SIG_FXSGS:
08653          if (p->dialing)
08654             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08655          else
08656             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08657          break;
08658       case SIG_FEATDMF_TA:
08659          switch (p->whichwink) {
08660          case 0:
08661             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08662                S_COR(p->owner->caller.ani.number.valid,
08663                   p->owner->caller.ani.number.str, ""));
08664             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08665                p->owner->caller.ani2,
08666                S_COR(p->owner->caller.ani.number.valid,
08667                   p->owner->caller.ani.number.str, ""));
08668             break;
08669          case 1:
08670             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08671             break;
08672          case 2:
08673             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08674             return NULL;
08675          }
08676          p->whichwink++;
08677          /* Fall through */
08678       case SIG_FEATDMF:
08679       case SIG_E911:
08680       case SIG_FGC_CAMAMF:
08681       case SIG_FGC_CAMA:
08682       case SIG_FEATB:
08683       case SIG_SF_FEATDMF:
08684       case SIG_SF_FEATB:
08685       case SIG_EMWINK:
08686          /* FGD MF and EMWINK *Must* wait for wink */
08687          if (!ast_strlen_zero(p->dop.dialstr)) {
08688             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08689             if (res < 0) {
08690                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08691                p->dop.dialstr[0] = '\0';
08692                return NULL;
08693             } else
08694                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08695          }
08696          p->dop.dialstr[0] = '\0';
08697          break;
08698       default:
08699          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08700       }
08701       break;
08702    case DAHDI_EVENT_HOOKCOMPLETE:
08703       if (p->inalarm) break;
08704       if ((p->radio || (p->oprmode < 0))) break;
08705       if (p->waitingfordt.tv_sec) break;
08706       switch (mysig) {
08707       case SIG_FXSLS:  /* only interesting for FXS */
08708       case SIG_FXSGS:
08709       case SIG_FXSKS:
08710       case SIG_EM:
08711       case SIG_EM_E1:
08712       case SIG_EMWINK:
08713       case SIG_FEATD:
08714       case SIG_SF:
08715       case SIG_SFWINK:
08716       case SIG_SF_FEATD:
08717          if (!ast_strlen_zero(p->dop.dialstr)) {
08718             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08719             if (res < 0) {
08720                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08721                p->dop.dialstr[0] = '\0';
08722                return NULL;
08723             } else
08724                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08725          }
08726          p->dop.dialstr[0] = '\0';
08727          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08728          break;
08729       case SIG_FEATDMF:
08730       case SIG_FEATDMF_TA:
08731       case SIG_E911:
08732       case SIG_FGC_CAMA:
08733       case SIG_FGC_CAMAMF:
08734       case SIG_FEATB:
08735       case SIG_SF_FEATDMF:
08736       case SIG_SF_FEATB:
08737          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08738          break;
08739       default:
08740          break;
08741       }
08742       break;
08743    case DAHDI_EVENT_POLARITY:
08744       /*
08745        * If we get a Polarity Switch event, check to see
08746        * if we should change the polarity state and
08747        * mark the channel as UP or if this is an indication
08748        * of remote end disconnect.
08749        */
08750       if (p->polarity == POLARITY_IDLE) {
08751          p->polarity = POLARITY_REV;
08752          if (p->answeronpolarityswitch &&
08753             ((ast->_state == AST_STATE_DIALING) ||
08754             (ast->_state == AST_STATE_RINGING))) {
08755             ast_debug(1, "Answering on polarity switch!\n");
08756             ast_setstate(p->owner, AST_STATE_UP);
08757             if (p->hanguponpolarityswitch) {
08758                p->polaritydelaytv = ast_tvnow();
08759             }
08760          } else
08761             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08762       }
08763       /* Removed else statement from here as it was preventing hangups from ever happening*/
08764       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08765       if (p->hanguponpolarityswitch &&
08766          (p->polarityonanswerdelay > 0) &&
08767          (p->polarity == POLARITY_REV) &&
08768          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08769          /* Added log_debug information below to provide a better indication of what is going on */
08770          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08771 
08772          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08773             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08774             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08775             p->polarity = POLARITY_IDLE;
08776          } else
08777             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08778 
08779       } else {
08780          p->polarity = POLARITY_IDLE;
08781          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08782       }
08783       /* Added more log_debug information below to provide a better indication of what is going on */
08784       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08785       break;
08786    default:
08787       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08788    }
08789    return &p->subs[idx].f;
08790 }
08791 
08792 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08793 {
08794    int res;
08795    int idx;
08796    struct ast_frame *f;
08797    int usedindex = -1;
08798    struct dahdi_pvt *p = ast->tech_pvt;
08799 
08800    idx = dahdi_get_index(ast, p, 1);
08801 
08802    p->subs[idx].f.frametype = AST_FRAME_NULL;
08803    p->subs[idx].f.datalen = 0;
08804    p->subs[idx].f.samples = 0;
08805    p->subs[idx].f.mallocd = 0;
08806    p->subs[idx].f.offset = 0;
08807    p->subs[idx].f.subclass.integer = 0;
08808    p->subs[idx].f.delivery = ast_tv(0,0);
08809    p->subs[idx].f.src = "dahdi_exception";
08810    p->subs[idx].f.data.ptr = NULL;
08811 
08812 
08813    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08814       /* If nobody owns us, absorb the event appropriately, otherwise
08815          we loop indefinitely.  This occurs when, during call waiting, the
08816          other end hangs up our channel so that it no longer exists, but we
08817          have neither FLASH'd nor ONHOOK'd to signify our desire to
08818          change to the other channel. */
08819       if (p->fake_event) {
08820          res = p->fake_event;
08821          p->fake_event = 0;
08822       } else
08823          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08824       /* Switch to real if there is one and this isn't something really silly... */
08825       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08826          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08827          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08828          p->owner = p->subs[SUB_REAL].owner;
08829          if (p->owner && ast_bridged_channel(p->owner))
08830             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08831          p->subs[SUB_REAL].needunhold = 1;
08832       }
08833       switch (res) {
08834       case DAHDI_EVENT_ONHOOK:
08835          dahdi_disable_ec(p);
08836          if (p->owner) {
08837             ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
08838             dahdi_ring_phone(p);
08839             p->callwaitingrepeat = 0;
08840             p->cidcwexpire = 0;
08841             p->cid_suppress_expire = 0;
08842          } else
08843             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08844          update_conf(p);
08845          break;
08846       case DAHDI_EVENT_RINGOFFHOOK:
08847          dahdi_enable_ec(p);
08848          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08849          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08850             p->subs[SUB_REAL].needanswer = 1;
08851             p->dialing = 0;
08852          }
08853          break;
08854       case DAHDI_EVENT_HOOKCOMPLETE:
08855       case DAHDI_EVENT_RINGERON:
08856       case DAHDI_EVENT_RINGEROFF:
08857          /* Do nothing */
08858          break;
08859       case DAHDI_EVENT_WINKFLASH:
08860          p->flashtime = ast_tvnow();
08861          if (p->owner) {
08862             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
08863             if (p->owner->_state != AST_STATE_UP) {
08864                /* Answer if necessary */
08865                usedindex = dahdi_get_index(p->owner, p, 0);
08866                if (usedindex > -1) {
08867                   p->subs[usedindex].needanswer = 1;
08868                }
08869                ast_setstate(p->owner, AST_STATE_UP);
08870             }
08871             p->callwaitingrepeat = 0;
08872             p->cidcwexpire = 0;
08873             p->cid_suppress_expire = 0;
08874             if (ast_bridged_channel(p->owner))
08875                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08876             p->subs[SUB_REAL].needunhold = 1;
08877          } else
08878             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08879          update_conf(p);
08880          break;
08881       default:
08882          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08883       }
08884       f = &p->subs[idx].f;
08885       return f;
08886    }
08887    if (!(p->radio || (p->oprmode < 0)))
08888       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08889    /* If it's not us, return NULL immediately */
08890    if (ast != p->owner) {
08891       ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
08892       f = &p->subs[idx].f;
08893       return f;
08894    }
08895    f = dahdi_handle_event(ast);
08896 
08897    /* tell the cdr this zap device hung up */
08898    if (f == NULL) {
08899       ast_set_hangupsource(ast, ast_channel_name(ast), 0);
08900    }
08901 
08902    return f;
08903 }
08904 
08905 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08906 {
08907    struct dahdi_pvt *p = ast->tech_pvt;
08908    struct ast_frame *f;
08909    ast_mutex_lock(&p->lock);
08910    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08911       struct analog_pvt *analog_p = p->sig_pvt;
08912       f = analog_exception(analog_p, ast);
08913    } else {
08914       f = __dahdi_exception(ast);
08915    }
08916    ast_mutex_unlock(&p->lock);
08917    return f;
08918 }
08919 
08920 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08921 {
08922    struct dahdi_pvt *p;
08923    int res;
08924    int idx;
08925    void *readbuf;
08926    struct ast_frame *f;
08927 
08928    /*
08929     * For analog channels, we must do deadlock avoidance because
08930     * analog ports can have more than one Asterisk channel using
08931     * the same private structure.
08932     */
08933    p = ast->tech_pvt;
08934    while (ast_mutex_trylock(&p->lock)) {
08935       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08936 
08937       /*
08938        * For PRI channels, we must refresh the private pointer because
08939        * the call could move to another B channel while the Asterisk
08940        * channel is unlocked.
08941        */
08942       p = ast->tech_pvt;
08943    }
08944 
08945    idx = dahdi_get_index(ast, p, 0);
08946 
08947    /* Hang up if we don't really exist */
08948    if (idx < 0)   {
08949       ast_log(LOG_WARNING, "We don't exist?\n");
08950       ast_mutex_unlock(&p->lock);
08951       return NULL;
08952    }
08953 
08954    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08955       ast_mutex_unlock(&p->lock);
08956       return NULL;
08957    }
08958 
08959    p->subs[idx].f.frametype = AST_FRAME_NULL;
08960    p->subs[idx].f.datalen = 0;
08961    p->subs[idx].f.samples = 0;
08962    p->subs[idx].f.mallocd = 0;
08963    p->subs[idx].f.offset = 0;
08964    p->subs[idx].f.subclass.integer = 0;
08965    p->subs[idx].f.delivery = ast_tv(0,0);
08966    p->subs[idx].f.src = "dahdi_read";
08967    p->subs[idx].f.data.ptr = NULL;
08968 
08969    /* make sure it sends initial key state as first frame */
08970    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08971    {
08972       struct dahdi_params ps;
08973 
08974       memset(&ps, 0, sizeof(ps));
08975       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08976          ast_mutex_unlock(&p->lock);
08977          return NULL;
08978       }
08979       p->firstradio = 1;
08980       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08981       if (ps.rxisoffhook)
08982       {
08983          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08984       }
08985       else
08986       {
08987          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08988       }
08989       ast_mutex_unlock(&p->lock);
08990       return &p->subs[idx].f;
08991    }
08992    if (p->ringt > 0) {
08993       if (!(--p->ringt)) {
08994          ast_mutex_unlock(&p->lock);
08995          return NULL;
08996       }
08997    }
08998 
08999 #ifdef HAVE_OPENR2
09000    if (p->mfcr2) {
09001       openr2_chan_process_event(p->r2chan);
09002       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09003          struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09004          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09005           * now enqueue a progress frame to bridge the media up */
09006          if (p->mfcr2_call_accepted &&
09007             !p->mfcr2_progress_sent && 
09008             ast->_state == AST_STATE_RINGING) {
09009             ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09010             ast_queue_frame(p->owner, &fr);
09011             p->mfcr2_progress_sent = 1;
09012          }
09013       }
09014    }
09015 #endif
09016 
09017    if (p->subs[idx].needringing) {
09018       /* Send ringing frame if requested */
09019       p->subs[idx].needringing = 0;
09020       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09021       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09022       ast_setstate(ast, AST_STATE_RINGING);
09023       ast_mutex_unlock(&p->lock);
09024       return &p->subs[idx].f;
09025    }
09026 
09027    if (p->subs[idx].needbusy) {
09028       /* Send busy frame if requested */
09029       p->subs[idx].needbusy = 0;
09030       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09031       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09032       ast_mutex_unlock(&p->lock);
09033       return &p->subs[idx].f;
09034    }
09035 
09036    if (p->subs[idx].needcongestion) {
09037       /* Send congestion frame if requested */
09038       p->subs[idx].needcongestion = 0;
09039       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09040       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09041       ast_mutex_unlock(&p->lock);
09042       return &p->subs[idx].f;
09043    }
09044 
09045    if (p->subs[idx].needanswer) {
09046       /* Send answer frame if requested */
09047       p->subs[idx].needanswer = 0;
09048       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09049       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09050       ast_mutex_unlock(&p->lock);
09051       return &p->subs[idx].f;
09052    }
09053 #ifdef HAVE_OPENR2
09054    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09055       /* openr2 took care of reading and handling any event
09056         (needanswer, needbusy etc), if we continue we will read()
09057         twice, lets just return a null frame. This should only
09058         happen when openr2 is dialing out */
09059       ast_mutex_unlock(&p->lock);
09060       return &ast_null_frame;
09061    }
09062 #endif
09063 
09064    if (p->subs[idx].needflash) {
09065       /* Send answer frame if requested */
09066       p->subs[idx].needflash = 0;
09067       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09069       ast_mutex_unlock(&p->lock);
09070       return &p->subs[idx].f;
09071    }
09072 
09073    if (p->subs[idx].needhold) {
09074       /* Send answer frame if requested */
09075       p->subs[idx].needhold = 0;
09076       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09077       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09078       ast_mutex_unlock(&p->lock);
09079       ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09080       return &p->subs[idx].f;
09081    }
09082 
09083    if (p->subs[idx].needunhold) {
09084       /* Send answer frame if requested */
09085       p->subs[idx].needunhold = 0;
09086       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09087       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09088       ast_mutex_unlock(&p->lock);
09089       ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09090       return &p->subs[idx].f;
09091    }
09092 
09093    /*
09094     * If we have a fake_event, fake an exception to handle it only
09095     * if this channel owns the private.
09096     */
09097    if (p->fake_event && p->owner == ast) {
09098       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09099          struct analog_pvt *analog_p = p->sig_pvt;
09100 
09101          f = analog_exception(analog_p, ast);
09102       } else {
09103          f = __dahdi_exception(ast);
09104       }
09105       ast_mutex_unlock(&p->lock);
09106       return f;
09107    }
09108 
09109    if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) {
09110       if (!p->subs[idx].linear) {
09111          p->subs[idx].linear = 1;
09112          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09113          if (res)
09114             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09115       }
09116    } else if ((ast->rawreadformat.id == AST_FORMAT_ULAW) ||
09117       (ast->rawreadformat.id == AST_FORMAT_ALAW)) {
09118       if (p->subs[idx].linear) {
09119          p->subs[idx].linear = 0;
09120          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09121          if (res)
09122             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09123       }
09124    } else {
09125       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(&ast->rawreadformat));
09126       ast_mutex_unlock(&p->lock);
09127       return NULL;
09128    }
09129    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09130    CHECK_BLOCKING(ast);
09131    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09132    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09133    /* Check for hangup */
09134    if (res < 0) {
09135       f = NULL;
09136       if (res == -1) {
09137          if (errno == EAGAIN) {
09138             /* Return "NULL" frame if there is nobody there */
09139             ast_mutex_unlock(&p->lock);
09140             return &p->subs[idx].f;
09141          } else if (errno == ELAST) {
09142             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09143                struct analog_pvt *analog_p = p->sig_pvt;
09144                f = analog_exception(analog_p, ast);
09145             } else {
09146                f = __dahdi_exception(ast);
09147             }
09148          } else
09149             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09150       }
09151       ast_mutex_unlock(&p->lock);
09152       return f;
09153    }
09154    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09155       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09156       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09157          struct analog_pvt *analog_p = p->sig_pvt;
09158          f = analog_exception(analog_p, ast);
09159       } else {
09160          f = __dahdi_exception(ast);
09161       }
09162       ast_mutex_unlock(&p->lock);
09163       return f;
09164    }
09165    if (p->tdd) { /* if in TDD mode, see if we receive that */
09166       int c;
09167 
09168       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09169       if (c < 0) {
09170          ast_debug(1,"tdd_feed failed\n");
09171          ast_mutex_unlock(&p->lock);
09172          return NULL;
09173       }
09174       if (c) { /* if a char to return */
09175          p->subs[idx].f.subclass.integer = 0;
09176          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09177          p->subs[idx].f.mallocd = 0;
09178          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09179          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09180          p->subs[idx].f.datalen = 1;
09181          *((char *) p->subs[idx].f.data.ptr) = c;
09182          ast_mutex_unlock(&p->lock);
09183          return &p->subs[idx].f;
09184       }
09185    }
09186    if (idx == SUB_REAL) {
09187       /* Ensure the CW timers decrement only on a single subchannel */
09188       if (p->cidcwexpire) {
09189          if (!--p->cidcwexpire) {
09190             /* Expired CID/CW */
09191             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09192             restore_conference(p);
09193          }
09194       }
09195       if (p->cid_suppress_expire) {
09196          --p->cid_suppress_expire;
09197       }
09198       if (p->callwaitingrepeat) {
09199          if (!--p->callwaitingrepeat) {
09200             /* Expired, Repeat callwaiting tone */
09201             ++p->callwaitrings;
09202             dahdi_callwait(ast);
09203          }
09204       }
09205    }
09206    if (p->subs[idx].linear) {
09207       p->subs[idx].f.datalen = READ_SIZE * 2;
09208    } else
09209       p->subs[idx].f.datalen = READ_SIZE;
09210 
09211    /* Handle CallerID Transmission */
09212    if ((p->owner == ast) && p->cidspill) {
09213       send_callerid(p);
09214    }
09215 
09216    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09217    ast_format_copy(&p->subs[idx].f.subclass.format, &ast->rawreadformat);
09218    p->subs[idx].f.samples = READ_SIZE;
09219    p->subs[idx].f.mallocd = 0;
09220    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09221    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09222 #if 0
09223    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09224 #endif
09225    if (p->dialing ||  p->radio || /* Transmitting something */
09226       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09227       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09228       ) {
09229       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09230          don't send anything */
09231       p->subs[idx].f.frametype = AST_FRAME_NULL;
09232       p->subs[idx].f.subclass.integer = 0;
09233       p->subs[idx].f.samples = 0;
09234       p->subs[idx].f.mallocd = 0;
09235       p->subs[idx].f.offset = 0;
09236       p->subs[idx].f.data.ptr = NULL;
09237       p->subs[idx].f.datalen= 0;
09238    }
09239    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09240       /* Perform busy detection etc on the dahdi line */
09241       int mute;
09242 
09243       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09244 
09245       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09246       mute = ast_dsp_was_muted(p->dsp);
09247       if (p->muting != mute) {
09248          p->muting = mute;
09249          dahdi_confmute(p, mute);
09250       }
09251 
09252       if (f) {
09253          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09254             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09255                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09256                   a busy */
09257                f = NULL;
09258             }
09259          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09260             || f->frametype == AST_FRAME_DTMF_END) {
09261 #ifdef HAVE_PRI
09262             if (dahdi_sig_pri_lib_handles(p->sig)
09263                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09264                && p->pri
09265                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09266                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09267                /* Don't accept in-band DTMF when in overlap dial mode */
09268                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09269                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09270                   f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09271 
09272                f->frametype = AST_FRAME_NULL;
09273                f->subclass.integer = 0;
09274             }
09275 #endif
09276             /* DSP clears us of being pulse */
09277             p->pulsedial = 0;
09278          } else if (p->waitingfordt.tv_sec) {
09279             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09280                p->waitingfordt.tv_sec = 0;
09281                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09282                f=NULL;
09283             } else if (f->frametype == AST_FRAME_VOICE) {
09284                f->frametype = AST_FRAME_NULL;
09285                f->subclass.integer = 0;
09286                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) {
09287                   p->waitingfordt.tv_sec = 0;
09288                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09289                   ast_dsp_set_features(p->dsp, p->dsp_features);
09290                   ast_debug(1, "Got 10 samples of dialtone!\n");
09291                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09292                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09293                      if (res < 0) {
09294                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09295                         p->dop.dialstr[0] = '\0';
09296                         ast_mutex_unlock(&p->lock);
09297                         return NULL;
09298                      } else {
09299                         ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09300                         p->dialing = 1;
09301                         p->dop.dialstr[0] = '\0';
09302                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09303                         ast_setstate(ast, AST_STATE_DIALING);
09304                      }
09305                   }
09306                }
09307             }
09308          }
09309       }
09310    } else
09311       f = &p->subs[idx].f;
09312 
09313    if (f) {
09314       switch (f->frametype) {
09315       case AST_FRAME_DTMF_BEGIN:
09316       case AST_FRAME_DTMF_END:
09317          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09318             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09319          } else {
09320             dahdi_handle_dtmf(ast, idx, &f);
09321          }
09322          break;
09323       case AST_FRAME_VOICE:
09324          if (p->cidspill || p->cid_suppress_expire) {
09325             /* We are/were sending a caller id spill.  Suppress any echo. */
09326             p->subs[idx].f.frametype = AST_FRAME_NULL;
09327             p->subs[idx].f.subclass.integer = 0;
09328             p->subs[idx].f.samples = 0;
09329             p->subs[idx].f.mallocd = 0;
09330             p->subs[idx].f.offset = 0;
09331             p->subs[idx].f.data.ptr = NULL;
09332             p->subs[idx].f.datalen= 0;
09333          }
09334          break;
09335       default:
09336          break;
09337       }
09338    }
09339 
09340    ast_mutex_unlock(&p->lock);
09341    return f;
09342 }
09343 
09344 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09345 {
09346    int sent=0;
09347    int size;
09348    int res;
09349    int fd;
09350    fd = p->subs[idx].dfd;
09351    while (len) {
09352       size = len;
09353       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09354          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09355       res = write(fd, buf, size);
09356       if (res != size) {
09357          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09358          return sent;
09359       }
09360       len -= size;
09361       buf += size;
09362    }
09363    return sent;
09364 }
09365 
09366 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09367 {
09368    struct dahdi_pvt *p = ast->tech_pvt;
09369    int res;
09370    int idx;
09371    idx = dahdi_get_index(ast, p, 0);
09372    if (idx < 0) {
09373       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09374       return -1;
09375    }
09376 
09377    /* Write a frame of (presumably voice) data */
09378    if (frame->frametype != AST_FRAME_VOICE) {
09379       if (frame->frametype != AST_FRAME_IMAGE)
09380          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09381       return 0;
09382    }
09383    if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09384       (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09385       (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09386       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09387       return -1;
09388    }
09389    if (p->dialing) {
09390       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09391       return 0;
09392    }
09393    if (!p->owner) {
09394       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09395       return 0;
09396    }
09397    if (p->cidspill) {
09398       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09399          ast_channel_name(ast));
09400       return 0;
09401    }
09402    /* Return if it's not valid data */
09403    if (!frame->data.ptr || !frame->datalen)
09404       return 0;
09405 
09406    if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09407       if (!p->subs[idx].linear) {
09408          p->subs[idx].linear = 1;
09409          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09410          if (res)
09411             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09412       }
09413       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09414    } else {
09415       /* x-law already */
09416       if (p->subs[idx].linear) {
09417          p->subs[idx].linear = 0;
09418          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09419          if (res)
09420             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09421       }
09422       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09423    }
09424    if (res < 0) {
09425       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09426       return -1;
09427    }
09428    return 0;
09429 }
09430 
09431 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09432 {
09433    struct dahdi_pvt *p = chan->tech_pvt;
09434    int res=-1;
09435    int idx;
09436    int func = DAHDI_FLASH;
09437 
09438    ast_mutex_lock(&p->lock);
09439    ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09440    switch (p->sig) {
09441 #if defined(HAVE_PRI)
09442    case SIG_PRI_LIB_HANDLE_CASES:
09443       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09444       ast_mutex_unlock(&p->lock);
09445       return res;
09446 #endif   /* defined(HAVE_PRI) */
09447 #if defined(HAVE_SS7)
09448    case SIG_SS7:
09449       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09450       ast_mutex_unlock(&p->lock);
09451       return res;
09452 #endif   /* defined(HAVE_SS7) */
09453    default:
09454       break;
09455    }
09456 #ifdef HAVE_OPENR2
09457    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09458       ast_mutex_unlock(&p->lock);
09459       /* if this is an R2 call and the call is not yet accepted, we don't want the
09460          tone indications to mess up with the MF tones */
09461       return 0;
09462    }
09463 #endif
09464    idx = dahdi_get_index(chan, p, 0);
09465    if (idx == SUB_REAL) {
09466       switch (condition) {
09467       case AST_CONTROL_BUSY:
09468          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09469          break;
09470       case AST_CONTROL_RINGING:
09471          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09472 
09473          if (chan->_state != AST_STATE_UP) {
09474             if ((chan->_state != AST_STATE_RING) ||
09475                ((p->sig != SIG_FXSKS) &&
09476              (p->sig != SIG_FXSLS) &&
09477              (p->sig != SIG_FXSGS)))
09478             ast_setstate(chan, AST_STATE_RINGING);
09479          }
09480          break;
09481       case AST_CONTROL_INCOMPLETE:
09482          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09483          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09484          res = 0;
09485          break;
09486       case AST_CONTROL_PROCEEDING:
09487          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09488          /* don't continue in ast_indicate */
09489          res = 0;
09490          break;
09491       case AST_CONTROL_PROGRESS:
09492          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09493          /* don't continue in ast_indicate */
09494          res = 0;
09495          break;
09496       case AST_CONTROL_CONGESTION:
09497          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09498          switch (chan->hangupcause) {
09499          case AST_CAUSE_USER_BUSY:
09500          case AST_CAUSE_NORMAL_CLEARING:
09501          case 0:/* Cause has not been set. */
09502             /* Supply a more appropriate cause. */
09503             chan->hangupcause = AST_CAUSE_CONGESTION;
09504             break;
09505          default:
09506             break;
09507          }
09508          break;
09509       case AST_CONTROL_HOLD:
09510          ast_moh_start(chan, data, p->mohinterpret);
09511          break;
09512       case AST_CONTROL_UNHOLD:
09513          ast_moh_stop(chan);
09514          break;
09515       case AST_CONTROL_RADIO_KEY:
09516          if (p->radio)
09517             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09518          res = 0;
09519          break;
09520       case AST_CONTROL_RADIO_UNKEY:
09521          if (p->radio)
09522             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09523          res = 0;
09524          break;
09525       case AST_CONTROL_FLASH:
09526          /* flash hookswitch */
09527          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09528             /* Clear out the dial buffer */
09529             p->dop.dialstr[0] = '\0';
09530             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09531                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09532                   ast_channel_name(chan), strerror(errno));
09533             } else
09534                res = 0;
09535          } else
09536             res = 0;
09537          break;
09538       case AST_CONTROL_SRCUPDATE:
09539          res = 0;
09540          break;
09541       case -1:
09542          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09543          break;
09544       }
09545    } else {
09546       res = 0;
09547    }
09548    ast_mutex_unlock(&p->lock);
09549    return res;
09550 }
09551 
09552 #if defined(HAVE_PRI)
09553 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09554 #else
09555 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09556 #endif   /* defined(HAVE_PRI) */
09557 {
09558    struct ast_str *chan_name;
09559    int x, y;
09560 
09561    /* Create the new channel name tail. */
09562    if (!(chan_name = ast_str_create(32))) {
09563       return NULL;
09564    }
09565    if (i->channel == CHAN_PSEUDO) {
09566       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09567 #if defined(HAVE_PRI)
09568    } else if (i->pri) {
09569       ast_mutex_lock(&i->pri->lock);
09570       y = ++i->pri->new_chan_seq;
09571       if (is_outgoing) {
09572          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09573          address[0] = '\0';
09574       } else if (ast_strlen_zero(i->cid_subaddr)) {
09575          /* Put in caller-id number only since there is no subaddress. */
09576          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09577       } else {
09578          /* Put in caller-id number and subaddress. */
09579          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09580             i->cid_subaddr, y);
09581       }
09582       ast_mutex_unlock(&i->pri->lock);
09583 #endif   /* defined(HAVE_PRI) */
09584    } else {
09585       y = 1;
09586       do {
09587          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09588          for (x = 0; x < 3; ++x) {
09589             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09590                ast_channel_name(i->subs[x].owner) + 6)) {
09591                break;
09592             }
09593          }
09594          ++y;
09595       } while (x < 3);
09596    }
09597    return chan_name;
09598 }
09599 
09600 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09601 {
09602    struct ast_channel *tmp;
09603    struct ast_format deflaw;
09604    int x;
09605    int features;
09606    struct ast_str *chan_name;
09607    struct ast_variable *v;
09608    char *dashptr;
09609    char device_name[AST_CHANNEL_NAME];
09610 
09611    if (i->subs[idx].owner) {
09612       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09613       return NULL;
09614    }
09615 
09616    ast_format_clear(&deflaw);
09617 #if defined(HAVE_PRI)
09618    /*
09619     * The dnid has been stuffed with the called-number[:subaddress]
09620     * by dahdi_request() for outgoing calls.
09621     */
09622    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09623 #else
09624    chan_name = create_channel_name(i);
09625 #endif   /* defined(HAVE_PRI) */
09626    if (!chan_name) {
09627       return NULL;
09628    }
09629 
09630    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09631    ast_free(chan_name);
09632    if (!tmp)
09633       return NULL;
09634    tmp->tech = &dahdi_tech;
09635 #if defined(HAVE_PRI)
09636    if (i->pri) {
09637       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09638    }
09639 #endif   /* defined(HAVE_PRI) */
09640    ast_channel_cc_params_init(tmp, i->cc_params);
09641    if (law) {
09642       i->law = law;
09643       if (law == DAHDI_LAW_ALAW) {
09644          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09645       } else {
09646          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09647       }
09648    } else {
09649       switch (i->sig) {
09650       case SIG_PRI_LIB_HANDLE_CASES:
09651          /* Make sure companding law is known. */
09652          i->law = (i->law_default == DAHDI_LAW_ALAW)
09653             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09654          break;
09655       default:
09656          i->law = i->law_default;
09657          break;
09658       }
09659       if (i->law_default == DAHDI_LAW_ALAW) {
09660          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09661       } else {
09662          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09663       }
09664    }
09665    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09666    ast_format_cap_add(tmp->nativeformats, &deflaw);
09667    /* Start out assuming ulaw since it's smaller :) */
09668    ast_format_copy(&tmp->rawreadformat, &deflaw);
09669    ast_format_copy(&tmp->readformat, &deflaw);
09670    ast_format_copy(&tmp->rawwriteformat, &deflaw);
09671    ast_format_copy(&tmp->writeformat, &deflaw);
09672    i->subs[idx].linear = 0;
09673    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09674    features = 0;
09675    if (idx == SUB_REAL) {
09676       if (i->busydetect && CANBUSYDETECT(i))
09677          features |= DSP_FEATURE_BUSY_DETECT;
09678       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09679          features |= DSP_FEATURE_CALL_PROGRESS;
09680       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09681          features |= DSP_FEATURE_WAITDIALTONE;
09682       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09683          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09684          features |= DSP_FEATURE_FAX_DETECT;
09685       }
09686       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09687       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09688          i->hardwaredtmf = 0;
09689          features |= DSP_FEATURE_DIGIT_DETECT;
09690       } else if (NEED_MFDETECT(i)) {
09691          i->hardwaredtmf = 1;
09692          features |= DSP_FEATURE_DIGIT_DETECT;
09693       }
09694    }
09695    if (features) {
09696       if (i->dsp) {
09697          ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09698       } else {
09699          if (i->channel != CHAN_PSEUDO)
09700             i->dsp = ast_dsp_new();
09701          else
09702             i->dsp = NULL;
09703          if (i->dsp) {
09704             i->dsp_features = features;
09705 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09706             /* We cannot do progress detection until receive PROGRESS message */
09707             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09708                /* Remember requested DSP features, don't treat
09709                   talking as ANSWER */
09710                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09711                features = 0;
09712             }
09713 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09714             ast_dsp_set_features(i->dsp, features);
09715             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09716             if (!ast_strlen_zero(progzone))
09717                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09718             if (i->busydetect && CANBUSYDETECT(i)) {
09719                ast_dsp_set_busy_count(i->dsp, i->busycount);
09720                ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09721             }
09722          }
09723       }
09724    }
09725 
09726    if (state == AST_STATE_RING)
09727       tmp->rings = 1;
09728    tmp->tech_pvt = i;
09729    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09730       /* Only FXO signalled stuff can be picked up */
09731       tmp->callgroup = i->callgroup;
09732       tmp->pickupgroup = i->pickupgroup;
09733    }
09734    if (!ast_strlen_zero(i->parkinglot))
09735       ast_channel_parkinglot_set(tmp, i->parkinglot);
09736    if (!ast_strlen_zero(i->language))
09737       ast_channel_language_set(tmp, i->language);
09738    if (!i->owner)
09739       i->owner = tmp;
09740    if (!ast_strlen_zero(i->accountcode))
09741       ast_channel_accountcode_set(tmp, i->accountcode);
09742    if (i->amaflags)
09743       tmp->amaflags = i->amaflags;
09744    i->subs[idx].owner = tmp;
09745    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09746    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09747       ast_channel_call_forward_set(tmp, i->call_forward);
09748    }
09749    /* If we've been told "no ADSI" then enforce it */
09750    if (!i->adsi)
09751       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09752    if (!ast_strlen_zero(i->exten))
09753       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09754    if (!ast_strlen_zero(i->rdnis)) {
09755       tmp->redirecting.from.number.valid = 1;
09756       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09757    }
09758    if (!ast_strlen_zero(i->dnid)) {
09759       tmp->dialed.number.str = ast_strdup(i->dnid);
09760    }
09761 
09762    /* Don't use ast_set_callerid() here because it will
09763     * generate a needless NewCallerID event */
09764 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09765    if (!ast_strlen_zero(i->cid_ani)) {
09766       tmp->caller.ani.number.valid = 1;
09767       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09768    } else if (!ast_strlen_zero(i->cid_num)) {
09769       tmp->caller.ani.number.valid = 1;
09770       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09771    }
09772 #else
09773    if (!ast_strlen_zero(i->cid_num)) {
09774       tmp->caller.ani.number.valid = 1;
09775       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09776    }
09777 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09778    tmp->caller.id.name.presentation = i->callingpres;
09779    tmp->caller.id.number.presentation = i->callingpres;
09780    tmp->caller.id.number.plan = i->cid_ton;
09781    tmp->caller.ani2 = i->cid_ani2;
09782    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09783    /* clear the fake event in case we posted one before we had ast_channel */
09784    i->fake_event = 0;
09785    /* Assure there is no confmute on this channel */
09786    dahdi_confmute(i, 0);
09787    i->muting = 0;
09788    /* Configure the new channel jb */
09789    ast_jb_configure(tmp, &global_jbconf);
09790 
09791    /* Set initial device state */
09792    ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
09793    dashptr = strrchr(device_name, '-');
09794    if (dashptr) {
09795       *dashptr = '\0';
09796    }
09797    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09798 
09799    for (v = i->vars ; v ; v = v->next)
09800       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09801 
09802    ast_module_ref(ast_module_info->self);
09803 
09804    dahdi_ami_channel_event(i, tmp);
09805    if (startpbx) {
09806 #ifdef HAVE_OPENR2
09807       if (i->mfcr2call) {
09808          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09809       }
09810 #endif
09811       if (ast_pbx_start(tmp)) {
09812          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
09813          ast_hangup(tmp);
09814          return NULL;
09815       }
09816    }
09817    return tmp;
09818 }
09819 
09820 
09821 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09822 {
09823    char c;
09824 
09825    *str = 0; /* start with empty output buffer */
09826    for (;;)
09827    {
09828       /* Wait for the first digit (up to specified ms). */
09829       c = ast_waitfordigit(chan, ms);
09830       /* if timeout, hangup or error, return as such */
09831       if (c < 1)
09832          return c;
09833       *str++ = c;
09834       *str = 0;
09835       if (strchr(term, c))
09836          return 1;
09837    }
09838 }
09839 
09840 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09841 {
09842    int j;
09843    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09844    for (;;)
09845    {
09846       /* set bits of interest */
09847       j = DAHDI_IOMUX_SIGEVENT;
09848       /* wait for some happening */
09849       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09850       /* exit loop if we have it */
09851       if (j & DAHDI_IOMUX_SIGEVENT) break;
09852    }
09853    /* get the event info */
09854    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09855    return 0;
09856 }
09857 
09858 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09859  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09860  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09861  *
09862  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09863  * DAHDI channel). Use this to enable or disable it.
09864  *
09865  * \bug the use of the word "channel" for those dahdichans is really confusing.
09866  */
09867 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09868 {
09869    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09870       return analog_dnd(dahdichan->sig_pvt, flag);
09871    }
09872 
09873    if (flag == -1) {
09874       return dahdichan->dnd;
09875    }
09876 
09877    /* Do not disturb */
09878    dahdichan->dnd = flag;
09879    ast_verb(3, "%s DND on channel %d\n",
09880          flag? "Enabled" : "Disabled",
09881          dahdichan->channel);
09882    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09883          "Channel: DAHDI/%d\r\n"
09884          "Status: %s\r\n", dahdichan->channel,
09885          flag? "enabled" : "disabled");
09886 
09887    return 0;
09888 }
09889 
09890 static int canmatch_featurecode(const char *exten)
09891 {
09892    int extlen = strlen(exten);
09893    const char *pickup_ext;
09894    if (!extlen) {
09895       return 1;
09896    }
09897    pickup_ext = ast_pickup_ext();
09898    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09899       return 1;
09900    }
09901    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09902    if (exten[0] == '*' && extlen < 3) {
09903       if (extlen == 1) {
09904          return 1;
09905       }
09906       /* "*0" should be processed before it gets here */
09907       switch (exten[1]) {
09908       case '6':
09909       case '7':
09910       case '8':
09911          return 1;
09912       }
09913    }
09914    return 0;
09915 }
09916 
09917 static void *analog_ss_thread(void *data)
09918 {
09919    struct ast_channel *chan = data;
09920    struct dahdi_pvt *p = chan->tech_pvt;
09921    char exten[AST_MAX_EXTENSION] = "";
09922    char exten2[AST_MAX_EXTENSION] = "";
09923    unsigned char buf[256];
09924    char dtmfcid[300];
09925    char dtmfbuf[300];
09926    struct callerid_state *cs = NULL;
09927    char *name = NULL, *number = NULL;
09928    int distMatches;
09929    int curRingData[3];
09930    int receivedRingT;
09931    int counter1;
09932    int counter;
09933    int samples = 0;
09934    struct ast_smdi_md_message *smdi_msg = NULL;
09935    int flags = 0;
09936    int i;
09937    int timeout;
09938    int getforward = 0;
09939    char *s1, *s2;
09940    int len = 0;
09941    int res;
09942    int idx;
09943    struct ast_format tmpfmt;
09944 
09945    ast_mutex_lock(&ss_thread_lock);
09946    ss_thread_count++;
09947    ast_mutex_unlock(&ss_thread_lock);
09948    /* in the bizarre case where the channel has become a zombie before we
09949       even get started here, abort safely
09950    */
09951    if (!p) {
09952       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
09953       ast_hangup(chan);
09954       goto quit;
09955    }
09956    ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
09957    idx = dahdi_get_index(chan, p, 1);
09958    if (idx < 0) {
09959       ast_log(LOG_WARNING, "Huh?\n");
09960       ast_hangup(chan);
09961       goto quit;
09962    }
09963    if (p->dsp)
09964       ast_dsp_digitreset(p->dsp);
09965    switch (p->sig) {
09966    case SIG_FEATD:
09967    case SIG_FEATDMF:
09968    case SIG_FEATDMF_TA:
09969    case SIG_E911:
09970    case SIG_FGC_CAMAMF:
09971    case SIG_FEATB:
09972    case SIG_EMWINK:
09973    case SIG_SF_FEATD:
09974    case SIG_SF_FEATDMF:
09975    case SIG_SF_FEATB:
09976    case SIG_SFWINK:
09977       if (dahdi_wink(p, idx))
09978          goto quit;
09979       /* Fall through */
09980    case SIG_EM:
09981    case SIG_EM_E1:
09982    case SIG_SF:
09983    case SIG_FGC_CAMA:
09984       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09985       if (p->dsp)
09986          ast_dsp_digitreset(p->dsp);
09987       /* set digit mode appropriately */
09988       if (p->dsp) {
09989          if (NEED_MFDETECT(p))
09990             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09991          else
09992             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09993       }
09994       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09995       /* Wait for the first digit only if immediate=no */
09996       if (!p->immediate)
09997          /* Wait for the first digit (up to 5 seconds). */
09998          res = ast_waitfordigit(chan, 5000);
09999       else
10000          res = 0;
10001       if (res > 0) {
10002          /* save first char */
10003          dtmfbuf[0] = res;
10004          switch (p->sig) {
10005          case SIG_FEATD:
10006          case SIG_SF_FEATD:
10007             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10008             if (res > 0)
10009                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10010             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10011             break;
10012          case SIG_FEATDMF_TA:
10013             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10014             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10015             if (dahdi_wink(p, idx)) goto quit;
10016             dtmfbuf[0] = 0;
10017             /* Wait for the first digit (up to 5 seconds). */
10018             res = ast_waitfordigit(chan, 5000);
10019             if (res <= 0) break;
10020             dtmfbuf[0] = res;
10021             /* fall through intentionally */
10022          case SIG_FEATDMF:
10023          case SIG_E911:
10024          case SIG_FGC_CAMAMF:
10025          case SIG_SF_FEATDMF:
10026             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10027             /* if international caca, do it again to get real ANO */
10028             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10029             {
10030                if (dahdi_wink(p, idx)) goto quit;
10031                dtmfbuf[0] = 0;
10032                /* Wait for the first digit (up to 5 seconds). */
10033                res = ast_waitfordigit(chan, 5000);
10034                if (res <= 0) break;
10035                dtmfbuf[0] = res;
10036                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10037             }
10038             if (res > 0) {
10039                /* if E911, take off hook */
10040                if (p->sig == SIG_E911)
10041                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10042                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10043             }
10044             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10045             break;
10046          case SIG_FEATB:
10047          case SIG_SF_FEATB:
10048             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10049             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10050             break;
10051          case SIG_EMWINK:
10052             /* if we received a '*', we are actually receiving Feature Group D
10053                dial syntax, so use that mode; otherwise, fall through to normal
10054                mode
10055             */
10056             if (res == '*') {
10057                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10058                if (res > 0)
10059                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10060                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10061                break;
10062             }
10063          default:
10064             /* If we got the first digit, get the rest */
10065             len = 1;
10066             dtmfbuf[len] = '\0';
10067             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10068                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10069                   timeout = matchdigittimeout;
10070                } else {
10071                   timeout = gendigittimeout;
10072                }
10073                res = ast_waitfordigit(chan, timeout);
10074                if (res < 0) {
10075                   ast_debug(1, "waitfordigit returned < 0...\n");
10076                   ast_hangup(chan);
10077                   goto quit;
10078                } else if (res) {
10079                   dtmfbuf[len++] = res;
10080                   dtmfbuf[len] = '\0';
10081                } else {
10082                   break;
10083                }
10084             }
10085             break;
10086          }
10087       }
10088       if (res == -1) {
10089          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10090          ast_hangup(chan);
10091          goto quit;
10092       } else if (res < 0) {
10093          ast_debug(1, "Got hung up before digits finished\n");
10094          ast_hangup(chan);
10095          goto quit;
10096       }
10097 
10098       if (p->sig == SIG_FGC_CAMA) {
10099          char anibuf[100];
10100 
10101          if (ast_safe_sleep(chan,1000) == -1) {
10102             ast_hangup(chan);
10103             goto quit;
10104          }
10105          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10106          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10107          res = my_getsigstr(chan, anibuf, "#", 10000);
10108          if ((res > 0) && (strlen(anibuf) > 2)) {
10109             if (anibuf[strlen(anibuf) - 1] == '#')
10110                anibuf[strlen(anibuf) - 1] = 0;
10111             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10112          }
10113          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10114       }
10115 
10116       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10117       if (ast_strlen_zero(exten))
10118          ast_copy_string(exten, "s", sizeof(exten));
10119       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10120          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10121          if (exten[0] == '*') {
10122             char *stringp=NULL;
10123             ast_copy_string(exten2, exten, sizeof(exten2));
10124             /* Parse out extension and callerid */
10125             stringp=exten2 +1;
10126             s1 = strsep(&stringp, "*");
10127             s2 = strsep(&stringp, "*");
10128             if (s2) {
10129                if (!ast_strlen_zero(p->cid_num))
10130                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10131                else
10132                   ast_set_callerid(chan, s1, NULL, s1);
10133                ast_copy_string(exten, s2, sizeof(exten));
10134             } else
10135                ast_copy_string(exten, s1, sizeof(exten));
10136          } else if (p->sig == SIG_FEATD)
10137             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10138       }
10139       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10140          if (exten[0] == '*') {
10141             char *stringp=NULL;
10142             ast_copy_string(exten2, exten, sizeof(exten2));
10143             /* Parse out extension and callerid */
10144             stringp=exten2 +1;
10145             s1 = strsep(&stringp, "#");
10146             s2 = strsep(&stringp, "#");
10147             if (s2) {
10148                if (!ast_strlen_zero(p->cid_num))
10149                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10150                else
10151                   if (*(s1 + 2))
10152                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10153                ast_copy_string(exten, s2 + 1, sizeof(exten));
10154             } else
10155                ast_copy_string(exten, s1 + 2, sizeof(exten));
10156          } else
10157             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10158       }
10159       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10160          if (exten[0] == '*') {
10161             char *stringp=NULL;
10162             ast_copy_string(exten2, exten, sizeof(exten2));
10163             /* Parse out extension and callerid */
10164             stringp=exten2 +1;
10165             s1 = strsep(&stringp, "#");
10166             s2 = strsep(&stringp, "#");
10167             if (s2 && (*(s2 + 1) == '0')) {
10168                if (*(s2 + 2))
10169                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10170             }
10171             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10172             else ast_copy_string(exten, "911", sizeof(exten));
10173          } else
10174             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10175       }
10176       if (p->sig == SIG_FEATB) {
10177          if (exten[0] == '*') {
10178             char *stringp=NULL;
10179             ast_copy_string(exten2, exten, sizeof(exten2));
10180             /* Parse out extension and callerid */
10181             stringp=exten2 +1;
10182             s1 = strsep(&stringp, "#");
10183             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10184          } else
10185             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10186       }
10187       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10188          dahdi_wink(p, idx);
10189          /* some switches require a minimum guard time between
10190             the last FGD wink and something that answers
10191             immediately. This ensures it */
10192          if (ast_safe_sleep(chan, 100)) {
10193             ast_hangup(chan);
10194             goto quit;
10195          }
10196       }
10197       dahdi_enable_ec(p);
10198       if (NEED_MFDETECT(p)) {
10199          if (p->dsp) {
10200             if (!p->hardwaredtmf)
10201                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10202             else {
10203                ast_dsp_free(p->dsp);
10204                p->dsp = NULL;
10205             }
10206          }
10207       }
10208 
10209       if (ast_exists_extension(chan, chan->context, exten, 1,
10210          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10211          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10212          if (p->dsp) ast_dsp_digitreset(p->dsp);
10213          res = ast_pbx_run(chan);
10214          if (res) {
10215             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10216             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10217          }
10218          goto quit;
10219       } else {
10220          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10221          sleep(2);
10222          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10223          if (res < 0)
10224             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10225          else
10226             sleep(1);
10227          res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10228          if (res >= 0)
10229             ast_waitstream(chan, "");
10230          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10231          ast_hangup(chan);
10232          goto quit;
10233       }
10234       break;
10235    case SIG_FXOLS:
10236    case SIG_FXOGS:
10237    case SIG_FXOKS:
10238       /* Read the first digit */
10239       timeout = firstdigittimeout;
10240       /* If starting a threeway call, never timeout on the first digit so someone
10241          can use flash-hook as a "hold" feature */
10242       if (p->subs[SUB_THREEWAY].owner)
10243          timeout = 999999;
10244       while (len < AST_MAX_EXTENSION-1) {
10245          /* Read digit unless it's supposed to be immediate, in which case the
10246             only answer is 's' */
10247          if (p->immediate)
10248             res = 's';
10249          else
10250             res = ast_waitfordigit(chan, timeout);
10251          timeout = 0;
10252          if (res < 0) {
10253             ast_debug(1, "waitfordigit returned < 0...\n");
10254             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10255             ast_hangup(chan);
10256             goto quit;
10257          } else if (res) {
10258             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10259             exten[len++]=res;
10260             exten[len] = '\0';
10261          }
10262          if (!ast_ignore_pattern(chan->context, exten))
10263             tone_zone_play_tone(p->subs[idx].dfd, -1);
10264          else
10265             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10266          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10267             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10268                if (getforward) {
10269                   /* Record this as the forwarding extension */
10270                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10271                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10272                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10273                   if (res)
10274                      break;
10275                   usleep(500000);
10276                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10277                   sleep(1);
10278                   memset(exten, 0, sizeof(exten));
10279                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10280                   len = 0;
10281                   getforward = 0;
10282                } else {
10283                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10284                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10285                   if (!ast_strlen_zero(p->cid_num)) {
10286                      if (!p->hidecallerid)
10287                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10288                      else
10289                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10290                   }
10291                   if (!ast_strlen_zero(p->cid_name)) {
10292                      if (!p->hidecallerid)
10293                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10294                   }
10295                   ast_setstate(chan, AST_STATE_RING);
10296                   dahdi_enable_ec(p);
10297                   res = ast_pbx_run(chan);
10298                   if (res) {
10299                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10300                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10301                   }
10302                   goto quit;
10303                }
10304             } else {
10305                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10306                   so just set the timeout to matchdigittimeout and wait some more */
10307                timeout = matchdigittimeout;
10308             }
10309          } else if (res == 0) {
10310             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10311             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10312             dahdi_wait_event(p->subs[idx].dfd);
10313             ast_hangup(chan);
10314             goto quit;
10315          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10316             ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10317             /* Disable call waiting if enabled */
10318             p->callwaiting = 0;
10319             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10320             if (res) {
10321                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10322                   ast_channel_name(chan), strerror(errno));
10323             }
10324             len = 0;
10325             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10326             memset(exten, 0, sizeof(exten));
10327             timeout = firstdigittimeout;
10328 
10329          } else if (!strcmp(exten,ast_pickup_ext())) {
10330             /* Scan all channels and see if there are any
10331              * ringing channels that have call groups
10332              * that equal this channels pickup group
10333              */
10334             if (idx == SUB_REAL) {
10335                /* Switch us from Third call to Call Wait */
10336                if (p->subs[SUB_THREEWAY].owner) {
10337                   /* If you make a threeway call and the *8# a call, it should actually
10338                      look like a callwait */
10339                   alloc_sub(p, SUB_CALLWAIT);
10340                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10341                   unalloc_sub(p, SUB_THREEWAY);
10342                }
10343                dahdi_enable_ec(p);
10344                if (ast_pickup_call(chan)) {
10345                   ast_debug(1, "No call pickup possible...\n");
10346                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10347                   dahdi_wait_event(p->subs[idx].dfd);
10348                }
10349                ast_hangup(chan);
10350                goto quit;
10351             } else {
10352                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10353                ast_hangup(chan);
10354                goto quit;
10355             }
10356 
10357          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10358             ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10359             /* Disable Caller*ID if enabled */
10360             p->hidecallerid = 1;
10361             ast_party_number_free(&chan->caller.id.number);
10362             ast_party_number_init(&chan->caller.id.number);
10363             ast_party_name_free(&chan->caller.id.name);
10364             ast_party_name_init(&chan->caller.id.name);
10365             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10366             if (res) {
10367                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10368                   ast_channel_name(chan), strerror(errno));
10369             }
10370             len = 0;
10371             memset(exten, 0, sizeof(exten));
10372             timeout = firstdigittimeout;
10373          } else if (p->callreturn && !strcmp(exten, "*69")) {
10374             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10375             break;
10376          } else if (!strcmp(exten, "*78")) {
10377             dahdi_dnd(p, 1);
10378             /* Do not disturb */
10379             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10380             getforward = 0;
10381             memset(exten, 0, sizeof(exten));
10382             len = 0;
10383          } else if (!strcmp(exten, "*79")) {
10384             dahdi_dnd(p, 0);
10385             /* Do not disturb */
10386             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10387             getforward = 0;
10388             memset(exten, 0, sizeof(exten));
10389             len = 0;
10390          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10391             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10392             getforward = 1;
10393             memset(exten, 0, sizeof(exten));
10394             len = 0;
10395          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10396             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10397             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10398             memset(p->call_forward, 0, sizeof(p->call_forward));
10399             getforward = 0;
10400             memset(exten, 0, sizeof(exten));
10401             len = 0;
10402          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10403                   p->subs[SUB_THREEWAY].owner &&
10404                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10405             /* This is a three way call, the main call being a real channel,
10406                and we're parking the first call. */
10407             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10408                chan, exten, chan->context, 0, NULL);
10409             ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10410             break;
10411          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10412             ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10413             /* Enable Caller*ID if enabled */
10414             p->hidecallerid = 0;
10415             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10416             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10417             if (res) {
10418                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10419                   ast_channel_name(chan), strerror(errno));
10420             }
10421             len = 0;
10422             memset(exten, 0, sizeof(exten));
10423             timeout = firstdigittimeout;
10424          } else if (!strcmp(exten, "*0")) {
10425             struct ast_channel *nbridge =
10426                p->subs[SUB_THREEWAY].owner;
10427             struct dahdi_pvt *pbridge = NULL;
10428             /* set up the private struct of the bridged one, if any */
10429             if (nbridge && ast_bridged_channel(nbridge))
10430                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10431             if (nbridge && pbridge &&
10432                (nbridge->tech == &dahdi_tech) &&
10433                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10434                ISTRUNK(pbridge)) {
10435                int func = DAHDI_FLASH;
10436                /* Clear out the dial buffer */
10437                p->dop.dialstr[0] = '\0';
10438                /* flash hookswitch */
10439                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10440                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10441                      ast_channel_name(nbridge), strerror(errno));
10442                }
10443                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10444                unalloc_sub(p, SUB_THREEWAY);
10445                p->owner = p->subs[SUB_REAL].owner;
10446                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10447                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10448                ast_hangup(chan);
10449                goto quit;
10450             } else {
10451                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10452                dahdi_wait_event(p->subs[idx].dfd);
10453                tone_zone_play_tone(p->subs[idx].dfd, -1);
10454                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10455                unalloc_sub(p, SUB_THREEWAY);
10456                p->owner = p->subs[SUB_REAL].owner;
10457                ast_hangup(chan);
10458                goto quit;
10459             }
10460          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10461             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10462             && !canmatch_featurecode(exten)) {
10463             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10464                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10465                chan->context);
10466             break;
10467          }
10468          if (!timeout)
10469             timeout = gendigittimeout;
10470          if (len && !ast_ignore_pattern(chan->context, exten))
10471             tone_zone_play_tone(p->subs[idx].dfd, -1);
10472       }
10473       break;
10474    case SIG_FXSLS:
10475    case SIG_FXSGS:
10476    case SIG_FXSKS:
10477       /* check for SMDI messages */
10478       if (p->use_smdi && p->smdi_iface) {
10479          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10480 
10481          if (smdi_msg != NULL) {
10482             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10483 
10484             if (smdi_msg->type == 'B')
10485                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10486             else if (smdi_msg->type == 'N')
10487                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10488 
10489             ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10490          } else {
10491             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10492          }
10493       }
10494 
10495       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10496          number = smdi_msg->calling_st;
10497 
10498       /* If we want caller id, we're in a prering state due to a polarity reversal
10499        * and we're set to use a polarity reversal to trigger the start of caller id,
10500        * grab the caller id and wait for ringing to start... */
10501       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10502                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10503          /* If set to use DTMF CID signalling, listen for DTMF */
10504          if (p->cid_signalling == CID_SIG_DTMF) {
10505             int k = 0;
10506             cs = NULL;
10507             ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10508             dahdi_setlinear(p->subs[idx].dfd, 0);
10509             /*
10510              * We are the only party interested in the Rx stream since
10511              * we have not answered yet.  We don't need or even want DTMF
10512              * emulation.  The DTMF digits can come so fast that emulation
10513              * can drop some of them.
10514              */
10515             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10516             res = 4000;/* This is a typical OFF time between rings. */
10517             for (;;) {
10518                struct ast_frame *f;
10519                res = ast_waitfor(chan, res);
10520                if (res <= 0) {
10521                   /*
10522                    * We do not need to restore the dahdi_setlinear()
10523                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10524                    * are hanging up the channel.
10525                    */
10526                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10527                      "Exiting simple switch\n");
10528                   ast_hangup(chan);
10529                   goto quit;
10530                }
10531                f = ast_read(chan);
10532                if (!f)
10533                   break;
10534                if (f->frametype == AST_FRAME_DTMF) {
10535                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10536                      dtmfbuf[k++] = f->subclass.integer;
10537                   }
10538                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10539                   res = 4000;/* This is a typical OFF time between rings. */
10540                }
10541                ast_frfree(f);
10542                if (chan->_state == AST_STATE_RING ||
10543                   chan->_state == AST_STATE_RINGING)
10544                   break; /* Got ring */
10545             }
10546             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10547             dtmfbuf[k] = '\0';
10548             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10549             /* Got cid and ring. */
10550             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10551             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10552             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10553             /* If first byte is NULL, we have no cid */
10554             if (!ast_strlen_zero(dtmfcid))
10555                number = dtmfcid;
10556             else
10557                number = NULL;
10558          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10559          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10560             cs = callerid_new(p->cid_signalling);
10561             if (cs) {
10562                samples = 0;
10563 #if 1
10564                bump_gains(p);
10565 #endif
10566                /* Take out of linear mode for Caller*ID processing */
10567                dahdi_setlinear(p->subs[idx].dfd, 0);
10568 
10569                /* First we wait and listen for the Caller*ID */
10570                for (;;) {
10571                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10572                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10573                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10574                      callerid_free(cs);
10575                      ast_hangup(chan);
10576                      goto quit;
10577                   }
10578                   if (i & DAHDI_IOMUX_SIGEVENT) {
10579                      res = dahdi_get_event(p->subs[idx].dfd);
10580                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10581                      if (res == DAHDI_EVENT_NOALARM) {
10582                         p->inalarm = 0;
10583                      }
10584 
10585                      if (p->cid_signalling == CID_SIG_V23_JP) {
10586                         if (res == DAHDI_EVENT_RINGBEGIN) {
10587                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10588                            usleep(1);
10589                         }
10590                      } else {
10591                         res = 0;
10592                         break;
10593                      }
10594                   } else if (i & DAHDI_IOMUX_READ) {
10595                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10596                      if (res < 0) {
10597                         if (errno != ELAST) {
10598                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10599                            callerid_free(cs);
10600                            ast_hangup(chan);
10601                            goto quit;
10602                         }
10603                         break;
10604                      }
10605                      samples += res;
10606 
10607                      if (p->cid_signalling == CID_SIG_V23_JP) {
10608                         res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10609                      } else {
10610                         res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10611                      }
10612                      if (res < 0) {
10613                         /*
10614                          * The previous diagnostic message output likely
10615                          * explains why it failed.
10616                          */
10617                         ast_log(LOG_WARNING,
10618                            "Failed to decode CallerID on channel '%s'\n",
10619                            ast_channel_name(chan));
10620                         break;
10621                      } else if (res)
10622                         break;
10623                      else if (samples > (8000 * 10))
10624                         break;
10625                   }
10626                }
10627                if (res == 1) {
10628                   callerid_get(cs, &name, &number, &flags);
10629                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10630                }
10631 
10632                if (p->cid_signalling == CID_SIG_V23_JP) {
10633                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10634                   usleep(1);
10635                }
10636 
10637                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10638                res = 4000;/* This is a typical OFF time between rings. */
10639                for (;;) {
10640                   struct ast_frame *f;
10641                   res = ast_waitfor(chan, res);
10642                   if (res <= 0) {
10643                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10644                         "Exiting simple switch\n");
10645                      ast_hangup(chan);
10646                      goto quit;
10647                   }
10648                   if (!(f = ast_read(chan))) {
10649                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10650                      ast_hangup(chan);
10651                      goto quit;
10652                   }
10653                   ast_frfree(f);
10654                   if (chan->_state == AST_STATE_RING ||
10655                      chan->_state == AST_STATE_RINGING)
10656                      break; /* Got ring */
10657                }
10658 
10659                /* We must have a ring by now, so, if configured, lets try to listen for
10660                 * distinctive ringing */
10661                if (p->usedistinctiveringdetection) {
10662                   len = 0;
10663                   distMatches = 0;
10664                   /* Clear the current ring data array so we don't have old data in it. */
10665                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10666                      curRingData[receivedRingT] = 0;
10667                   receivedRingT = 0;
10668                   counter = 0;
10669                   counter1 = 0;
10670                   /* Check to see if context is what it should be, if not set to be. */
10671                   if (strcmp(p->context,p->defcontext) != 0) {
10672                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10673                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10674                   }
10675 
10676                   for (;;) {
10677                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10678                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10679                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10680                         callerid_free(cs);
10681                         ast_hangup(chan);
10682                         goto quit;
10683                      }
10684                      if (i & DAHDI_IOMUX_SIGEVENT) {
10685                         res = dahdi_get_event(p->subs[idx].dfd);
10686                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10687                         if (res == DAHDI_EVENT_NOALARM) {
10688                            p->inalarm = 0;
10689                         }
10690                         res = 0;
10691                         /* Let us detect distinctive ring */
10692 
10693                         curRingData[receivedRingT] = p->ringt;
10694 
10695                         if (p->ringt < p->ringt_base/2)
10696                            break;
10697                         /* Increment the ringT counter so we can match it against
10698                            values in chan_dahdi.conf for distinctive ring */
10699                         if (++receivedRingT == ARRAY_LEN(curRingData))
10700                            break;
10701                      } else if (i & DAHDI_IOMUX_READ) {
10702                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10703                         if (res < 0) {
10704                            if (errno != ELAST) {
10705                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10706                               callerid_free(cs);
10707                               ast_hangup(chan);
10708                               goto quit;
10709                            }
10710                            break;
10711                         }
10712                         if (p->ringt > 0) {
10713                            if (!(--p->ringt)) {
10714                               res = -1;
10715                               break;
10716                            }
10717                         }
10718                      }
10719                   }
10720                      /* this only shows up if you have n of the dring patterns filled in */
10721                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10722                   for (counter = 0; counter < 3; counter++) {
10723                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10724                      channel */
10725                      distMatches = 0;
10726                      for (counter1 = 0; counter1 < 3; counter1++) {
10727                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10728                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10729                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10730                            curRingData[counter1]);
10731                            distMatches++;
10732                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10733                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10734                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10735                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10736                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10737                            distMatches++;
10738                         }
10739                      }
10740 
10741                      if (distMatches == 3) {
10742                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10743                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10744                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10745                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10746                         break;
10747                      }
10748                   }
10749                }
10750                /* Restore linear mode (if appropriate) for Caller*ID processing */
10751                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10752 #if 1
10753                restore_gains(p);
10754 #endif
10755             } else
10756                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10757          } else {
10758             ast_log(LOG_WARNING, "Channel %s in prering "
10759                "state, but I have nothing to do. "
10760                "Terminating simple switch, should be "
10761                "restarted by the actual ring.\n",
10762                ast_channel_name(chan));
10763             ast_hangup(chan);
10764             goto quit;
10765          }
10766       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10767          if (p->cid_signalling == CID_SIG_DTMF) {
10768             int k = 0;
10769             cs = NULL;
10770             dahdi_setlinear(p->subs[idx].dfd, 0);
10771             res = 2000;
10772             for (;;) {
10773                struct ast_frame *f;
10774                res = ast_waitfor(chan, res);
10775                if (res <= 0) {
10776                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10777                      "Exiting simple switch\n");
10778                   ast_hangup(chan);
10779                   goto quit;
10780                }
10781                f = ast_read(chan);
10782                if (!f) {
10783                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10784                   ast_hangup(chan);
10785                   goto quit;
10786                }
10787                if (f->frametype == AST_FRAME_DTMF) {
10788                   dtmfbuf[k++] = f->subclass.integer;
10789                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10790                   res = 2000;
10791                }
10792                ast_frfree(f);
10793 
10794                if (p->ringt_base == p->ringt)
10795                   break;
10796             }
10797             dtmfbuf[k] = '\0';
10798             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10799             /* Got cid and ring. */
10800             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10801             ast_debug(1, "CID is '%s', flags %d\n",
10802                dtmfcid, flags);
10803             /* If first byte is NULL, we have no cid */
10804             if (!ast_strlen_zero(dtmfcid))
10805                number = dtmfcid;
10806             else
10807                number = NULL;
10808             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10809          } else {
10810             /* FSK Bell202 callerID */
10811             cs = callerid_new(p->cid_signalling);
10812             if (cs) {
10813 #if 1
10814                bump_gains(p);
10815 #endif
10816                samples = 0;
10817                len = 0;
10818                distMatches = 0;
10819                /* Clear the current ring data array so we don't have old data in it. */
10820                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10821                   curRingData[receivedRingT] = 0;
10822                receivedRingT = 0;
10823                counter = 0;
10824                counter1 = 0;
10825                /* Check to see if context is what it should be, if not set to be. */
10826                if (strcmp(p->context,p->defcontext) != 0) {
10827                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10828                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10829                }
10830 
10831                /* Take out of linear mode for Caller*ID processing */
10832                dahdi_setlinear(p->subs[idx].dfd, 0);
10833                for (;;) {
10834                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10835                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10836                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10837                      callerid_free(cs);
10838                      ast_hangup(chan);
10839                      goto quit;
10840                   }
10841                   if (i & DAHDI_IOMUX_SIGEVENT) {
10842                      res = dahdi_get_event(p->subs[idx].dfd);
10843                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10844                      if (res == DAHDI_EVENT_NOALARM) {
10845                         p->inalarm = 0;
10846                      }
10847                      /* If we get a PR event, they hung up while processing calerid */
10848                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10849                         ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10850                         p->polarity = POLARITY_IDLE;
10851                         callerid_free(cs);
10852                         ast_hangup(chan);
10853                         goto quit;
10854                      }
10855                      res = 0;
10856                      /* Let us detect callerid when the telco uses distinctive ring */
10857 
10858                      curRingData[receivedRingT] = p->ringt;
10859 
10860                      if (p->ringt < p->ringt_base/2)
10861                         break;
10862                      /* Increment the ringT counter so we can match it against
10863                         values in chan_dahdi.conf for distinctive ring */
10864                      if (++receivedRingT == ARRAY_LEN(curRingData))
10865                         break;
10866                   } else if (i & DAHDI_IOMUX_READ) {
10867                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10868                      if (res < 0) {
10869                         if (errno != ELAST) {
10870                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10871                            callerid_free(cs);
10872                            ast_hangup(chan);
10873                            goto quit;
10874                         }
10875                         break;
10876                      }
10877                      if (p->ringt > 0) {
10878                         if (!(--p->ringt)) {
10879                            res = -1;
10880                            break;
10881                         }
10882                      }
10883                      samples += res;
10884                      res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10885                      if (res < 0) {
10886                         /*
10887                          * The previous diagnostic message output likely
10888                          * explains why it failed.
10889                          */
10890                         ast_log(LOG_WARNING,
10891                            "Failed to decode CallerID on channel '%s'\n",
10892                            ast_channel_name(chan));
10893                         break;
10894                      } else if (res)
10895                         break;
10896                      else if (samples > (8000 * 10))
10897                         break;
10898                   }
10899                }
10900                if (res == 1) {
10901                   callerid_get(cs, &name, &number, &flags);
10902                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10903                }
10904                if (distinctiveringaftercid == 1) {
10905                   /* Clear the current ring data array so we don't have old data in it. */
10906                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10907                      curRingData[receivedRingT] = 0;
10908                   }
10909                   receivedRingT = 0;
10910                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10911                   for (;;) {
10912                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10913                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10914                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10915                         callerid_free(cs);
10916                         ast_hangup(chan);
10917                         goto quit;
10918                      }
10919                      if (i & DAHDI_IOMUX_SIGEVENT) {
10920                         res = dahdi_get_event(p->subs[idx].dfd);
10921                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10922                         if (res == DAHDI_EVENT_NOALARM) {
10923                            p->inalarm = 0;
10924                         }
10925                         res = 0;
10926                         /* Let us detect callerid when the telco uses distinctive ring */
10927 
10928                         curRingData[receivedRingT] = p->ringt;
10929 
10930                         if (p->ringt < p->ringt_base/2)
10931                            break;
10932                         /* Increment the ringT counter so we can match it against
10933                            values in chan_dahdi.conf for distinctive ring */
10934                         if (++receivedRingT == ARRAY_LEN(curRingData))
10935                            break;
10936                      } else if (i & DAHDI_IOMUX_READ) {
10937                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10938                         if (res < 0) {
10939                            if (errno != ELAST) {
10940                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10941                               callerid_free(cs);
10942                               ast_hangup(chan);
10943                               goto quit;
10944                            }
10945                            break;
10946                         }
10947                         if (p->ringt > 0) {
10948                            if (!(--p->ringt)) {
10949                               res = -1;
10950                               break;
10951                            }
10952                         }
10953                      }
10954                   }
10955                }
10956                if (p->usedistinctiveringdetection) {
10957                   /* this only shows up if you have n of the dring patterns filled in */
10958                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10959 
10960                   for (counter = 0; counter < 3; counter++) {
10961                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10962                      channel */
10963                      /* this only shows up if you have n of the dring patterns filled in */
10964                      ast_verb(3, "Checking %d,%d,%d\n",
10965                            p->drings.ringnum[counter].ring[0],
10966                            p->drings.ringnum[counter].ring[1],
10967                            p->drings.ringnum[counter].ring[2]);
10968                      distMatches = 0;
10969                      for (counter1 = 0; counter1 < 3; counter1++) {
10970                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10971                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10972                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10973                            curRingData[counter1]);
10974                            distMatches++;
10975                         }
10976                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10977                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10978                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10979                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10980                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10981                            distMatches++;
10982                         }
10983                      }
10984                      if (distMatches == 3) {
10985                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10986                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10987                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10988                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10989                         break;
10990                      }
10991                   }
10992                }
10993                /* Restore linear mode (if appropriate) for Caller*ID processing */
10994                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10995 #if 1
10996                restore_gains(p);
10997 #endif
10998                if (res < 0) {
10999                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11000                }
11001             } else
11002                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11003          }
11004       } else
11005          cs = NULL;
11006 
11007       if (number)
11008          ast_shrink_phone_number(number);
11009       ast_set_callerid(chan, number, name, number);
11010 
11011       if (smdi_msg)
11012          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11013 
11014       if (cs)
11015          callerid_free(cs);
11016 
11017       my_handle_notify_message(chan, p, flags, -1);
11018 
11019       ast_setstate(chan, AST_STATE_RING);
11020       chan->rings = 1;
11021       p->ringt = p->ringt_base;
11022       res = ast_pbx_run(chan);
11023       if (res) {
11024          ast_hangup(chan);
11025          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11026       }
11027       goto quit;
11028    default:
11029       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11030       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11031       if (res < 0)
11032             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11033    }
11034    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11035    if (res < 0)
11036          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11037    ast_hangup(chan);
11038 quit:
11039    ast_mutex_lock(&ss_thread_lock);
11040    ss_thread_count--;
11041    ast_cond_signal(&ss_thread_complete);
11042    ast_mutex_unlock(&ss_thread_lock);
11043    return NULL;
11044 }
11045 
11046 struct mwi_thread_data {
11047    struct dahdi_pvt *pvt;
11048    unsigned char buf[READ_SIZE];
11049    size_t len;
11050 };
11051 
11052 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11053 {
11054    int x;
11055    int sum = 0;
11056 
11057    if (!len)
11058       return 0;
11059 
11060    for (x = 0; x < len; x++)
11061       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11062 
11063    return sum / len;
11064 }
11065 
11066 static void *mwi_thread(void *data)
11067 {
11068    struct mwi_thread_data *mtd = data;
11069    struct callerid_state *cs;
11070    pthread_t threadid;
11071    int samples = 0;
11072    char *name, *number;
11073    int flags;
11074    int i, res;
11075    unsigned int spill_done = 0;
11076    int spill_result = -1;
11077    struct ast_format tmpfmt;
11078 
11079    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11080       mtd->pvt->mwimonitoractive = 0;
11081 
11082       return NULL;
11083    }
11084 
11085    callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11086 
11087    bump_gains(mtd->pvt);
11088 
11089    for (;;) {
11090       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11091       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11092          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11093          goto quit;
11094       }
11095 
11096       if (i & DAHDI_IOMUX_SIGEVENT) {
11097          struct ast_channel *chan;
11098 
11099          /* If we get an event, screen out events that we do not act on.
11100           * Otherwise, cancel and go to the simple switch to let it deal with it.
11101           */
11102          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11103 
11104          switch (res) {
11105          case DAHDI_EVENT_NEONMWI_ACTIVE:
11106          case DAHDI_EVENT_NEONMWI_INACTIVE:
11107          case DAHDI_EVENT_NONE:
11108          case DAHDI_EVENT_BITSCHANGED:
11109             break;
11110          case DAHDI_EVENT_NOALARM:
11111             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11112                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11113 
11114                analog_p->inalarm = 0;
11115             }
11116             mtd->pvt->inalarm = 0;
11117             handle_clear_alarms(mtd->pvt);
11118             break;
11119          case DAHDI_EVENT_ALARM:
11120             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11121                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11122 
11123                analog_p->inalarm = 1;
11124             }
11125             mtd->pvt->inalarm = 1;
11126             res = get_alarms(mtd->pvt);
11127             handle_alarms(mtd->pvt, res);
11128             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11129          default:
11130             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11131             callerid_free(cs);
11132 
11133             restore_gains(mtd->pvt);
11134             mtd->pvt->ringt = mtd->pvt->ringt_base;
11135 
11136             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11137                int result;
11138                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11139                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11140                } else {
11141                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11142                }
11143                if (result) {
11144                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11145                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11146                   if (res < 0)
11147                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11148                   ast_hangup(chan);
11149                   goto quit;
11150                }
11151                goto quit_no_clean;
11152 
11153             } else {
11154                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11155             }
11156          }
11157       } else if (i & DAHDI_IOMUX_READ) {
11158          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11159             if (errno != ELAST) {
11160                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11161                goto quit;
11162             }
11163             break;
11164          }
11165          samples += res;
11166          if (!spill_done) {
11167             if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11168                /*
11169                 * The previous diagnostic message output likely
11170                 * explains why it failed.
11171                 */
11172                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11173                break;
11174             } else if (spill_result) {
11175                spill_done = 1;
11176             }
11177          } else {
11178             /* keep reading data until the energy level drops below the threshold
11179                so we don't get another 'trigger' on the remaining carrier signal
11180             */
11181             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11182                break;
11183          }
11184          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11185             break;
11186       }
11187    }
11188 
11189    if (spill_result == 1) {
11190       callerid_get(cs, &name, &number, &flags);
11191       if (flags & CID_MSGWAITING) {
11192          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11193          notify_message(mtd->pvt->mailbox, 1);
11194       } else if (flags & CID_NOMSGWAITING) {
11195          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11196          notify_message(mtd->pvt->mailbox, 0);
11197       } else {
11198          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11199       }
11200    }
11201 
11202 
11203 quit:
11204    callerid_free(cs);
11205 
11206    restore_gains(mtd->pvt);
11207 
11208 quit_no_clean:
11209    mtd->pvt->mwimonitoractive = 0;
11210 
11211    ast_free(mtd);
11212 
11213    return NULL;
11214 }
11215 
11216 /*
11217 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11218 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11219 * that are sent out via FXS port on voicemail state change.  The execution of
11220 * the mwi send is state driven and can either generate a ring pulse prior to
11221 * sending the fsk spill or simply send an fsk spill.
11222 */
11223 static int mwi_send_init(struct dahdi_pvt * pvt)
11224 {
11225    int x;
11226    struct ast_format tmpfmt;
11227 
11228 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11229    /* Determine how this spill is to be sent */
11230    if (pvt->mwisend_rpas) {
11231       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11232       pvt->mwisendactive = 1;
11233    } else if (pvt->mwisend_fsk) {
11234       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11235       pvt->mwisendactive = 1;
11236    } else {
11237       pvt->mwisendactive = 0;
11238       return 0;
11239    }
11240 #else
11241    if (mwisend_rpas) {
11242       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11243    } else {
11244       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11245    }
11246    pvt->mwisendactive = 1;
11247 #endif
11248 
11249    if (pvt->cidspill) {
11250       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11251       ast_free(pvt->cidspill);
11252       pvt->cidspill = NULL;
11253       pvt->cidpos = 0;
11254       pvt->cidlen = 0;
11255    }
11256    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11257    if (!pvt->cidspill) {
11258       pvt->mwisendactive = 0;
11259       return -1;
11260    }
11261    x = DAHDI_FLUSH_BOTH;
11262    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11263    x = 3000;
11264    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11265 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11266    if (pvt->mwisend_fsk) {
11267 #endif
11268       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11269                       ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11270       pvt->cidpos = 0;
11271 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11272    }
11273 #endif
11274    return 0;
11275 }
11276 
11277 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11278 {
11279    struct timeval    now;
11280    int         res;
11281 
11282    /* sanity check to catch if this had been interrupted previously
11283    *  i.e. state says there is more to do but there is no spill allocated
11284    */
11285    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11286       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11287    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11288       /* Normal processing -- Perform mwi send action */
11289       switch ( pvt->mwisend_data.mwisend_current) {
11290       case MWI_SEND_SA:
11291          /* Send the Ring Pulse Signal Alert */
11292          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11293          if (res) {
11294             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11295             goto quit;
11296          }
11297          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11298          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11299          break;
11300       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11301          break;
11302       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304          if (pvt->mwisend_fsk) {
11305 #endif
11306             gettimeofday(&now, NULL);
11307             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11308                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11309             }
11310 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11311          } else { /* support for mwisendtype=nofsk */
11312             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11313          }
11314 #endif
11315          break;
11316       case MWI_SEND_SPILL:
11317          /* We read some number of bytes.  Write an equal amount of data */
11318          if(0 < num_read) {
11319             if (num_read > pvt->cidlen - pvt->cidpos)
11320                num_read = pvt->cidlen - pvt->cidpos;
11321             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11322             if (res > 0) {
11323                pvt->cidpos += res;
11324                if (pvt->cidpos >= pvt->cidlen) {
11325                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11326                }
11327             } else {
11328                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11329                goto quit;
11330             }
11331          }
11332          break;
11333       case MWI_SEND_CLEANUP:
11334          /* For now, do nothing */
11335          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11336          break;
11337       default:
11338          /* Should not get here, punt*/
11339          goto quit;
11340       }
11341    }
11342 
11343    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11344       if (pvt->cidspill) {
11345          ast_free(pvt->cidspill);
11346          pvt->cidspill = NULL;
11347          pvt->cidpos = 0;
11348          pvt->cidlen = 0;
11349       }
11350       pvt->mwisendactive = 0;
11351    }
11352    return 0;
11353 quit:
11354    if (pvt->cidspill) {
11355       ast_free(pvt->cidspill);
11356       pvt->cidspill = NULL;
11357       pvt->cidpos = 0;
11358       pvt->cidlen = 0;
11359    }
11360    pvt->mwisendactive = 0;
11361    return -1;
11362 }
11363 
11364 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11365 {
11366    int handled = 0;
11367 
11368    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11369       switch (event) {
11370       case DAHDI_EVENT_RINGEROFF:
11371          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11372             handled = 1;
11373 
11374             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11375                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11376                ast_free(pvt->cidspill);
11377                pvt->cidspill = NULL;
11378                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11379                pvt->mwisendactive = 0;
11380             } else {
11381                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11382                gettimeofday(&pvt->mwisend_data.pause, NULL);
11383             }
11384          }
11385          break;
11386       /* Going off hook, I need to punt this spill */
11387       case DAHDI_EVENT_RINGOFFHOOK:
11388          if (pvt->cidspill) {
11389             ast_free(pvt->cidspill);
11390             pvt->cidspill = NULL;
11391             pvt->cidpos = 0;
11392             pvt->cidlen = 0;
11393          }
11394          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11395          pvt->mwisendactive = 0;
11396          break;
11397       case DAHDI_EVENT_RINGERON:
11398       case DAHDI_EVENT_HOOKCOMPLETE:
11399          break;
11400       default:
11401          break;
11402       }
11403    }
11404    return handled;
11405 }
11406 
11407 /* destroy a DAHDI channel, identified by its number */
11408 static int dahdi_destroy_channel_bynum(int channel)
11409 {
11410    struct dahdi_pvt *cur;
11411 
11412    ast_mutex_lock(&iflock);
11413    for (cur = iflist; cur; cur = cur->next) {
11414       if (cur->channel == channel) {
11415          int x = DAHDI_FLASH;
11416 
11417          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11418          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11419 
11420          destroy_channel(cur, 1);
11421          ast_mutex_unlock(&iflock);
11422          ast_module_unref(ast_module_info->self);
11423          return RESULT_SUCCESS;
11424       }
11425    }
11426    ast_mutex_unlock(&iflock);
11427    return RESULT_FAILURE;
11428 }
11429 
11430 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11431 {
11432    int res;
11433    pthread_t threadid;
11434    struct ast_channel *chan;
11435 
11436    /* Handle an event on a given channel for the monitor thread. */
11437 
11438    switch (event) {
11439    case DAHDI_EVENT_NONE:
11440    case DAHDI_EVENT_BITSCHANGED:
11441       break;
11442    case DAHDI_EVENT_WINKFLASH:
11443    case DAHDI_EVENT_RINGOFFHOOK:
11444       if (i->inalarm) break;
11445       if (i->radio) break;
11446       /* Got a ring/answer.  What kind of channel are we? */
11447       switch (i->sig) {
11448       case SIG_FXOLS:
11449       case SIG_FXOGS:
11450       case SIG_FXOKS:
11451          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11452          if (res && (errno == EBUSY))
11453             break;
11454 
11455          /* Cancel VMWI spill */
11456          ast_free(i->cidspill);
11457          i->cidspill = NULL;
11458          restore_conference(i);
11459 
11460          if (i->immediate) {
11461             dahdi_enable_ec(i);
11462             /* The channel is immediately up.  Start right away */
11463             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11464             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11465             if (!chan) {
11466                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11467                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11468                if (res < 0)
11469                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11470             }
11471          } else {
11472             /* Check for callerid, digits, etc */
11473             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11474             if (chan) {
11475                if (has_voicemail(i))
11476                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11477                else
11478                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11479                if (res < 0)
11480                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11481                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11482                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11483                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11484                   if (res < 0)
11485                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11486                   ast_hangup(chan);
11487                }
11488             } else
11489                ast_log(LOG_WARNING, "Unable to create channel\n");
11490          }
11491          break;
11492       case SIG_FXSLS:
11493       case SIG_FXSGS:
11494       case SIG_FXSKS:
11495             i->ringt = i->ringt_base;
11496             /* Fall through */
11497       case SIG_EMWINK:
11498       case SIG_FEATD:
11499       case SIG_FEATDMF:
11500       case SIG_FEATDMF_TA:
11501       case SIG_E911:
11502       case SIG_FGC_CAMA:
11503       case SIG_FGC_CAMAMF:
11504       case SIG_FEATB:
11505       case SIG_EM:
11506       case SIG_EM_E1:
11507       case SIG_SFWINK:
11508       case SIG_SF_FEATD:
11509       case SIG_SF_FEATDMF:
11510       case SIG_SF_FEATB:
11511       case SIG_SF:
11512          /* Check for callerid, digits, etc */
11513          if (i->cid_start == CID_START_POLARITY_IN) {
11514             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11515          } else {
11516             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11517          }
11518 
11519          if (!chan) {
11520             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11521          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11522             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11523             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11524             if (res < 0) {
11525                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11526             }
11527             ast_hangup(chan);
11528          }
11529          break;
11530       default:
11531          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11532          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11533          if (res < 0)
11534             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11535          return NULL;
11536       }
11537       break;
11538    case DAHDI_EVENT_NOALARM:
11539       switch (i->sig) {
11540 #if defined(HAVE_PRI)
11541       case SIG_PRI_LIB_HANDLE_CASES:
11542          ast_mutex_lock(&i->lock);
11543          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11544          ast_mutex_unlock(&i->lock);
11545          break;
11546 #endif   /* defined(HAVE_PRI) */
11547 #if defined(HAVE_SS7)
11548       case SIG_SS7:
11549          sig_ss7_set_alarm(i->sig_pvt, 0);
11550          break;
11551 #endif   /* defined(HAVE_SS7) */
11552       default:
11553          i->inalarm = 0;
11554          break;
11555       }
11556       handle_clear_alarms(i);
11557       break;
11558    case DAHDI_EVENT_ALARM:
11559       switch (i->sig) {
11560 #if defined(HAVE_PRI)
11561       case SIG_PRI_LIB_HANDLE_CASES:
11562          ast_mutex_lock(&i->lock);
11563          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11564          ast_mutex_unlock(&i->lock);
11565          break;
11566 #endif   /* defined(HAVE_PRI) */
11567 #if defined(HAVE_SS7)
11568       case SIG_SS7:
11569          sig_ss7_set_alarm(i->sig_pvt, 1);
11570          break;
11571 #endif   /* defined(HAVE_SS7) */
11572       default:
11573          i->inalarm = 1;
11574          break;
11575       }
11576       res = get_alarms(i);
11577       handle_alarms(i, res);
11578       /* fall thru intentionally */
11579    case DAHDI_EVENT_ONHOOK:
11580       if (i->radio)
11581          break;
11582       /* Back on hook.  Hang up. */
11583       switch (i->sig) {
11584       case SIG_FXOLS:
11585       case SIG_FXOGS:
11586       case SIG_FEATD:
11587       case SIG_FEATDMF:
11588       case SIG_FEATDMF_TA:
11589       case SIG_E911:
11590       case SIG_FGC_CAMA:
11591       case SIG_FGC_CAMAMF:
11592       case SIG_FEATB:
11593       case SIG_EM:
11594       case SIG_EM_E1:
11595       case SIG_EMWINK:
11596       case SIG_SF_FEATD:
11597       case SIG_SF_FEATDMF:
11598       case SIG_SF_FEATB:
11599       case SIG_SF:
11600       case SIG_SFWINK:
11601       case SIG_FXSLS:
11602       case SIG_FXSGS:
11603       case SIG_FXSKS:
11604       case SIG_FXOKS:
11605          dahdi_disable_ec(i);
11606          /* Diddle the battery for the zhone */
11607 #ifdef ZHONE_HACK
11608          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11609          usleep(1);
11610 #endif
11611          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11612          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11613          break;
11614       case SIG_SS7:
11615       case SIG_PRI_LIB_HANDLE_CASES:
11616          dahdi_disable_ec(i);
11617          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11618          break;
11619       default:
11620          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11621          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11622          return NULL;
11623       }
11624       break;
11625    case DAHDI_EVENT_POLARITY:
11626       switch (i->sig) {
11627       case SIG_FXSLS:
11628       case SIG_FXSKS:
11629       case SIG_FXSGS:
11630          /* We have already got a PR before the channel was
11631             created, but it wasn't handled. We need polarity
11632             to be REV for remote hangup detection to work.
11633             At least in Spain */
11634          if (i->hanguponpolarityswitch)
11635             i->polarity = POLARITY_REV;
11636          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11637             i->polarity = POLARITY_REV;
11638             ast_verb(2, "Starting post polarity "
11639                "CID detection on channel %d\n",
11640                i->channel);
11641             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11642             if (!chan) {
11643                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11644             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11645                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11646             }
11647          }
11648          break;
11649       default:
11650          ast_log(LOG_WARNING, "handle_init_event detected "
11651             "polarity reversal on non-FXO (SIG_FXS) "
11652             "interface %d\n", i->channel);
11653       }
11654       break;
11655    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11656       ast_log(LOG_NOTICE,
11657             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11658             i->channel);
11659       return i;
11660    case DAHDI_EVENT_NEONMWI_ACTIVE:
11661       if (i->mwimonitor_neon) {
11662          notify_message(i->mailbox, 1);
11663          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11664       }
11665       break;
11666    case DAHDI_EVENT_NEONMWI_INACTIVE:
11667       if (i->mwimonitor_neon) {
11668          notify_message(i->mailbox, 0);
11669          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11670       }
11671       break;
11672    }
11673    return NULL;
11674 }
11675 
11676 static void *do_monitor(void *data)
11677 {
11678    int count, res, res2, spoint, pollres=0;
11679    struct dahdi_pvt *i;
11680    struct dahdi_pvt *last = NULL;
11681    struct dahdi_pvt *doomed;
11682    time_t thispass = 0, lastpass = 0;
11683    int found;
11684    char buf[1024];
11685    struct pollfd *pfds=NULL;
11686    int lastalloc = -1;
11687    /* This thread monitors all the frame relay interfaces which are not yet in use
11688       (and thus do not have a separate thread) indefinitely */
11689    /* From here on out, we die whenever asked */
11690 #if 0
11691    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11692       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11693       return NULL;
11694    }
11695    ast_debug(1, "Monitor starting...\n");
11696 #endif
11697    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11698 
11699    for (;;) {
11700       /* Lock the interface list */
11701       ast_mutex_lock(&iflock);
11702       if (!pfds || (lastalloc != ifcount)) {
11703          if (pfds) {
11704             ast_free(pfds);
11705             pfds = NULL;
11706          }
11707          if (ifcount) {
11708             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11709                ast_mutex_unlock(&iflock);
11710                return NULL;
11711             }
11712          }
11713          lastalloc = ifcount;
11714       }
11715       /* Build the stuff we're going to poll on, that is the socket of every
11716          dahdi_pvt that does not have an associated owner channel */
11717       count = 0;
11718       for (i = iflist; i; i = i->next) {
11719          ast_mutex_lock(&i->lock);
11720          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11721             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11722                struct analog_pvt *p = i->sig_pvt;
11723 
11724                if (!p)
11725                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11726 
11727                if (!p->owner && !p->subs[SUB_REAL].owner) {
11728                   /* This needs to be watched, as it lacks an owner */
11729                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11730                   pfds[count].events = POLLPRI;
11731                   pfds[count].revents = 0;
11732                   /* Message waiting or r2 channels also get watched for reading */
11733                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11734                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11735                      pfds[count].events |= POLLIN;
11736                   }
11737                   count++;
11738                }
11739             } else {
11740                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11741                   /* This needs to be watched, as it lacks an owner */
11742                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11743                   pfds[count].events = POLLPRI;
11744                   pfds[count].revents = 0;
11745                   /* If we are monitoring for VMWI or sending CID, we need to
11746                      read from the channel as well */
11747                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11748                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11749                      pfds[count].events |= POLLIN;
11750                   }
11751                   count++;
11752                }
11753             }
11754          }
11755          ast_mutex_unlock(&i->lock);
11756       }
11757       /* Okay, now that we know what to do, release the interface lock */
11758       ast_mutex_unlock(&iflock);
11759 
11760       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11761       pthread_testcancel();
11762       /* Wait at least a second for something to happen */
11763       res = poll(pfds, count, 1000);
11764       pthread_testcancel();
11765       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11766 
11767       /* Okay, poll has finished.  Let's see what happened.  */
11768       if (res < 0) {
11769          if ((errno != EAGAIN) && (errno != EINTR))
11770             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11771          continue;
11772       }
11773       /* Alright, lock the interface list again, and let's look and see what has
11774          happened */
11775       ast_mutex_lock(&iflock);
11776       found = 0;
11777       spoint = 0;
11778       lastpass = thispass;
11779       thispass = time(NULL);
11780       doomed = NULL;
11781       for (i = iflist;; i = i->next) {
11782          if (doomed) {
11783             int res;
11784             res = dahdi_destroy_channel_bynum(doomed->channel);
11785             if (res != RESULT_SUCCESS) {
11786                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11787             }
11788             doomed = NULL;
11789          }
11790          if (!i) {
11791             break;
11792          }
11793 
11794          if (thispass != lastpass) {
11795             if (!found && ((i == last) || ((i == iflist) && !last))) {
11796                last = i;
11797                if (last) {
11798                   struct analog_pvt *analog_p = last->sig_pvt;
11799                   /* Only allow MWI to be initiated on a quiescent fxs port */
11800                   if (analog_p
11801                      && !last->mwisendactive
11802                      && (last->sig & __DAHDI_SIG_FXO)
11803                      && !analog_p->fxsoffhookstate
11804                      && !last->owner
11805                      && !ast_strlen_zero(last->mailbox)
11806                      && (thispass - analog_p->onhooktime > 3)) {
11807                      res = has_voicemail(last);
11808                      if (analog_p->msgstate != res) {
11809                         /* Set driver resources for signalling VMWI */
11810                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11811                         if (res2) {
11812                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11813                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11814                         }
11815                         /* If enabled for FSK spill then initiate it */
11816                         if (mwi_send_init(last)) {
11817                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11818                         }
11819                         analog_p->msgstate = res;
11820                         found ++;
11821                      }
11822                   }
11823                   last = last->next;
11824                }
11825             }
11826          }
11827          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11828             if (i->radio && !i->owner)
11829             {
11830                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11831                if (res)
11832                {
11833                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11834                   /* Don't hold iflock while handling init events */
11835                   ast_mutex_unlock(&iflock);
11836                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11837                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11838                   else
11839                      doomed = handle_init_event(i, res);
11840                   ast_mutex_lock(&iflock);
11841                }
11842                continue;
11843             }
11844             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11845             if (pollres & POLLIN) {
11846                if (i->owner || i->subs[SUB_REAL].owner) {
11847 #ifdef HAVE_PRI
11848                   if (!i->pri)
11849 #endif
11850                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11851                   continue;
11852                }
11853                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11854                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11855                   continue;
11856                }
11857                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11858                if (res > 0) {
11859                   if (i->mwimonitor_fsk) {
11860                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11861                         pthread_attr_t attr;
11862                         pthread_t threadid;
11863                         struct mwi_thread_data *mtd;
11864 
11865                         pthread_attr_init(&attr);
11866                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11867 
11868                         ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
11869                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11870                            mtd->pvt = i;
11871                            memcpy(mtd->buf, buf, res);
11872                            mtd->len = res;
11873                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11874                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11875                               ast_free(mtd);
11876                            }
11877                            i->mwimonitoractive = 1;
11878                         }
11879                      }
11880                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11881                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11882                      int energy;
11883                      struct timeval now;
11884                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11885                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11886                      */
11887                      if (1 == i->dtmfcid_holdoff_state) {
11888                         gettimeofday(&i->dtmfcid_delay, NULL);
11889                         i->dtmfcid_holdoff_state = 2;
11890                      } else if (2 == i->dtmfcid_holdoff_state) {
11891                         gettimeofday(&now, NULL);
11892                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11893                            i->dtmfcid_holdoff_state = 0;
11894                         }
11895                      } else {
11896                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11897                         if (!i->mwisendactive && energy > dtmfcid_level) {
11898                            pthread_t threadid;
11899                            struct ast_channel *chan;
11900                            ast_mutex_unlock(&iflock);
11901                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11902                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11903                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11904                               i->dtmfcid_holdoff_state = 1;
11905                            } else {
11906                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11907                               if (!chan) {
11908                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11909                               } else {
11910                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11911                                  if (res) {
11912                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11913                                  } else {
11914                                     i->dtmfcid_holdoff_state = 1;
11915                                  }
11916                               }
11917                            }
11918                            ast_mutex_lock(&iflock);
11919                         }
11920                      }
11921                   }
11922                   if (i->mwisendactive) {
11923                      mwi_send_process_buffer(i, res);
11924                   }
11925                } else {
11926                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11927                }
11928             }
11929             if (pollres & POLLPRI) {
11930                if (i->owner || i->subs[SUB_REAL].owner) {
11931 #ifdef HAVE_PRI
11932                   if (!i->pri)
11933 #endif
11934                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11935                   continue;
11936                }
11937                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11938                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11939                /* Don't hold iflock while handling init events */
11940                ast_mutex_unlock(&iflock);
11941                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11942                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11943                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11944                   else
11945                      doomed = handle_init_event(i, res);
11946                }
11947                ast_mutex_lock(&iflock);
11948             }
11949          }
11950       }
11951       ast_mutex_unlock(&iflock);
11952    }
11953    /* Never reached */
11954    return NULL;
11955 
11956 }
11957 
11958 static int restart_monitor(void)
11959 {
11960    /* If we're supposed to be stopped -- stay stopped */
11961    if (monitor_thread == AST_PTHREADT_STOP)
11962       return 0;
11963    ast_mutex_lock(&monlock);
11964    if (monitor_thread == pthread_self()) {
11965       ast_mutex_unlock(&monlock);
11966       ast_log(LOG_WARNING, "Cannot kill myself\n");
11967       return -1;
11968    }
11969    if (monitor_thread != AST_PTHREADT_NULL) {
11970       /* Wake up the thread */
11971       pthread_kill(monitor_thread, SIGURG);
11972    } else {
11973       /* Start a new monitor */
11974       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11975          ast_mutex_unlock(&monlock);
11976          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11977          return -1;
11978       }
11979    }
11980    ast_mutex_unlock(&monlock);
11981    return 0;
11982 }
11983 
11984 #if defined(HAVE_PRI)
11985 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11986 {
11987    int x;
11988    int trunkgroup;
11989    /* Get appropriate trunk group if there is one */
11990    trunkgroup = pris[*span].mastertrunkgroup;
11991    if (trunkgroup) {
11992       /* Select a specific trunk group */
11993       for (x = 0; x < NUM_SPANS; x++) {
11994          if (pris[x].pri.trunkgroup == trunkgroup) {
11995             *span = x;
11996             return 0;
11997          }
11998       }
11999       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12000       *span = -1;
12001    } else {
12002       if (pris[*span].pri.trunkgroup) {
12003          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
12004          *span = -1;
12005       } else if (pris[*span].mastertrunkgroup) {
12006          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12007          *span = -1;
12008       } else {
12009          if (si->totalchans == 31) {
12010             /* E1 */
12011             pris[*span].dchannels[0] = 16 + offset;
12012          } else if (si->totalchans == 24) {
12013             /* T1 or J1 */
12014             pris[*span].dchannels[0] = 24 + offset;
12015          } else if (si->totalchans == 3) {
12016             /* BRI */
12017             pris[*span].dchannels[0] = 3 + offset;
12018          } else {
12019             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);
12020             *span = -1;
12021             return 0;
12022          }
12023          pris[*span].pri.span = *span + 1;
12024       }
12025    }
12026    return 0;
12027 }
12028 #endif   /* defined(HAVE_PRI) */
12029 
12030 #if defined(HAVE_PRI)
12031 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12032 {
12033    struct dahdi_spaninfo si;
12034    struct dahdi_params p;
12035    int fd;
12036    int span;
12037    int ospan=0;
12038    int x,y;
12039    for (x = 0; x < NUM_SPANS; x++) {
12040       if (pris[x].pri.trunkgroup == trunkgroup) {
12041          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12042          return -1;
12043       }
12044    }
12045    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12046       if (!channels[y])
12047          break;
12048       memset(&si, 0, sizeof(si));
12049       memset(&p, 0, sizeof(p));
12050       fd = open("/dev/dahdi/channel", O_RDWR);
12051       if (fd < 0) {
12052          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12053          return -1;
12054       }
12055       x = channels[y];
12056       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12057          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12058          close(fd);
12059          return -1;
12060       }
12061       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12062          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12063          close(fd);
12064          return -1;
12065       }
12066       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12067          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12068          close(fd);
12069          return -1;
12070       }
12071       span = p.spanno - 1;
12072       if (pris[span].pri.trunkgroup) {
12073          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12074          close(fd);
12075          return -1;
12076       }
12077       if (pris[span].pri.pvts[0]) {
12078          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12079          close(fd);
12080          return -1;
12081       }
12082       if (!y) {
12083          pris[span].pri.trunkgroup = trunkgroup;
12084          ospan = span;
12085       }
12086       pris[ospan].dchannels[y] = channels[y];
12087       pris[span].pri.span = span + 1;
12088       close(fd);
12089    }
12090    return 0;
12091 }
12092 #endif   /* defined(HAVE_PRI) */
12093 
12094 #if defined(HAVE_PRI)
12095 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12096 {
12097    if (pris[span].mastertrunkgroup) {
12098       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);
12099       return -1;
12100    }
12101    pris[span].mastertrunkgroup = trunkgroup;
12102    pris[span].prilogicalspan = logicalspan;
12103    return 0;
12104 }
12105 #endif   /* defined(HAVE_PRI) */
12106 
12107 #if defined(HAVE_SS7)
12108 static unsigned int parse_pointcode(const char *pcstring)
12109 {
12110    unsigned int code1, code2, code3;
12111    int numvals;
12112 
12113    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12114    if (numvals == 1)
12115       return code1;
12116    if (numvals == 3)
12117       return (code1 << 16) | (code2 << 8) | code3;
12118 
12119    return 0;
12120 }
12121 #endif   /* defined(HAVE_SS7) */
12122 
12123 #if defined(HAVE_SS7)
12124 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12125 {
12126    if ((linkset < 0) || (linkset >= NUM_SPANS))
12127       return NULL;
12128    else
12129       return &linksets[linkset - 1];
12130 }
12131 #endif   /* defined(HAVE_SS7) */
12132 
12133 #ifdef HAVE_OPENR2
12134 static void dahdi_r2_destroy_links(void)
12135 {
12136    int i = 0;
12137    if (!r2links) {
12138       return;
12139    }
12140    for (; i < r2links_count; i++) {
12141       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12142          pthread_cancel(r2links[i]->r2master);
12143          pthread_join(r2links[i]->r2master, NULL);
12144          openr2_context_delete(r2links[i]->protocol_context);
12145       }
12146       ast_free(r2links[i]);
12147    }
12148    ast_free(r2links);
12149    r2links = NULL;
12150    r2links_count = 0;
12151 }
12152 
12153 #define R2_LINK_CAPACITY 10
12154 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12155 {
12156    struct dahdi_mfcr2 *new_r2link = NULL;
12157    struct dahdi_mfcr2 **new_r2links = NULL;
12158    /* this function is called just when starting up and no monitor threads have been launched,
12159       no need to lock monitored_count member */
12160    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12161       new_r2link = ast_calloc(1, sizeof(**r2links));
12162       if (!new_r2link) {
12163          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12164          return NULL;
12165       }
12166       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12167       if (!new_r2links) {
12168          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12169          ast_free(new_r2link);
12170          return NULL;
12171       }
12172       r2links = new_r2links;
12173       new_r2link->r2master = AST_PTHREADT_NULL;
12174       r2links[r2links_count] = new_r2link;
12175       r2links_count++;
12176       ast_debug(1, "Created new R2 link!\n");
12177    }
12178    return r2links[r2links_count - 1];
12179 }
12180 
12181 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12182 {
12183    char tmplogdir[] = "/tmp";
12184    char logdir[OR2_MAX_PATH];
12185    int threshold = 0;
12186    int snres = 0;
12187    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12188          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12189          conf->mfcr2.max_dnis);
12190    if (!r2_link->protocol_context) {
12191       return -1;
12192    }
12193    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12194    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12195 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12196    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12197 #endif
12198    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12199    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12200    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12201    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12202    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12203 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12204    openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12205    openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12206 #endif
12207 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12208    openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12209 #endif
12210    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12211       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12212          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12213       }
12214    } else {
12215       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12216       if (snres >= sizeof(logdir)) {
12217          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12218          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12219             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12220          }
12221       } else {
12222          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12223             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12224          }
12225       }
12226    }
12227    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12228       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12229          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12230       }
12231    }
12232    r2_link->monitored_count = 0;
12233    return 0;
12234 }
12235 #endif
12236 
12237 /* converts a DAHDI sigtype to signalling as can be configured from
12238  * chan_dahdi.conf.
12239  * While both have basically the same values, this will later be the
12240  * place to add filters and sanity checks
12241  */
12242 static int sigtype_to_signalling(int sigtype)
12243 {
12244    return sigtype;
12245 }
12246 
12247 /*!
12248  * \internal
12249  * \brief Get file name and channel number from (subdir,number)
12250  *
12251  * \param subdir name of the subdirectory under /dev/dahdi/
12252  * \param channel name of device file under /dev/dahdi/<subdir>/
12253  * \param path buffer to put file name in
12254  * \param pathlen maximal length of path
12255  *
12256  * \retval minor number of dahdi channel.
12257  * \retval -errno on error.
12258  */
12259 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12260 {
12261    struct stat stbuf;
12262    int      num;
12263 
12264    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12265    if (stat(path, &stbuf) < 0) {
12266       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12267       return -errno;
12268    }
12269    if (!S_ISCHR(stbuf.st_mode)) {
12270       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12271       return -EINVAL;
12272    }
12273    num = minor(stbuf.st_rdev);
12274    ast_debug(1, "%s -> %d\n", path, num);
12275    return num;
12276 
12277 }
12278 
12279 /*!
12280  * \internal
12281  * \brief Initialize/create a channel interface.
12282  *
12283  * \param channel Channel interface number to initialize/create.
12284  * \param conf Configuration parameters to initialize interface with.
12285  * \param reloading What we are doing now:
12286  * 0 - initial module load,
12287  * 1 - module reload,
12288  * 2 - module restart
12289  *
12290  * \retval Interface-pointer initialized/created
12291  * \retval NULL if error
12292  */
12293 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12294 {
12295    /* Make a dahdi_pvt structure for this interface */
12296    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12297    char fn[80];
12298    struct dahdi_bufferinfo bi;
12299 
12300    int res;
12301 #if defined(HAVE_PRI)
12302    int span = 0;
12303 #endif   /* defined(HAVE_PRI) */
12304    int here = 0;/*!< TRUE if the channel interface already exists. */
12305    int x;
12306    struct analog_pvt *analog_p = NULL;
12307    struct dahdi_params p;
12308 #if defined(HAVE_PRI)
12309    struct dahdi_spaninfo si;
12310    struct sig_pri_chan *pri_chan = NULL;
12311 #endif   /* defined(HAVE_PRI) */
12312 #if defined(HAVE_SS7)
12313    struct sig_ss7_chan *ss7_chan = NULL;
12314 #endif   /* defined(HAVE_SS7) */
12315 
12316    /* Search channel interface list to see if it already exists. */
12317    for (tmp = iflist; tmp; tmp = tmp->next) {
12318       if (!tmp->destroy) {
12319          if (tmp->channel == channel) {
12320             /* The channel interface already exists. */
12321             here = 1;
12322             break;
12323          }
12324          if (tmp->channel > channel) {
12325             /* No way it can be in the sorted list. */
12326             tmp = NULL;
12327             break;
12328          }
12329       }
12330    }
12331 
12332    if (!here && reloading != 1) {
12333       tmp = ast_calloc(1, sizeof(*tmp));
12334       if (!tmp) {
12335          return NULL;
12336       }
12337       tmp->cc_params = ast_cc_config_params_init();
12338       if (!tmp->cc_params) {
12339          ast_free(tmp);
12340          return NULL;
12341       }
12342       ast_mutex_init(&tmp->lock);
12343       ifcount++;
12344       for (x = 0; x < 3; x++)
12345          tmp->subs[x].dfd = -1;
12346       tmp->channel = channel;
12347       tmp->priindication_oob = conf->chan.priindication_oob;
12348    }
12349 
12350    if (tmp) {
12351       int chan_sig = conf->chan.sig;
12352 
12353       /* If there are variables in tmp before it is updated to match the new config, clear them */
12354       if (reloading && tmp->vars) {
12355          ast_variables_destroy(tmp->vars);
12356          tmp->vars = NULL;
12357       }
12358 
12359       if (!here) {
12360          /* Can only get here if this is a new channel interface being created. */
12361          if ((channel != CHAN_PSEUDO)) {
12362             int count = 0;
12363 
12364             snprintf(fn, sizeof(fn), "%d", channel);
12365             /* Open non-blocking */
12366             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12367             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 */
12368                usleep(1);
12369                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12370                count++;
12371             }
12372             /* Allocate a DAHDI structure */
12373             if (tmp->subs[SUB_REAL].dfd < 0) {
12374                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);
12375                destroy_dahdi_pvt(tmp);
12376                return NULL;
12377             }
12378             memset(&p, 0, sizeof(p));
12379             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12380             if (res < 0) {
12381                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12382                destroy_dahdi_pvt(tmp);
12383                return NULL;
12384             }
12385             if (conf->is_sig_auto)
12386                chan_sig = sigtype_to_signalling(p.sigtype);
12387             if (p.sigtype != (chan_sig & 0x3ffff)) {
12388                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));
12389                destroy_dahdi_pvt(tmp);
12390                return NULL;
12391             }
12392             tmp->law_default = p.curlaw;
12393             tmp->law = p.curlaw;
12394             tmp->span = p.spanno;
12395 #if defined(HAVE_PRI)
12396             span = p.spanno - 1;
12397 #endif   /* defined(HAVE_PRI) */
12398          } else {
12399             chan_sig = 0;
12400          }
12401          tmp->sig = chan_sig;
12402          tmp->outsigmod = conf->chan.outsigmod;
12403 
12404          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12405             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12406             if (!analog_p) {
12407                destroy_dahdi_pvt(tmp);
12408                return NULL;
12409             }
12410             tmp->sig_pvt = analog_p;
12411          }
12412 #if defined(HAVE_SS7)
12413          if (chan_sig == SIG_SS7) {
12414             struct dahdi_ss7 *ss7;
12415             int clear = 0;
12416 
12417             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12418                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12419                destroy_dahdi_pvt(tmp);
12420                return NULL;
12421             }
12422 
12423             ss7 = ss7_resolve_linkset(cur_linkset);
12424             if (!ss7) {
12425                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12426                destroy_dahdi_pvt(tmp);
12427                return NULL;
12428             }
12429             ss7->ss7.span = cur_linkset;
12430             if (cur_cicbeginswith < 0) {
12431                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12432                destroy_dahdi_pvt(tmp);
12433                return NULL;
12434             }
12435             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12436             if (!ss7_chan) {
12437                destroy_dahdi_pvt(tmp);
12438                return NULL;
12439             }
12440             tmp->sig_pvt = ss7_chan;
12441             tmp->ss7 = &ss7->ss7;
12442 
12443             ss7_chan->channel = tmp->channel;
12444             ss7_chan->cic = cur_cicbeginswith++;
12445 
12446             /* DB: Add CIC's DPC information */
12447             ss7_chan->dpc = cur_defaultdpc;
12448 
12449             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12450 
12451             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12452             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12453             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12454             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12455 
12456             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12457             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12458          }
12459 #endif   /* defined(HAVE_SS7) */
12460 #ifdef HAVE_OPENR2
12461          if (chan_sig == SIG_MFCR2) {
12462             struct dahdi_mfcr2 *r2_link;
12463             r2_link = dahdi_r2_get_link();
12464             if (!r2_link) {
12465                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12466                destroy_dahdi_pvt(tmp);
12467                return NULL;
12468             }
12469             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12470                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12471                destroy_dahdi_pvt(tmp);
12472                return NULL;
12473             }
12474             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12475                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12476                destroy_dahdi_pvt(tmp);
12477                return NULL;
12478             }
12479             r2_link->pvts[r2_link->numchans++] = tmp;
12480             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12481                                         tmp->subs[SUB_REAL].dfd,
12482                                         NULL, NULL);
12483             if (!tmp->r2chan) {
12484                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12485                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12486                destroy_dahdi_pvt(tmp);
12487                return NULL;
12488             }
12489             tmp->mfcr2 = r2_link;
12490             if (conf->mfcr2.call_files) {
12491                openr2_chan_enable_call_files(tmp->r2chan);
12492             }
12493             openr2_chan_set_client_data(tmp->r2chan, tmp);
12494             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12495             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12496             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12497             tmp->mfcr2_category = conf->mfcr2.category;
12498             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12499             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12500             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12501             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12502             tmp->mfcr2call = 0;
12503             tmp->mfcr2_dnis_index = 0;
12504             tmp->mfcr2_ani_index = 0;
12505             r2_link->monitored_count++;
12506          }
12507 #endif
12508 #ifdef HAVE_PRI
12509          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12510             int offset;
12511             int matchesdchan;
12512             int x,y;
12513             int myswitchtype = 0;
12514 
12515             offset = 0;
12516             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12517                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12518                destroy_dahdi_pvt(tmp);
12519                return NULL;
12520             }
12521             if (span >= NUM_SPANS) {
12522                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12523                destroy_dahdi_pvt(tmp);
12524                return NULL;
12525             } else {
12526                si.spanno = 0;
12527                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12528                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12529                   destroy_dahdi_pvt(tmp);
12530                   return NULL;
12531                }
12532                /* Store the logical span first based upon the real span */
12533                tmp->logicalspan = pris[span].prilogicalspan;
12534                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12535                if (span < 0) {
12536                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12537                   destroy_dahdi_pvt(tmp);
12538                   return NULL;
12539                }
12540                myswitchtype = conf->pri.pri.switchtype;
12541                /* Make sure this isn't a d-channel */
12542                matchesdchan=0;
12543                for (x = 0; x < NUM_SPANS; x++) {
12544                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12545                      if (pris[x].dchannels[y] == tmp->channel) {
12546                         matchesdchan = 1;
12547                         break;
12548                      }
12549                   }
12550                }
12551                if (!matchesdchan) {
12552                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12553                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12554                      destroy_dahdi_pvt(tmp);
12555                      return NULL;
12556                   }
12557                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12558                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12559                      destroy_dahdi_pvt(tmp);
12560                      return NULL;
12561                   }
12562                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12563                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12564                      destroy_dahdi_pvt(tmp);
12565                      return NULL;
12566                   }
12567                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12568                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12569                      destroy_dahdi_pvt(tmp);
12570                      return NULL;
12571                   }
12572                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12573                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12574                      destroy_dahdi_pvt(tmp);
12575                      return NULL;
12576                   }
12577                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12578                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12579                      destroy_dahdi_pvt(tmp);
12580                      return NULL;
12581                   }
12582                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12583                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12584                      destroy_dahdi_pvt(tmp);
12585                      return NULL;
12586                   }
12587                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12588                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12589                         pris[span].pri.trunkgroup);
12590                      destroy_dahdi_pvt(tmp);
12591                      return NULL;
12592                   }
12593 
12594                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12595                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12596                   if (!pri_chan) {
12597                      destroy_dahdi_pvt(tmp);
12598                      return NULL;
12599                   }
12600                   tmp->sig_pvt = pri_chan;
12601                   tmp->pri = &pris[span].pri;
12602 
12603                   tmp->priexclusive = conf->chan.priexclusive;
12604 
12605                   if (!tmp->pri->cc_params) {
12606                      tmp->pri->cc_params = ast_cc_config_params_init();
12607                      if (!tmp->pri->cc_params) {
12608                         destroy_dahdi_pvt(tmp);
12609                         return NULL;
12610                      }
12611                   }
12612                   ast_cc_copy_config_params(tmp->pri->cc_params,
12613                      conf->chan.cc_params);
12614 
12615                   pris[span].pri.sig = chan_sig;
12616                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12617                   pris[span].pri.switchtype = myswitchtype;
12618                   pris[span].pri.nsf = conf->pri.pri.nsf;
12619                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12620                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12621                   pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12622                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12623                   pris[span].pri.minunused = conf->pri.pri.minunused;
12624                   pris[span].pri.minidle = conf->pri.pri.minidle;
12625                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12626                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12627                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12628 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12629                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12630 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12631 #ifdef HAVE_PRI_INBANDDISCONNECT
12632                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12633 #endif
12634 #if defined(HAVE_PRI_CALL_HOLD)
12635                   pris[span].pri.hold_disconnect_transfer =
12636                      conf->pri.pri.hold_disconnect_transfer;
12637 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12638 #if defined(HAVE_PRI_CCSS)
12639                   pris[span].pri.cc_ptmp_recall_mode =
12640                      conf->pri.pri.cc_ptmp_recall_mode;
12641                   pris[span].pri.cc_qsig_signaling_link_req =
12642                      conf->pri.pri.cc_qsig_signaling_link_req;
12643                   pris[span].pri.cc_qsig_signaling_link_rsp =
12644                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12645 #endif   /* defined(HAVE_PRI_CCSS) */
12646 #if defined(HAVE_PRI_CALL_WAITING)
12647                   pris[span].pri.max_call_waiting_calls =
12648                      conf->pri.pri.max_call_waiting_calls;
12649                   pris[span].pri.allow_call_waiting_calls =
12650                      conf->pri.pri.allow_call_waiting_calls;
12651 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12652                   pris[span].pri.transfer = conf->chan.transfer;
12653                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12654 #if defined(HAVE_PRI_L2_PERSISTENCE)
12655                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12656 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12657 #if defined(HAVE_PRI_AOC_EVENTS)
12658                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12659                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12660 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12661                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12662                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12663                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12664 #if defined(HAVE_PRI_MWI)
12665                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12666                      conf->pri.pri.mwi_mailboxes,
12667                      sizeof(pris[span].pri.mwi_mailboxes));
12668                   ast_copy_string(pris[span].pri.mwi_vm_numbers,
12669                      conf->pri.pri.mwi_vm_numbers,
12670                      sizeof(pris[span].pri.mwi_vm_numbers));
12671 #endif   /* defined(HAVE_PRI_MWI) */
12672                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12673                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12674                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12675                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12676                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12677                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12678                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12679                   pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12680                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12681 #if defined(HAVE_PRI_DISPLAY_TEXT)
12682                   pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12683                   pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12684 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
12685 #if defined(HAVE_PRI_MCID)
12686                   pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12687 #endif   /* defined(HAVE_PRI_MCID) */
12688 #if defined(HAVE_PRI_DATETIME_SEND)
12689                   pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12690 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
12691 
12692                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12693                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12694                   }
12695 
12696 #if defined(HAVE_PRI_CALL_WAITING)
12697                   /* Channel initial config parameters. */
12698                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12699                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12700                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12701                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12702                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12703                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12704                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12705                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12706                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12707                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12708 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12709                } else {
12710                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12711                   destroy_dahdi_pvt(tmp);
12712                   return NULL;
12713                }
12714             }
12715          }
12716 #endif
12717       } else {
12718          /* already exists in interface list */
12719          ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12720          chan_sig = tmp->sig;
12721          if (tmp->subs[SUB_REAL].dfd > -1) {
12722             memset(&p, 0, sizeof(p));
12723             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12724          }
12725       }
12726       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12727       switch (chan_sig) {
12728       case SIG_FXSKS:
12729       case SIG_FXSLS:
12730       case SIG_EM:
12731       case SIG_EM_E1:
12732       case SIG_EMWINK:
12733       case SIG_FEATD:
12734       case SIG_FEATDMF:
12735       case SIG_FEATDMF_TA:
12736       case SIG_FEATB:
12737       case SIG_E911:
12738       case SIG_SF:
12739       case SIG_SFWINK:
12740       case SIG_FGC_CAMA:
12741       case SIG_FGC_CAMAMF:
12742       case SIG_SF_FEATD:
12743       case SIG_SF_FEATDMF:
12744       case SIG_SF_FEATB:
12745          p.starttime = 250;
12746          break;
12747       }
12748 
12749       if (tmp->radio) {
12750          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12751          p.channo = channel;
12752          p.rxwinktime = 1;
12753          p.rxflashtime = 1;
12754          p.starttime = 1;
12755          p.debouncetime = 5;
12756       } else {
12757          p.channo = channel;
12758          /* Override timing settings based on config file */
12759          if (conf->timing.prewinktime >= 0)
12760             p.prewinktime = conf->timing.prewinktime;
12761          if (conf->timing.preflashtime >= 0)
12762             p.preflashtime = conf->timing.preflashtime;
12763          if (conf->timing.winktime >= 0)
12764             p.winktime = conf->timing.winktime;
12765          if (conf->timing.flashtime >= 0)
12766             p.flashtime = conf->timing.flashtime;
12767          if (conf->timing.starttime >= 0)
12768             p.starttime = conf->timing.starttime;
12769          if (conf->timing.rxwinktime >= 0)
12770             p.rxwinktime = conf->timing.rxwinktime;
12771          if (conf->timing.rxflashtime >= 0)
12772             p.rxflashtime = conf->timing.rxflashtime;
12773          if (conf->timing.debouncetime >= 0)
12774             p.debouncetime = conf->timing.debouncetime;
12775       }
12776 
12777       /* don't set parms on a pseudo-channel */
12778       if (tmp->subs[SUB_REAL].dfd >= 0)
12779       {
12780          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12781          if (res < 0) {
12782             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12783             destroy_dahdi_pvt(tmp);
12784             return NULL;
12785          }
12786       }
12787 #if 1
12788       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12789          memset(&bi, 0, sizeof(bi));
12790          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12791          if (!res) {
12792             bi.txbufpolicy = conf->chan.buf_policy;
12793             bi.rxbufpolicy = conf->chan.buf_policy;
12794             bi.numbufs = conf->chan.buf_no;
12795             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12796             if (res < 0) {
12797                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12798             }
12799          } else {
12800             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12801          }
12802          tmp->buf_policy = conf->chan.buf_policy;
12803          tmp->buf_no = conf->chan.buf_no;
12804          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12805          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12806          tmp->faxbuf_no = conf->chan.faxbuf_no;
12807          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12808           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12809           * The reason the ioctl call above failed should to be determined before worrying about the
12810           * faxbuffer-related ioctl calls */
12811          tmp->bufsize = bi.bufsize;
12812       }
12813 #endif
12814       tmp->immediate = conf->chan.immediate;
12815       tmp->transfertobusy = conf->chan.transfertobusy;
12816       if (chan_sig & __DAHDI_SIG_FXS) {
12817          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12818          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12819          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12820       }
12821       tmp->ringt_base = ringt_base;
12822       tmp->firstradio = 0;
12823       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12824          tmp->permcallwaiting = conf->chan.callwaiting;
12825       else
12826          tmp->permcallwaiting = 0;
12827       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12828       tmp->destroy = 0;
12829       tmp->drings = conf->chan.drings;
12830 
12831       /* 10 is a nice default. */
12832       if (tmp->drings.ringnum[0].range == 0)
12833          tmp->drings.ringnum[0].range = 10;
12834       if (tmp->drings.ringnum[1].range == 0)
12835          tmp->drings.ringnum[1].range = 10;
12836       if (tmp->drings.ringnum[2].range == 0)
12837          tmp->drings.ringnum[2].range = 10;
12838 
12839       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12840       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12841       tmp->threewaycalling = conf->chan.threewaycalling;
12842       tmp->adsi = conf->chan.adsi;
12843       tmp->use_smdi = conf->chan.use_smdi;
12844       tmp->permhidecallerid = conf->chan.hidecallerid;
12845       tmp->hidecalleridname = conf->chan.hidecalleridname;
12846       tmp->callreturn = conf->chan.callreturn;
12847       tmp->echocancel = conf->chan.echocancel;
12848       tmp->echotraining = conf->chan.echotraining;
12849       tmp->pulse = conf->chan.pulse;
12850       if (tmp->echocancel.head.tap_length) {
12851          tmp->echocanbridged = conf->chan.echocanbridged;
12852       } else {
12853          if (conf->chan.echocanbridged)
12854             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12855          tmp->echocanbridged = 0;
12856       }
12857       tmp->busydetect = conf->chan.busydetect;
12858       tmp->busycount = conf->chan.busycount;
12859       tmp->busy_cadence = conf->chan.busy_cadence;
12860       tmp->callprogress = conf->chan.callprogress;
12861       tmp->waitfordialtone = conf->chan.waitfordialtone;
12862       tmp->cancallforward = conf->chan.cancallforward;
12863       tmp->dtmfrelax = conf->chan.dtmfrelax;
12864       tmp->callwaiting = tmp->permcallwaiting;
12865       tmp->hidecallerid = tmp->permhidecallerid;
12866       tmp->channel = channel;
12867       tmp->stripmsd = conf->chan.stripmsd;
12868       tmp->use_callerid = conf->chan.use_callerid;
12869       tmp->cid_signalling = conf->chan.cid_signalling;
12870       tmp->cid_start = conf->chan.cid_start;
12871       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12872       tmp->restrictcid = conf->chan.restrictcid;
12873       tmp->use_callingpres = conf->chan.use_callingpres;
12874       if (tmp->usedistinctiveringdetection) {
12875          if (!tmp->use_callerid) {
12876             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12877             tmp->use_callerid = 1;
12878          }
12879       }
12880 
12881       if (tmp->cid_signalling == CID_SIG_SMDI) {
12882          if (!tmp->use_smdi) {
12883             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12884             tmp->use_smdi = 1;
12885          }
12886       }
12887       if (tmp->use_smdi) {
12888          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12889          if (!(tmp->smdi_iface)) {
12890             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12891             tmp->use_smdi = 0;
12892          }
12893       }
12894 
12895       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12896       tmp->amaflags = conf->chan.amaflags;
12897       if (!here) {
12898          tmp->confno = -1;
12899          tmp->propconfno = -1;
12900       }
12901       tmp->canpark = conf->chan.canpark;
12902       tmp->transfer = conf->chan.transfer;
12903       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12904       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12905       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12906       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12907       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12908       ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
12909       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12910       tmp->cid_ton = 0;
12911       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12912          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12913          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12914       } else {
12915          tmp->cid_num[0] = '\0';
12916          tmp->cid_name[0] = '\0';
12917       }
12918 #if defined(HAVE_PRI)
12919       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12920          tmp->cid_tag[0] = '\0';
12921       } else
12922 #endif   /* defined(HAVE_PRI) */
12923       {
12924          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12925       }
12926       tmp->cid_subaddr[0] = '\0';
12927       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12928       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12929          char *mailbox, *context;
12930          mailbox = context = ast_strdupa(tmp->mailbox);
12931          strsep(&context, "@");
12932          if (ast_strlen_zero(context))
12933             context = "default";
12934          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12935             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12936             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12937             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12938             AST_EVENT_IE_END);
12939       }
12940 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12941       tmp->mwisend_setting = conf->chan.mwisend_setting;
12942       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12943       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12944 #endif
12945 
12946       tmp->group = conf->chan.group;
12947       tmp->callgroup = conf->chan.callgroup;
12948       tmp->pickupgroup= conf->chan.pickupgroup;
12949       if (conf->chan.vars) {
12950          struct ast_variable *v, *tmpvar;
12951                    for (v = conf->chan.vars ; v ; v = v->next) {
12952                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12953                                   tmpvar->next = tmp->vars;
12954                                    tmp->vars = tmpvar;
12955                            }
12956                   }
12957       }
12958       tmp->cid_rxgain = conf->chan.cid_rxgain;
12959       tmp->rxgain = conf->chan.rxgain;
12960       tmp->txgain = conf->chan.txgain;
12961       tmp->txdrc = conf->chan.txdrc;
12962       tmp->rxdrc = conf->chan.rxdrc;
12963       tmp->tonezone = conf->chan.tonezone;
12964       if (tmp->subs[SUB_REAL].dfd > -1) {
12965          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12966          if (tmp->dsp)
12967             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12968          update_conf(tmp);
12969          if (!here) {
12970             switch (chan_sig) {
12971             case SIG_PRI_LIB_HANDLE_CASES:
12972             case SIG_SS7:
12973             case SIG_MFCR2:
12974                break;
12975             default:
12976                /* Hang it up to be sure it's good */
12977                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12978                break;
12979             }
12980          }
12981          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12982          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12983             /* the dchannel is down so put the channel in alarm */
12984             switch (tmp->sig) {
12985 #ifdef HAVE_PRI
12986             case SIG_PRI_LIB_HANDLE_CASES:
12987                sig_pri_set_alarm(tmp->sig_pvt, 1);
12988                break;
12989 #endif
12990 #if defined(HAVE_SS7)
12991             case SIG_SS7:
12992                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12993                break;
12994 #endif   /* defined(HAVE_SS7) */
12995             default:
12996                /* The only sig submodule left should be sig_analog. */
12997                analog_p = tmp->sig_pvt;
12998                if (analog_p) {
12999                   analog_p->inalarm = 1;
13000                }
13001                tmp->inalarm = 1;
13002                break;
13003             }
13004             handle_alarms(tmp, res);
13005          }
13006       }
13007 
13008       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13009       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13010       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13011       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13012       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13013 
13014       if (!here) {
13015          tmp->locallyblocked = 0;
13016          tmp->remotelyblocked = 0;
13017          switch (tmp->sig) {
13018 #if defined(HAVE_PRI)
13019          case SIG_PRI_LIB_HANDLE_CASES:
13020             tmp->inservice = 1;/* Inservice until actually implemented. */
13021 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13022             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13023             if (chan_sig == SIG_PRI) {
13024                char db_chan_name[20];
13025                char db_answer[5];
13026 
13027                /*
13028                 * Initialize the active out-of-service status
13029                 * and delete any record if the feature is not enabled.
13030                 */
13031                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13032                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13033                   unsigned *why;
13034 
13035                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13036                   if (tmp->pri->enable_service_message_support) {
13037                      char state;
13038 
13039                      sscanf(db_answer, "%1c:%30u", &state, why);
13040 
13041                      /* Ensure that only the implemented bits could be set.*/
13042                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13043                   }
13044                   if (!*why) {
13045                      ast_db_del(db_chan_name, SRVST_DBKEY);
13046                   }
13047                }
13048             }
13049 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13050             break;
13051 #endif   /* defined(HAVE_PRI) */
13052 #if defined(HAVE_SS7)
13053          case SIG_SS7:
13054             tmp->inservice = 0;
13055             break;
13056 #endif   /* defined(HAVE_SS7) */
13057          default:
13058              /* We default to in service on protocols that don't have a reset */
13059             tmp->inservice = 1;
13060             break;
13061          }
13062       }
13063 
13064       switch (tmp->sig) {
13065 #if defined(HAVE_PRI)
13066       case SIG_PRI_LIB_HANDLE_CASES:
13067          if (pri_chan) {
13068             pri_chan->channel = tmp->channel;
13069             pri_chan->hidecallerid = tmp->hidecallerid;
13070             pri_chan->hidecalleridname = tmp->hidecalleridname;
13071             pri_chan->immediate = tmp->immediate;
13072             pri_chan->inalarm = tmp->inalarm;
13073             pri_chan->priexclusive = tmp->priexclusive;
13074             pri_chan->priindication_oob = tmp->priindication_oob;
13075             pri_chan->use_callerid = tmp->use_callerid;
13076             pri_chan->use_callingpres = tmp->use_callingpres;
13077             ast_copy_string(pri_chan->context, tmp->context,
13078                sizeof(pri_chan->context));
13079             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13080                sizeof(pri_chan->mohinterpret));
13081             pri_chan->stripmsd = tmp->stripmsd;
13082          }
13083          break;
13084 #endif   /* defined(HAVE_PRI) */
13085 #if defined(HAVE_SS7)
13086       case SIG_SS7:
13087          if (ss7_chan) {
13088             ss7_chan->inalarm = tmp->inalarm;
13089 
13090             ss7_chan->stripmsd = tmp->stripmsd;
13091             ss7_chan->hidecallerid = tmp->hidecallerid;
13092             ss7_chan->use_callerid = tmp->use_callerid;
13093             ss7_chan->use_callingpres = tmp->use_callingpres;
13094             ss7_chan->immediate = tmp->immediate;
13095             ss7_chan->locallyblocked = tmp->locallyblocked;
13096             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13097             ast_copy_string(ss7_chan->context, tmp->context,
13098                sizeof(ss7_chan->context));
13099             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13100                sizeof(ss7_chan->mohinterpret));
13101          }
13102          break;
13103 #endif   /* defined(HAVE_SS7) */
13104       default:
13105          /* The only sig submodule left should be sig_analog. */
13106          analog_p = tmp->sig_pvt;
13107          if (analog_p) {
13108             analog_p->channel = tmp->channel;
13109             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13110             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13111             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13112             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13113             analog_p->callreturn = conf->chan.callreturn;
13114             analog_p->cancallforward = conf->chan.cancallforward;
13115             analog_p->canpark = conf->chan.canpark;
13116             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13117             analog_p->immediate = conf->chan.immediate;
13118             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13119             analog_p->pulse = conf->chan.pulse;
13120             analog_p->threewaycalling = conf->chan.threewaycalling;
13121             analog_p->transfer = conf->chan.transfer;
13122             analog_p->transfertobusy = conf->chan.transfertobusy;
13123             analog_p->use_callerid = tmp->use_callerid;
13124             analog_p->use_smdi = tmp->use_smdi;
13125             analog_p->smdi_iface = tmp->smdi_iface;
13126             analog_p->outsigmod = ANALOG_SIG_NONE;
13127             analog_p->echotraining = conf->chan.echotraining;
13128             analog_p->cid_signalling = conf->chan.cid_signalling;
13129             analog_p->stripmsd = conf->chan.stripmsd;
13130             switch (conf->chan.cid_start) {
13131             case CID_START_POLARITY:
13132                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13133                break;
13134             case CID_START_POLARITY_IN:
13135                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13136                break;
13137             case CID_START_DTMF_NOALERT:
13138                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13139                break;
13140             default:
13141                analog_p->cid_start = ANALOG_CID_START_RING;
13142                break;
13143             }
13144             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13145             analog_p->ringt = conf->chan.ringt;
13146             analog_p->ringt_base = ringt_base;
13147             analog_p->chan_tech = &dahdi_tech;
13148             analog_p->onhooktime = time(NULL);
13149             if (chan_sig & __DAHDI_SIG_FXO) {
13150                memset(&p, 0, sizeof(p));
13151                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13152                if (!res) {
13153                   analog_p->fxsoffhookstate = p.rxisoffhook;
13154                }
13155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13156                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13157 #endif
13158             }
13159             analog_p->msgstate = -1;
13160 
13161             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13162             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13163             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13164 
13165             analog_config_complete(analog_p);
13166          }
13167          break;
13168       }
13169 #if defined(HAVE_PRI)
13170       if (tmp->channel == CHAN_PSEUDO) {
13171          /*
13172           * Save off pseudo channel buffer policy values for dynamic creation of
13173           * no B channel interfaces.
13174           */
13175          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13176          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13177          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13178          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13179       }
13180 #endif   /* defined(HAVE_PRI) */
13181    }
13182    if (tmp && !here) {
13183       /* Add the new channel interface to the sorted channel interface list. */
13184       dahdi_iflist_insert(tmp);
13185    }
13186    return tmp;
13187 }
13188 
13189 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13190 {
13191 #if defined(HAVE_PRI)
13192    if (0 < span) {
13193       /* The channel must be on the specified PRI span. */
13194       if (!p->pri || p->pri->span != span) {
13195          return 0;
13196       }
13197       if (!groupmatch && channelmatch == -1) {
13198          /* Match any group since it only needs to be on the PRI span. */
13199          *groupmatched = 1;
13200          return 1;
13201       }
13202    }
13203 #endif   /* defined(HAVE_PRI) */
13204    /* check group matching */
13205    if (groupmatch) {
13206       if ((p->group & groupmatch) != groupmatch)
13207          /* Doesn't match the specified group, try the next one */
13208          return 0;
13209       *groupmatched = 1;
13210    }
13211    /* Check to see if we have a channel match */
13212    if (channelmatch != -1) {
13213       if (p->channel != channelmatch)
13214          /* Doesn't match the specified channel, try the next one */
13215          return 0;
13216       *channelmatched = 1;
13217    }
13218 
13219    return 1;
13220 }
13221 
13222 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13223 {
13224    struct dahdi_pvt *p = *pvt;
13225 
13226    if (p->inalarm)
13227       return 0;
13228 
13229    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13230       return analog_available(p->sig_pvt);
13231 
13232    switch (p->sig) {
13233 #if defined(HAVE_PRI)
13234    case SIG_PRI_LIB_HANDLE_CASES:
13235       {
13236          struct sig_pri_chan *pvt_chan;
13237          int res;
13238 
13239          pvt_chan = p->sig_pvt;
13240          res = sig_pri_available(&pvt_chan, is_specific_channel);
13241          *pvt = pvt_chan->chan_pvt;
13242          return res;
13243       }
13244 #endif   /* defined(HAVE_PRI) */
13245 #if defined(HAVE_SS7)
13246    case SIG_SS7:
13247       return sig_ss7_available(p->sig_pvt);
13248 #endif   /* defined(HAVE_SS7) */
13249    default:
13250       break;
13251    }
13252 
13253    if (p->locallyblocked || p->remotelyblocked) {
13254       return 0;
13255    }
13256 
13257    /* If no owner definitely available */
13258    if (!p->owner) {
13259 #ifdef HAVE_OPENR2
13260       /* Trust MFC/R2 */
13261       if (p->mfcr2) {
13262          if (p->mfcr2call) {
13263             return 0;
13264          } else {
13265             return 1;
13266          }
13267       }
13268 #endif
13269       return 1;
13270    }
13271 
13272    return 0;
13273 }
13274 
13275 #if defined(HAVE_PRI)
13276 #if defined(HAVE_PRI_CALL_WAITING)
13277 /*!
13278  * \internal
13279  * \brief Init the private channel configuration using the span controller.
13280  * \since 1.8
13281  *
13282  * \param priv Channel to init the configuration.
13283  * \param pri sig_pri PRI control structure.
13284  *
13285  * \note Assumes the pri->lock is already obtained.
13286  *
13287  * \return Nothing
13288  */
13289 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13290 {
13291    struct dahdi_pvt *pvt = priv;
13292 
13293    pvt->stripmsd = pri->ch_cfg.stripmsd;
13294    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13295    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13296    pvt->immediate = pri->ch_cfg.immediate;
13297    pvt->priexclusive = pri->ch_cfg.priexclusive;
13298    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13299    pvt->use_callerid = pri->ch_cfg.use_callerid;
13300    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13301    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13302    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13303 }
13304 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13305 #endif   /* defined(HAVE_PRI) */
13306 
13307 #if defined(HAVE_PRI)
13308 /*!
13309  * \internal
13310  * \brief Create a no B channel interface.
13311  * \since 1.8
13312  *
13313  * \param pri sig_pri span controller to add interface.
13314  *
13315  * \note Assumes the pri->lock is already obtained.
13316  *
13317  * \retval array-index into private pointer array on success.
13318  * \retval -1 on error.
13319  */
13320 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13321 {
13322    int pvt_idx;
13323    int res;
13324    unsigned idx;
13325    struct dahdi_pvt *pvt;
13326    struct sig_pri_chan *chan;
13327    struct dahdi_bufferinfo bi;
13328 
13329    static int nobch_channel = CHAN_PSEUDO;
13330 
13331    /* Find spot in the private pointer array for new interface. */
13332    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13333       if (!pri->pvts[pvt_idx]) {
13334          break;
13335       }
13336    }
13337    if (pri->numchans == pvt_idx) {
13338       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13339          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13340          return -1;
13341       }
13342 
13343       /* Add new spot to the private pointer array. */
13344       pri->pvts[pvt_idx] = NULL;
13345       ++pri->numchans;
13346    }
13347 
13348    pvt = ast_calloc(1, sizeof(*pvt));
13349    if (!pvt) {
13350       return -1;
13351    }
13352    pvt->cc_params = ast_cc_config_params_init();
13353    if (!pvt->cc_params) {
13354       ast_free(pvt);
13355       return -1;
13356    }
13357    ast_mutex_init(&pvt->lock);
13358    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13359       pvt->subs[idx].dfd = -1;
13360    }
13361    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13362    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13363    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13364    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13365 
13366    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13367    if (!chan) {
13368       destroy_dahdi_pvt(pvt);
13369       return -1;
13370    }
13371    chan->no_b_channel = 1;
13372 
13373    /*
13374     * Pseudo channel companding law.
13375     * Needed for outgoing call waiting calls.
13376     * XXX May need to make this determined by switchtype or user option.
13377     */
13378    pvt->law_default = DAHDI_LAW_ALAW;
13379 
13380    pvt->sig = pri->sig;
13381    pvt->outsigmod = -1;
13382    pvt->pri = pri;
13383    pvt->sig_pvt = chan;
13384    pri->pvts[pvt_idx] = chan;
13385 
13386    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13387    if (pvt->subs[SUB_REAL].dfd < 0) {
13388       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13389          strerror(errno));
13390       destroy_dahdi_pvt(pvt);
13391       return -1;
13392    }
13393    memset(&bi, 0, sizeof(bi));
13394    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13395    if (!res) {
13396       pvt->bufsize = bi.bufsize;
13397       bi.txbufpolicy = pvt->buf_policy;
13398       bi.rxbufpolicy = pvt->buf_policy;
13399       bi.numbufs = pvt->buf_no;
13400       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13401       if (res < 0) {
13402          ast_log(LOG_WARNING,
13403             "Unable to set buffer policy on no B channel interface: %s\n",
13404             strerror(errno));
13405       }
13406    } else
13407       ast_log(LOG_WARNING,
13408          "Unable to check buffer policy on no B channel interface: %s\n",
13409          strerror(errno));
13410 
13411    --nobch_channel;
13412    if (CHAN_PSEUDO < nobch_channel) {
13413       nobch_channel = CHAN_PSEUDO - 1;
13414    }
13415    pvt->channel = nobch_channel;
13416    pvt->span = pri->span;
13417    chan->channel = pvt->channel;
13418 
13419    dahdi_nobch_insert(pri, pvt);
13420 
13421    return pvt_idx;
13422 }
13423 #endif   /* defined(HAVE_PRI) */
13424 
13425 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13426    structures; it makes no attempt to safely copy regular channel private
13427    structures that might contain reference-counted object pointers and other
13428    scary bits
13429 */
13430 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13431 {
13432    struct dahdi_pvt *p;
13433    struct dahdi_bufferinfo bi;
13434    int res;
13435 
13436    p = ast_malloc(sizeof(*p));
13437    if (!p) {
13438       return NULL;
13439    }
13440    *p = *src;
13441 
13442    /* Must deep copy the cc_params. */
13443    p->cc_params = ast_cc_config_params_init();
13444    if (!p->cc_params) {
13445       ast_free(p);
13446       return NULL;
13447    }
13448    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13449 
13450    p->which_iflist = DAHDI_IFLIST_NONE;
13451    p->next = NULL;
13452    p->prev = NULL;
13453    ast_mutex_init(&p->lock);
13454    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13455    if (p->subs[SUB_REAL].dfd < 0) {
13456       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13457       destroy_dahdi_pvt(p);
13458       return NULL;
13459    }
13460    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13461    if (!res) {
13462       bi.txbufpolicy = src->buf_policy;
13463       bi.rxbufpolicy = src->buf_policy;
13464       bi.numbufs = src->buf_no;
13465       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13466       if (res < 0) {
13467          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13468       }
13469    } else
13470       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13471    p->destroy = 1;
13472    dahdi_iflist_insert(p);
13473    return p;
13474 }
13475 
13476 struct dahdi_starting_point {
13477    /*! Group matching mask.  Zero if not specified. */
13478    ast_group_t groupmatch;
13479    /*! DAHDI channel to match with.  -1 if not specified. */
13480    int channelmatch;
13481    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13482    int rr_starting_point;
13483    /*! ISDN span where channels can be picked (Zero if not specified) */
13484    int span;
13485    /*! Analog channel distinctive ring cadance index. */
13486    int cadance;
13487    /*! Dialing option. c/r/d if present and valid. */
13488    char opt;
13489    /*! TRUE if to search the channel list backwards. */
13490    char backwards;
13491    /*! TRUE if search is done with round robin sequence. */
13492    char roundrobin;
13493 };
13494 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13495 {
13496    char *dest;
13497    char *s;
13498    int x;
13499    int res = 0;
13500    struct dahdi_pvt *p;
13501    char *subdir = NULL;
13502    AST_DECLARE_APP_ARGS(args,
13503       AST_APP_ARG(group);  /* channel/group token */
13504       //AST_APP_ARG(ext);  /* extension token */
13505       //AST_APP_ARG(opts); /* options token */
13506       AST_APP_ARG(other);  /* Any remining unused arguments */
13507    );
13508 
13509    /*
13510     * data is ---v
13511     * Dial(DAHDI/pseudo[/extension[/options]])
13512     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13513     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13514     * Dial(DAHDI/i<span>[/extension[/options]])
13515     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13516     *
13517     * i - ISDN span channel restriction.
13518     *     Used by CC to ensure that the CC recall goes out the same span.
13519     *     Also to make ISDN channel names dialable when the sequence number
13520     *     is stripped off.  (Used by DTMF attended transfer feature.)
13521     *
13522     * g - channel group allocation search forward
13523     * G - channel group allocation search backward
13524     * r - channel group allocation round robin search forward
13525     * R - channel group allocation round robin search backward
13526     *
13527     * c - Wait for DTMF digit to confirm answer
13528     * r<cadance#> - Set distintive ring cadance number
13529     * d - Force bearer capability for ISDN/SS7 call to digital.
13530     */
13531 
13532    if (data) {
13533       dest = ast_strdupa(data);
13534    } else {
13535       ast_log(LOG_WARNING, "Channel requested with no data\n");
13536       return NULL;
13537    }
13538    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13539    if (!args.argc || ast_strlen_zero(args.group)) {
13540       ast_log(LOG_WARNING, "No channel/group specified\n");
13541       return NULL;
13542    }
13543 
13544    /* Initialize the output parameters */
13545    memset(param, 0, sizeof(*param));
13546    param->channelmatch = -1;
13547 
13548    if (strchr(args.group, '!') != NULL) {
13549       char *prev = args.group;
13550       while ((s = strchr(prev, '!')) != NULL) {
13551          *s++ = '/';
13552          prev = s;
13553       }
13554       *(prev - 1) = '\0';
13555       subdir = args.group;
13556       args.group = prev;
13557    } else if (args.group[0] == 'i') {
13558       /* Extract the ISDN span channel restriction specifier. */
13559       res = sscanf(args.group + 1, "%30d", &x);
13560       if (res < 1) {
13561          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13562          return NULL;
13563       }
13564       param->span = x;
13565 
13566       /* Remove the ISDN span channel restriction specifier. */
13567       s = strchr(args.group, '-');
13568       if (!s) {
13569          /* Search all groups since we are ISDN span restricted. */
13570          return iflist;
13571       }
13572       args.group = s + 1;
13573       res = 0;
13574    }
13575    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13576       /* Retrieve the group number */
13577       s = args.group + 1;
13578       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13579       if (res < 1) {
13580          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13581          return NULL;
13582       }
13583       param->groupmatch = ((ast_group_t) 1 << x);
13584 
13585       if (toupper(args.group[0]) == 'G') {
13586          if (args.group[0] == 'G') {
13587             param->backwards = 1;
13588             p = ifend;
13589          } else
13590             p = iflist;
13591       } else {
13592          if (ARRAY_LEN(round_robin) <= x) {
13593             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13594                x, data);
13595             return NULL;
13596          }
13597          if (args.group[0] == 'R') {
13598             param->backwards = 1;
13599             p = round_robin[x] ? round_robin[x]->prev : ifend;
13600             if (!p)
13601                p = ifend;
13602          } else {
13603             p = round_robin[x] ? round_robin[x]->next : iflist;
13604             if (!p)
13605                p = iflist;
13606          }
13607          param->roundrobin = 1;
13608          param->rr_starting_point = x;
13609       }
13610    } else {
13611       s = args.group;
13612       if (!strcasecmp(s, "pseudo")) {
13613          /* Special case for pseudo */
13614          x = CHAN_PSEUDO;
13615          param->channelmatch = x;
13616       } else {
13617          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13618          if (res < 1) {
13619             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13620             return NULL;
13621          } else {
13622             param->channelmatch = x;
13623          }
13624       }
13625       if (subdir) {
13626          char path[PATH_MAX];
13627          struct stat stbuf;
13628 
13629          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13630                subdir, param->channelmatch);
13631          if (stat(path, &stbuf) < 0) {
13632             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13633                   path, strerror(errno));
13634             return NULL;
13635          }
13636          if (!S_ISCHR(stbuf.st_mode)) {
13637             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13638                   path);
13639             return NULL;
13640          }
13641          param->channelmatch = minor(stbuf.st_rdev);
13642       }
13643 
13644       p = iflist;
13645    }
13646 
13647    if (param->opt == 'r' && res < 3) {
13648       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13649       param->opt = '\0';
13650    }
13651 
13652    return p;
13653 }
13654 
13655 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13656 {
13657    int callwait = 0;
13658    struct dahdi_pvt *p;
13659    struct ast_channel *tmp = NULL;
13660    struct dahdi_pvt *exitpvt;
13661    int channelmatched = 0;
13662    int groupmatched = 0;
13663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13664    int transcapdigital = 0;
13665 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13666    struct dahdi_starting_point start;
13667 
13668    ast_mutex_lock(&iflock);
13669    p = determine_starting_point(data, &start);
13670    if (!p) {
13671       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13672       ast_mutex_unlock(&iflock);
13673       return NULL;
13674    }
13675 
13676    /* Search for an unowned channel */
13677    exitpvt = p;
13678    while (p && !tmp) {
13679       if (start.roundrobin)
13680          round_robin[start.rr_starting_point] = p;
13681 
13682       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13683          && available(&p, channelmatched)) {
13684          ast_debug(1, "Using channel %d\n", p->channel);
13685 
13686          callwait = (p->owner != NULL);
13687 #ifdef HAVE_OPENR2
13688          if (p->mfcr2) {
13689             ast_mutex_lock(&p->lock);
13690             if (p->mfcr2call) {
13691                ast_mutex_unlock(&p->lock);
13692                ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13693                goto next;
13694             }
13695             p->mfcr2call = 1;
13696             ast_mutex_unlock(&p->lock);
13697          }
13698 #endif
13699          if (p->channel == CHAN_PSEUDO) {
13700             p = duplicate_pseudo(p);
13701             if (!p) {
13702                break;
13703             }
13704          }
13705 
13706          p->distinctivering = 0;
13707          /* Make special notes */
13708          switch (start.opt) {
13709          case '\0':
13710             /* No option present. */
13711             break;
13712          case 'c':
13713             /* Confirm answer */
13714             p->confirmanswer = 1;
13715             break;
13716          case 'r':
13717             /* Distinctive ring */
13718             p->distinctivering = start.cadance;
13719             break;
13720          case 'd':
13721 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13722             /* If this is an ISDN call, make it digital */
13723             transcapdigital = AST_TRANS_CAP_DIGITAL;
13724 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13725             break;
13726          default:
13727             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13728             break;
13729          }
13730 
13731          p->outgoing = 1;
13732          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13733             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13734 #ifdef HAVE_PRI
13735          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13736             /*
13737              * We already have the B channel reserved for this call.  We
13738              * just need to make sure that dahdi_hangup() has completed
13739              * cleaning up before continuing.
13740              */
13741             ast_mutex_lock(&p->lock);
13742             ast_mutex_unlock(&p->lock);
13743 
13744             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13745                sizeof(p->dnid));
13746             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13747 #endif
13748 #if defined(HAVE_SS7)
13749          } else if (p->sig == SIG_SS7) {
13750             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13751 #endif   /* defined(HAVE_SS7) */
13752          } else {
13753             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "");
13754          }
13755          if (!tmp) {
13756             p->outgoing = 0;
13757 #if defined(HAVE_PRI)
13758             switch (p->sig) {
13759             case SIG_PRI_LIB_HANDLE_CASES:
13760 #if defined(HAVE_PRI_CALL_WAITING)
13761                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13762                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13763                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13764                }
13765 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13766                /*
13767                 * This should be the last thing to clear when we are done with
13768                 * the channel.
13769                 */
13770                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13771                break;
13772             default:
13773                break;
13774             }
13775 #endif   /* defined(HAVE_PRI) */
13776          } else {
13777             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
13778          }
13779          break;
13780       }
13781 #ifdef HAVE_OPENR2
13782 next:
13783 #endif
13784       if (start.backwards) {
13785          p = p->prev;
13786          if (!p)
13787             p = ifend;
13788       } else {
13789          p = p->next;
13790          if (!p)
13791             p = iflist;
13792       }
13793       /* stop when you roll to the one that we started from */
13794       if (p == exitpvt)
13795          break;
13796    }
13797    ast_mutex_unlock(&iflock);
13798    restart_monitor();
13799    if (cause && !tmp) {
13800       if (callwait || channelmatched) {
13801          *cause = AST_CAUSE_BUSY;
13802       } else if (groupmatched) {
13803          *cause = AST_CAUSE_CONGESTION;
13804       } else {
13805          /*
13806           * We did not match any channel requested.
13807           * Dialplan error requesting non-existant channel?
13808           */
13809       }
13810    }
13811 
13812    return tmp;
13813 }
13814 
13815 /*!
13816  * \internal
13817  * \brief Determine the device state for a given DAHDI device if we can.
13818  * \since 1.8
13819  *
13820  * \param data DAHDI device name after "DAHDI/".
13821  *
13822  * \retval device_state enum ast_device_state value.
13823  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13824  */
13825 static int dahdi_devicestate(const char *data)
13826 {
13827 #if defined(HAVE_PRI)
13828    const char *device;
13829    unsigned span;
13830    int res;
13831 
13832    device = data;
13833 
13834    if (*device != 'I') {
13835       /* The request is not for an ISDN span device. */
13836       return AST_DEVICE_UNKNOWN;
13837    }
13838    res = sscanf(device, "I%30u", &span);
13839    if (res != 1 || !span || NUM_SPANS < span) {
13840       /* Bad format for ISDN span device name. */
13841       return AST_DEVICE_UNKNOWN;
13842    }
13843    device = strchr(device, '/');
13844    if (!device) {
13845       /* Bad format for ISDN span device name. */
13846       return AST_DEVICE_UNKNOWN;
13847    }
13848 
13849    /*
13850     * Since there are currently no other span devstate's defined,
13851     * it must be congestion.
13852     */
13853 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13854    ++device;
13855    if (!strcmp(device, "congestion"))
13856 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13857    {
13858       return pris[span - 1].pri.congestion_devstate;
13859    }
13860 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13861    else if (!strcmp(device, "threshold")) {
13862       return pris[span - 1].pri.threshold_devstate;
13863    }
13864    return AST_DEVICE_UNKNOWN;
13865 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13866 #else
13867    return AST_DEVICE_UNKNOWN;
13868 #endif   /* defined(HAVE_PRI) */
13869 }
13870 
13871 /*!
13872  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13873  * \since 1.8
13874  *
13875  * \param inbound Incoming asterisk channel.
13876  * \param dest Same dial string passed to dahdi_request().
13877  * \param callback Callback into CC core to announce a busy channel available for CC.
13878  *
13879  * \details
13880  * This callback acts like a forked dial with all prongs of the fork busy.
13881  * Essentially, for each channel that could have taken the call, indicate that
13882  * it is busy.
13883  *
13884  * \retval 0 on success.
13885  * \retval -1 on error.
13886  */
13887 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13888 {
13889    struct dahdi_pvt *p;
13890    struct dahdi_pvt *exitpvt;
13891    struct dahdi_starting_point start;
13892    int groupmatched = 0;
13893    int channelmatched = 0;
13894 
13895    ast_mutex_lock(&iflock);
13896    p = determine_starting_point(dest, &start);
13897    if (!p) {
13898       ast_mutex_unlock(&iflock);
13899       return -1;
13900    }
13901    exitpvt = p;
13902    for (;;) {
13903       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13904          /* We found a potential match. call the callback */
13905          struct ast_str *device_name;
13906          char *dash;
13907          const char *monitor_type;
13908          char dialstring[AST_CHANNEL_NAME];
13909          char full_device_name[AST_CHANNEL_NAME];
13910 
13911          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13912          case AST_CC_MONITOR_NEVER:
13913             break;
13914          case AST_CC_MONITOR_NATIVE:
13915          case AST_CC_MONITOR_ALWAYS:
13916          case AST_CC_MONITOR_GENERIC:
13917 #if defined(HAVE_PRI)
13918             if (dahdi_sig_pri_lib_handles(p->sig)) {
13919                /*
13920                 * ISDN is in a trunk busy condition so we need to monitor
13921                 * the span congestion device state.
13922                 */
13923                snprintf(full_device_name, sizeof(full_device_name),
13924                   "DAHDI/I%d/congestion", p->pri->span);
13925             } else
13926 #endif   /* defined(HAVE_PRI) */
13927             {
13928 #if defined(HAVE_PRI)
13929                device_name = create_channel_name(p, 1, "");
13930 #else
13931                device_name = create_channel_name(p);
13932 #endif   /* defined(HAVE_PRI) */
13933                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13934                   device_name ? ast_str_buffer(device_name) : "");
13935                ast_free(device_name);
13936                /*
13937                 * The portion after the '-' in the channel name is either a random
13938                 * number, a sequence number, or a subchannel number. None are
13939                 * necessary so strip them off.
13940                 */
13941                dash = strrchr(full_device_name, '-');
13942                if (dash) {
13943                   *dash = '\0';
13944                }
13945             }
13946             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13947 
13948             /*
13949              * Analog can only do generic monitoring.
13950              * ISDN is in a trunk busy condition and any "device" is going
13951              * to be busy until a B channel becomes available.  The generic
13952              * monitor can do this task.
13953              */
13954             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13955             callback(inbound,
13956 #if defined(HAVE_PRI)
13957                p->pri ? p->pri->cc_params : p->cc_params,
13958 #else
13959                p->cc_params,
13960 #endif   /* defined(HAVE_PRI) */
13961                monitor_type, full_device_name, dialstring, NULL);
13962             break;
13963          }
13964       }
13965       p = start.backwards ? p->prev : p->next;
13966       if (!p) {
13967          p = start.backwards ? ifend : iflist;
13968       }
13969       if (p == exitpvt) {
13970          break;
13971       }
13972    }
13973    ast_mutex_unlock(&iflock);
13974    return 0;
13975 }
13976 
13977 #if defined(HAVE_SS7)
13978 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13979 {
13980    int i;
13981 
13982    if (ss7) {
13983       for (i = 0; i < NUM_SPANS; i++) {
13984          if (linksets[i].ss7.ss7 == ss7) {
13985             ast_verbose("[%d] %s", i + 1, s);
13986             return;
13987          }
13988       }
13989    }
13990    ast_verbose("%s", s);
13991 }
13992 #endif   /* defined(HAVE_SS7) */
13993 
13994 #if defined(HAVE_SS7)
13995 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13996 {
13997    int i;
13998 
13999    if (ss7) {
14000       for (i = 0; i < NUM_SPANS; i++) {
14001          if (linksets[i].ss7.ss7 == ss7) {
14002             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14003             return;
14004          }
14005       }
14006    }
14007    ast_log(LOG_ERROR, "%s", s);
14008 }
14009 #endif   /* defined(HAVE_SS7) */
14010 
14011 #if defined(HAVE_OPENR2)
14012 static void *mfcr2_monitor(void *data)
14013 {
14014    struct dahdi_mfcr2 *mfcr2 = data;
14015    /* we should be using pthread_key_create
14016       and allocate pollers dynamically.
14017       I think do_monitor() could be leaking, since it
14018       could be cancelled at any time and is not
14019       using thread keys, why?, */
14020    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14021    int res = 0;
14022    int i = 0;
14023    int oldstate = 0;
14024    int quit_loop = 0;
14025    int maxsleep = 20;
14026    int was_idle = 0;
14027    int pollsize = 0;
14028    /* now that we're ready to get calls, unblock our side and
14029       get current line state */
14030    for (i = 0; i < mfcr2->numchans; i++) {
14031       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14032       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14033    }
14034    while (1) {
14035       /* we trust here that the mfcr2 channel list will not ever change once
14036          the module is loaded */
14037       pollsize = 0;
14038       for (i = 0; i < mfcr2->numchans; i++) {
14039          pollers[i].revents = 0;
14040          pollers[i].events = 0;
14041          if (mfcr2->pvts[i]->owner) {
14042             continue;
14043          }
14044          if (!mfcr2->pvts[i]->r2chan) {
14045             ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14046             quit_loop = 1;
14047             break;
14048          }
14049          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14050          pollers[i].events = POLLIN | POLLPRI;
14051          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14052          pollsize++;
14053       }
14054       if (quit_loop) {
14055          break;
14056       }
14057       if (pollsize == 0) {
14058          if (!was_idle) {
14059             ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14060             was_idle = 1;
14061          }
14062          poll(NULL, 0, maxsleep);
14063          continue;
14064       }
14065       was_idle = 0;
14066       /* probably poll() is a valid cancel point, lets just be on the safe side
14067          by calling pthread_testcancel */
14068       pthread_testcancel();
14069       res = poll(pollers, mfcr2->numchans, maxsleep);
14070       pthread_testcancel();
14071       if ((res < 0) && (errno != EINTR)) {
14072          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14073          break;
14074       }
14075       /* do we want to allow to cancel while processing events? */
14076       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14077       for (i = 0; i < mfcr2->numchans; i++) {
14078          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14079             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14080          }
14081       }
14082       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14083    }
14084    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14085    return 0;
14086 }
14087 #endif /* HAVE_OPENR2 */
14088 
14089 #if defined(HAVE_PRI)
14090 #ifndef PRI_RESTART
14091 #error "Upgrade your libpri"
14092 #endif
14093 static void dahdi_pri_message(struct pri *pri, char *s)
14094 {
14095    int x;
14096    int y;
14097    int dchan = -1;
14098    int span = -1;
14099    int dchancount = 0;
14100 
14101    if (pri) {
14102       for (x = 0; x < NUM_SPANS; x++) {
14103          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14104             if (pris[x].pri.dchans[y]) {
14105                dchancount++;
14106             }
14107 
14108             if (pris[x].pri.dchans[y] == pri) {
14109                dchan = y;
14110             }
14111          }
14112          if (dchan >= 0) {
14113             span = x;
14114             break;
14115          }
14116          dchancount = 0;
14117       }
14118       if (-1 < span) {
14119          if (1 < dchancount) {
14120             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14121          } else {
14122             ast_verbose("PRI Span: %d %s", span + 1, s);
14123          }
14124       } else {
14125          ast_verbose("PRI Span: ? %s", s);
14126       }
14127    } else {
14128       ast_verbose("PRI Span: ? %s", s);
14129    }
14130 
14131    ast_mutex_lock(&pridebugfdlock);
14132 
14133    if (pridebugfd >= 0) {
14134       if (write(pridebugfd, s, strlen(s)) < 0) {
14135          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14136       }
14137    }
14138 
14139    ast_mutex_unlock(&pridebugfdlock);
14140 }
14141 #endif   /* defined(HAVE_PRI) */
14142 
14143 #if defined(HAVE_PRI)
14144 static void dahdi_pri_error(struct pri *pri, char *s)
14145 {
14146    int x;
14147    int y;
14148    int dchan = -1;
14149    int span = -1;
14150    int dchancount = 0;
14151 
14152    if (pri) {
14153       for (x = 0; x < NUM_SPANS; x++) {
14154          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14155             if (pris[x].pri.dchans[y]) {
14156                dchancount++;
14157             }
14158 
14159             if (pris[x].pri.dchans[y] == pri) {
14160                dchan = y;
14161             }
14162          }
14163          if (dchan >= 0) {
14164             span = x;
14165             break;
14166          }
14167          dchancount = 0;
14168       }
14169       if (-1 < span) {
14170          if (1 < dchancount) {
14171             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14172          } else {
14173             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14174          }
14175       } else {
14176          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14177       }
14178    } else {
14179       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14180    }
14181 
14182    ast_mutex_lock(&pridebugfdlock);
14183 
14184    if (pridebugfd >= 0) {
14185       if (write(pridebugfd, s, strlen(s)) < 0) {
14186          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14187       }
14188    }
14189 
14190    ast_mutex_unlock(&pridebugfdlock);
14191 }
14192 #endif   /* defined(HAVE_PRI) */
14193 
14194 #if defined(HAVE_PRI)
14195 static int prepare_pri(struct dahdi_pri *pri)
14196 {
14197    int i, res, x;
14198    struct dahdi_params p;
14199    struct dahdi_bufferinfo bi;
14200    struct dahdi_spaninfo si;
14201 
14202    pri->pri.calls = &dahdi_pri_callbacks;
14203 
14204    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14205       if (!pri->dchannels[i])
14206          break;
14207       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14208       x = pri->dchannels[i];
14209       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14210          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14211          return -1;
14212       }
14213       memset(&p, 0, sizeof(p));
14214       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14215       if (res) {
14216          dahdi_close_pri_fd(pri, i);
14217          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14218          return -1;
14219       }
14220       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14221          dahdi_close_pri_fd(pri, i);
14222          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14223          return -1;
14224       }
14225       memset(&si, 0, sizeof(si));
14226       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14227       if (res) {
14228          dahdi_close_pri_fd(pri, i);
14229          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14230       }
14231       if (!si.alarms) {
14232          pri_event_noalarm(&pri->pri, i, 1);
14233       } else {
14234          pri_event_alarm(&pri->pri, i, 1);
14235       }
14236       memset(&bi, 0, sizeof(bi));
14237       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14238       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14239       bi.numbufs = 32;
14240       bi.bufsize = 1024;
14241       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14242          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14243          dahdi_close_pri_fd(pri, i);
14244          return -1;
14245       }
14246       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14247    }
14248    return 0;
14249 }
14250 #endif   /* defined(HAVE_PRI) */
14251 
14252 #if defined(HAVE_PRI)
14253 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14254 {
14255    int which, span;
14256    char *ret = NULL;
14257 
14258    if (pos != rpos)
14259       return ret;
14260 
14261    for (which = span = 0; span < NUM_SPANS; span++) {
14262       if (pris[span].pri.pri && ++which > state) {
14263          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14264             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14265          }
14266          break;
14267       }
14268    }
14269    return ret;
14270 }
14271 #endif   /* defined(HAVE_PRI) */
14272 
14273 #if defined(HAVE_PRI)
14274 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14275 {
14276    return complete_span_helper(line,word,pos,state,3);
14277 }
14278 #endif   /* defined(HAVE_PRI) */
14279 
14280 #if defined(HAVE_PRI)
14281 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14282 {
14283    int myfd;
14284    switch (cmd) {
14285    case CLI_INIT:
14286       e->command = "pri set debug file";
14287       e->usage = "Usage: pri set debug file [output-file]\n"
14288          "       Sends PRI debug output to the specified output file\n";
14289       return NULL;
14290    case CLI_GENERATE:
14291       return NULL;
14292    }
14293    if (a->argc < 5)
14294       return CLI_SHOWUSAGE;
14295 
14296    if (ast_strlen_zero(a->argv[4]))
14297       return CLI_SHOWUSAGE;
14298 
14299    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14300    if (myfd < 0) {
14301       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14302       return CLI_SUCCESS;
14303    }
14304 
14305    ast_mutex_lock(&pridebugfdlock);
14306 
14307    if (pridebugfd >= 0)
14308       close(pridebugfd);
14309 
14310    pridebugfd = myfd;
14311    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14312    ast_mutex_unlock(&pridebugfdlock);
14313    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14314    return CLI_SUCCESS;
14315 }
14316 #endif   /* defined(HAVE_PRI) */
14317 
14318 #if defined(HAVE_PRI)
14319 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14320 {
14321    int span;
14322    int x;
14323    int debugmask = 0;
14324    int level = 0;
14325    switch (cmd) {
14326    case CLI_INIT:
14327       e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14328       e->usage =
14329          "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14330          "       Enables debugging on a given PRI span\n"
14331          "  Level is a bitmap of the following values:\n"
14332          "  1 General debugging incl. state changes\n"
14333          "  2 Decoded Q.931 messages\n"
14334          "  4 Decoded Q.921 messages\n"
14335          "  8 Raw hex dumps of Q.921 frames\n"
14336          "       on - equivalent to 3\n"
14337          "       hex - equivalent to 8\n"
14338          "       intense - equivalent to 15\n";
14339       return NULL;
14340    case CLI_GENERATE:
14341       return complete_span_4(a->line, a->word, a->pos, a->n);
14342    }
14343    if (a->argc < 6) {
14344       return CLI_SHOWUSAGE;
14345    }
14346 
14347    if (!strcasecmp(a->argv[3], "on")) {
14348       level = 3;
14349    } else if (!strcasecmp(a->argv[3], "off")) {
14350       level = 0;
14351    } else if (!strcasecmp(a->argv[3], "intense")) {
14352       level = 15;
14353    } else if (!strcasecmp(a->argv[3], "hex")) {
14354       level = 8;
14355    } else {
14356       level = atoi(a->argv[3]);
14357    }
14358    span = atoi(a->argv[5]);
14359    if ((span < 1) || (span > NUM_SPANS)) {
14360       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14361       return CLI_SUCCESS;
14362    }
14363    if (!pris[span-1].pri.pri) {
14364       ast_cli(a->fd, "No PRI running on span %d\n", span);
14365       return CLI_SUCCESS;
14366    }
14367 
14368    if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14369    if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14370    if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14371    if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14372 
14373    /* Set debug level in libpri */
14374    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14375       if (pris[span - 1].pri.dchans[x]) {
14376          pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14377       }
14378    }
14379    if (level == 0) {
14380       /* Close the debugging file if it's set */
14381       ast_mutex_lock(&pridebugfdlock);
14382       if (0 <= pridebugfd) {
14383          close(pridebugfd);
14384          pridebugfd = -1;
14385          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14386             pridebugfilename);
14387       }
14388       ast_mutex_unlock(&pridebugfdlock);
14389    }
14390    pris[span - 1].pri.debug = (level) ? 1 : 0;
14391    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14392    return CLI_SUCCESS;
14393 }
14394 #endif   /* defined(HAVE_PRI) */
14395 
14396 #if defined(HAVE_PRI)
14397 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14398 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14399 {
14400    unsigned *why;
14401    int channel;
14402    int trunkgroup;
14403    int x, y, fd = a->fd;
14404    int interfaceid = 0;
14405    char *c;
14406    char db_chan_name[20], db_answer[5];
14407    struct dahdi_pvt *tmp;
14408    struct dahdi_pri *pri;
14409 
14410    if (a->argc < 5 || a->argc > 6)
14411       return CLI_SHOWUSAGE;
14412    if ((c = strchr(a->argv[4], ':'))) {
14413       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14414          return CLI_SHOWUSAGE;
14415       if ((trunkgroup < 1) || (channel < 1))
14416          return CLI_SHOWUSAGE;
14417       pri = NULL;
14418       for (x=0;x<NUM_SPANS;x++) {
14419          if (pris[x].pri.trunkgroup == trunkgroup) {
14420             pri = pris + x;
14421             break;
14422          }
14423       }
14424       if (!pri) {
14425          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14426          return CLI_FAILURE;
14427       }
14428    } else
14429       channel = atoi(a->argv[4]);
14430 
14431    if (a->argc == 6)
14432       interfaceid = atoi(a->argv[5]);
14433 
14434    /* either servicing a D-Channel */
14435    for (x = 0; x < NUM_SPANS; x++) {
14436       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14437          if (pris[x].dchannels[y] == channel) {
14438             pri = pris + x;
14439             if (pri->pri.enable_service_message_support) {
14440                ast_mutex_lock(&pri->pri.lock);
14441                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14442                ast_mutex_unlock(&pri->pri.lock);
14443             } else {
14444                ast_cli(fd,
14445                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14446                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14447             }
14448             return CLI_SUCCESS;
14449          }
14450       }
14451    }
14452 
14453    /* or servicing a B-Channel */
14454    ast_mutex_lock(&iflock);
14455    for (tmp = iflist; tmp; tmp = tmp->next) {
14456       if (tmp->pri && tmp->channel == channel) {
14457          ast_mutex_unlock(&iflock);
14458          ast_mutex_lock(&tmp->pri->lock);
14459          if (!tmp->pri->enable_service_message_support) {
14460             ast_mutex_unlock(&tmp->pri->lock);
14461             ast_cli(fd,
14462                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14463                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14464             return CLI_SUCCESS;
14465          }
14466          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14467          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14468          switch(changestatus) {
14469          case 0: /* enable */
14470             /* Near end wants to be in service now. */
14471             ast_db_del(db_chan_name, SRVST_DBKEY);
14472             *why &= ~SRVST_NEAREND;
14473             if (*why) {
14474                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14475                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14476             } else {
14477                dahdi_pri_update_span_devstate(tmp->pri);
14478             }
14479             break;
14480          /* case 1:  -- loop */
14481          case 2: /* disable */
14482             /* Near end wants to be out-of-service now. */
14483             ast_db_del(db_chan_name, SRVST_DBKEY);
14484             *why |= SRVST_NEAREND;
14485             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14486             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14487             dahdi_pri_update_span_devstate(tmp->pri);
14488             break;
14489          /* case 3:  -- continuity */
14490          /* case 4:  -- shutdown */
14491          default:
14492             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14493             break;
14494          }
14495          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14496          ast_mutex_unlock(&tmp->pri->lock);
14497          return CLI_SUCCESS;
14498       }
14499    }
14500    ast_mutex_unlock(&iflock);
14501 
14502    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14503    return CLI_FAILURE;
14504 }
14505 
14506 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14507 {
14508    switch (cmd) {
14509    case CLI_INIT:
14510       e->command = "pri service enable channel";
14511       e->usage =
14512          "Usage: pri service enable channel <channel> [<interface id>]\n"
14513          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14514          "  to restore a channel to service, with optional interface id\n"
14515          "  as agreed upon with remote switch operator\n";
14516       return NULL;
14517    case CLI_GENERATE:
14518       return NULL;
14519    }
14520    return handle_pri_service_generic(e, cmd, a, 0);
14521 }
14522 
14523 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14524 {
14525    switch (cmd) {
14526    case CLI_INIT:
14527       e->command = "pri service disable channel";
14528       e->usage =
14529          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14530          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14531          "  to remove a channel from service, with optional interface id\n"
14532          "  as agreed upon with remote switch operator\n";
14533       return NULL;
14534    case CLI_GENERATE:
14535       return NULL;
14536    }
14537    return handle_pri_service_generic(e, cmd, a, 2);
14538 }
14539 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14540 #endif   /* defined(HAVE_PRI) */
14541 
14542 #if defined(HAVE_PRI)
14543 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14544 {
14545    int span;
14546 
14547    switch (cmd) {
14548    case CLI_INIT:
14549       e->command = "pri show channels";
14550       e->usage =
14551          "Usage: pri show channels\n"
14552          "       Displays PRI channel information such as the current mapping\n"
14553          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14554          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14555          "       are not associated with any B channel.\n";
14556       return NULL;
14557    case CLI_GENERATE:
14558       return NULL;
14559    }
14560 
14561    if (a->argc != 3)
14562       return CLI_SHOWUSAGE;
14563 
14564    sig_pri_cli_show_channels_header(a->fd);
14565    for (span = 0; span < NUM_SPANS; ++span) {
14566       if (pris[span].pri.pri) {
14567          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14568       }
14569    }
14570    return CLI_SUCCESS;
14571 }
14572 #endif   /* defined(HAVE_PRI) */
14573 
14574 #if defined(HAVE_PRI)
14575 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14576 {
14577    int span;
14578 
14579    switch (cmd) {
14580    case CLI_INIT:
14581       e->command = "pri show spans";
14582       e->usage =
14583          "Usage: pri show spans\n"
14584          "       Displays PRI span information\n";
14585       return NULL;
14586    case CLI_GENERATE:
14587       return NULL;
14588    }
14589 
14590    if (a->argc != 3)
14591       return CLI_SHOWUSAGE;
14592 
14593    for (span = 0; span < NUM_SPANS; span++) {
14594       if (pris[span].pri.pri) {
14595          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14596       }
14597    }
14598    return CLI_SUCCESS;
14599 }
14600 #endif   /* defined(HAVE_PRI) */
14601 
14602 #if defined(HAVE_PRI)
14603 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14604 {
14605    int span;
14606 
14607    switch (cmd) {
14608    case CLI_INIT:
14609       e->command = "pri show span";
14610       e->usage =
14611          "Usage: pri show span <span>\n"
14612          "       Displays PRI Information on a given PRI span\n";
14613       return NULL;
14614    case CLI_GENERATE:
14615       return complete_span_4(a->line, a->word, a->pos, a->n);
14616    }
14617 
14618    if (a->argc < 4)
14619       return CLI_SHOWUSAGE;
14620    span = atoi(a->argv[3]);
14621    if ((span < 1) || (span > NUM_SPANS)) {
14622       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14623       return CLI_SUCCESS;
14624    }
14625    if (!pris[span-1].pri.pri) {
14626       ast_cli(a->fd, "No PRI running on span %d\n", span);
14627       return CLI_SUCCESS;
14628    }
14629 
14630    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14631 
14632    return CLI_SUCCESS;
14633 }
14634 #endif   /* defined(HAVE_PRI) */
14635 
14636 #if defined(HAVE_PRI)
14637 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14638 {
14639    int x;
14640    int span;
14641    int count=0;
14642    int debug;
14643 
14644    switch (cmd) {
14645    case CLI_INIT:
14646       e->command = "pri show debug";
14647       e->usage =
14648          "Usage: pri show debug\n"
14649          "  Show the debug state of pri spans\n";
14650       return NULL;
14651    case CLI_GENERATE:
14652       return NULL;
14653    }
14654 
14655    for (span = 0; span < NUM_SPANS; span++) {
14656       if (pris[span].pri.pri) {
14657          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14658             if (pris[span].pri.dchans[x]) {
14659                debug = pri_get_debug(pris[span].pri.dchans[x]);
14660                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" );
14661                count++;
14662             }
14663          }
14664       }
14665 
14666    }
14667    ast_mutex_lock(&pridebugfdlock);
14668    if (pridebugfd >= 0)
14669       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14670    ast_mutex_unlock(&pridebugfdlock);
14671 
14672    if (!count)
14673       ast_cli(a->fd, "No PRI running\n");
14674    return CLI_SUCCESS;
14675 }
14676 #endif   /* defined(HAVE_PRI) */
14677 
14678 #if defined(HAVE_PRI)
14679 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14680 {
14681    switch (cmd) {
14682    case CLI_INIT:
14683       e->command = "pri show version";
14684       e->usage =
14685          "Usage: pri show version\n"
14686          "Show libpri version information\n";
14687       return NULL;
14688    case CLI_GENERATE:
14689       return NULL;
14690    }
14691 
14692    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14693 
14694    return CLI_SUCCESS;
14695 }
14696 #endif   /* defined(HAVE_PRI) */
14697 
14698 #if defined(HAVE_PRI)
14699 static struct ast_cli_entry dahdi_pri_cli[] = {
14700    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14701 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14702    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14703    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14704 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14705    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14706    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14707    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14708    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14709    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14710    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14711 };
14712 #endif   /* defined(HAVE_PRI) */
14713 
14714 #ifdef HAVE_OPENR2
14715 
14716 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14717 {
14718    switch (cmd) {
14719    case CLI_INIT:
14720       e->command = "mfcr2 show version";
14721       e->usage =
14722          "Usage: mfcr2 show version\n"
14723          "       Shows the version of the OpenR2 library being used.\n";
14724       return NULL;
14725    case CLI_GENERATE:
14726       return NULL;
14727    }
14728    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14729    return CLI_SUCCESS;
14730 }
14731 
14732 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14733 {
14734 #define FORMAT "%4s %40s\n"
14735    int i = 0;
14736    int numvariants = 0;
14737    const openr2_variant_entry_t *variants;
14738    switch (cmd) {
14739    case CLI_INIT:
14740       e->command = "mfcr2 show variants";
14741       e->usage =
14742          "Usage: mfcr2 show variants\n"
14743          "       Shows the list of MFC/R2 variants supported.\n";
14744       return NULL;
14745    case CLI_GENERATE:
14746       return NULL;
14747    }
14748    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14749       ast_cli(a->fd, "Failed to get list of variants.\n");
14750       return CLI_FAILURE;
14751    }
14752    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14753    for (i = 0; i < numvariants; i++) {
14754       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14755    }
14756    return CLI_SUCCESS;
14757 #undef FORMAT
14758 }
14759 
14760 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14761 {
14762 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14763    int filtertype = 0;
14764    int targetnum = 0;
14765    char channo[5];
14766    char anino[5];
14767    char dnisno[5];
14768    struct dahdi_pvt *p;
14769    openr2_context_t *r2context;
14770    openr2_variant_t r2variant;
14771    switch (cmd) {
14772    case CLI_INIT:
14773       e->command = "mfcr2 show channels [group|context]";
14774       e->usage =
14775          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14776          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14777       return NULL;
14778    case CLI_GENERATE:
14779       return NULL;
14780    }
14781    if (!((a->argc == 3) || (a->argc == 5))) {
14782       return CLI_SHOWUSAGE;
14783    }
14784    if (a->argc == 5) {
14785       if (!strcasecmp(a->argv[3], "group")) {
14786          targetnum = atoi(a->argv[4]);
14787          if ((targetnum < 0) || (targetnum > 63))
14788             return CLI_SHOWUSAGE;
14789          targetnum = 1 << targetnum;
14790          filtertype = 1;
14791       } else if (!strcasecmp(a->argv[3], "context")) {
14792          filtertype = 2;
14793       } else {
14794          return CLI_SHOWUSAGE;
14795       }
14796    }
14797    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14798    ast_mutex_lock(&iflock);
14799    for (p = iflist; p; p = p->next) {
14800       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14801          continue;
14802       }
14803       if (filtertype) {
14804          switch(filtertype) {
14805          case 1: /* mfcr2 show channels group <group> */
14806             if (p->group != targetnum) {
14807                continue;
14808             }
14809             break;
14810          case 2: /* mfcr2 show channels context <context> */
14811             if (strcasecmp(p->context, a->argv[4])) {
14812                continue;
14813             }
14814             break;
14815          default:
14816             ;
14817          }
14818       }
14819       r2context = openr2_chan_get_context(p->r2chan);
14820       r2variant = openr2_context_get_variant(r2context);
14821       snprintf(channo, sizeof(channo), "%d", p->channel);
14822       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14823       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14824       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14825             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14826             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14827             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14828    }
14829    ast_mutex_unlock(&iflock);
14830    return CLI_SUCCESS;
14831 #undef FORMAT
14832 }
14833 
14834 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14835 {
14836    struct dahdi_pvt *p = NULL;
14837    int channo = 0;
14838    char *toklevel = NULL;
14839    char *saveptr = NULL;
14840    char *logval = NULL;
14841    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14842    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14843    switch (cmd) {
14844    case CLI_INIT:
14845       e->command = "mfcr2 set debug";
14846       e->usage =
14847          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14848          "       Set a new logging level for the specified channel.\n"
14849          "       If no channel is specified the logging level will be applied to all channels.\n";
14850       return NULL;
14851    case CLI_GENERATE:
14852       return NULL;
14853    }
14854    if (a->argc < 4) {
14855       return CLI_SHOWUSAGE;
14856    }
14857    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14858    logval = ast_strdupa(a->argv[3]);
14859    toklevel = strtok_r(logval, ",", &saveptr);
14860    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14861       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14862       return CLI_FAILURE;
14863    } else if (OR2_LOG_NOTHING == tmplevel) {
14864       loglevel = tmplevel;
14865    } else {
14866       loglevel |= tmplevel;
14867       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14868          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14869             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14870             continue;
14871          }
14872          loglevel |= tmplevel;
14873       }
14874    }
14875    ast_mutex_lock(&iflock);
14876    for (p = iflist; p; p = p->next) {
14877       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14878          continue;
14879       }
14880       if ((channo != -1) && (p->channel != channo )) {
14881          continue;
14882       }
14883       openr2_chan_set_log_level(p->r2chan, loglevel);
14884       if (channo != -1) {
14885          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14886          break;
14887       }
14888    }
14889    if ((channo != -1) && !p) {
14890       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14891    }
14892    if (channo == -1) {
14893       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14894    }
14895    ast_mutex_unlock(&iflock);
14896    return CLI_SUCCESS;
14897 }
14898 
14899 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14900 {
14901    struct dahdi_pvt *p = NULL;
14902    int channo = 0;
14903    switch (cmd) {
14904    case CLI_INIT:
14905       e->command = "mfcr2 call files [on|off]";
14906       e->usage =
14907          "Usage: mfcr2 call files [on|off] <channel>\n"
14908          "       Enable call files creation on the specified channel.\n"
14909          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14910       return NULL;
14911    case CLI_GENERATE:
14912       return NULL;
14913    }
14914    if (a->argc < 4) {
14915       return CLI_SHOWUSAGE;
14916    }
14917    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14918    ast_mutex_lock(&iflock);
14919    for (p = iflist; p; p = p->next) {
14920       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14921          continue;
14922       }
14923       if ((channo != -1) && (p->channel != channo )) {
14924          continue;
14925       }
14926       if (ast_true(a->argv[3])) {
14927          openr2_chan_enable_call_files(p->r2chan);
14928       } else {
14929          openr2_chan_disable_call_files(p->r2chan);
14930       }
14931       if (channo != -1) {
14932          if (ast_true(a->argv[3])) {
14933             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14934          } else {
14935             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14936          }
14937          break;
14938       }
14939    }
14940    if ((channo != -1) && !p) {
14941       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14942    }
14943    if (channo == -1) {
14944       if (ast_true(a->argv[3])) {
14945          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14946       } else {
14947          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14948       }
14949    }
14950    ast_mutex_unlock(&iflock);
14951    return CLI_SUCCESS;
14952 }
14953 
14954 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14955 {
14956    struct dahdi_pvt *p = NULL;
14957    int channo = 0;
14958    switch (cmd) {
14959    case CLI_INIT:
14960       e->command = "mfcr2 set idle";
14961       e->usage =
14962          "Usage: mfcr2 set idle <channel>\n"
14963          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14964          "       Force the given channel into IDLE state.\n"
14965          "       If no channel is specified, all channels will be set to IDLE.\n";
14966       return NULL;
14967    case CLI_GENERATE:
14968       return NULL;
14969    }
14970    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14971    ast_mutex_lock(&iflock);
14972    for (p = iflist; p; p = p->next) {
14973       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14974          continue;
14975       }
14976       if ((channo != -1) && (p->channel != channo )) {
14977          continue;
14978       }
14979       openr2_chan_set_idle(p->r2chan);
14980       ast_mutex_lock(&p->lock);
14981       p->locallyblocked = 0;
14982       p->mfcr2call = 0;
14983       ast_mutex_unlock(&p->lock);
14984       if (channo != -1) {
14985          break;
14986       }
14987    }
14988    if ((channo != -1) && !p) {
14989       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14990    }
14991    ast_mutex_unlock(&iflock);
14992    return CLI_SUCCESS;
14993 }
14994 
14995 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14996 {
14997    struct dahdi_pvt *p = NULL;
14998    int channo = 0;
14999    switch (cmd) {
15000    case CLI_INIT:
15001       e->command = "mfcr2 set blocked";
15002       e->usage =
15003          "Usage: mfcr2 set blocked <channel>\n"
15004          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15005          "       Force the given channel into BLOCKED state.\n"
15006          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15007       return NULL;
15008    case CLI_GENERATE:
15009       return NULL;
15010    }
15011    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15012    ast_mutex_lock(&iflock);
15013    for (p = iflist; p; p = p->next) {
15014       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15015          continue;
15016       }
15017       if ((channo != -1) && (p->channel != channo )) {
15018          continue;
15019       }
15020       openr2_chan_set_blocked(p->r2chan);
15021       ast_mutex_lock(&p->lock);
15022       p->locallyblocked = 1;
15023       ast_mutex_unlock(&p->lock);
15024       if (channo != -1) {
15025          break;
15026       }
15027    }
15028    if ((channo != -1) && !p) {
15029       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15030    }
15031    ast_mutex_unlock(&iflock);
15032    return CLI_SUCCESS;
15033 }
15034 
15035 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15036    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15037    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15038    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15039    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15040    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15041    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15042    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15043 };
15044 
15045 #endif /* HAVE_OPENR2 */
15046 
15047 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15048 {
15049    int channel;
15050    int ret;
15051    switch (cmd) {
15052    case CLI_INIT:
15053       e->command = "dahdi destroy channel";
15054       e->usage =
15055          "Usage: dahdi destroy channel <chan num>\n"
15056          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15057       return NULL;
15058    case CLI_GENERATE:
15059       return NULL;
15060    }
15061    if (a->argc != 4)
15062       return CLI_SHOWUSAGE;
15063 
15064    channel = atoi(a->argv[3]);
15065    ret = dahdi_destroy_channel_bynum(channel);
15066    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15067 }
15068 
15069 static void dahdi_softhangup_all(void)
15070 {
15071    struct dahdi_pvt *p;
15072 retry:
15073    ast_mutex_lock(&iflock);
15074    for (p = iflist; p; p = p->next) {
15075       ast_mutex_lock(&p->lock);
15076       if (p->owner && !p->restartpending) {
15077          if (ast_channel_trylock(p->owner)) {
15078             if (option_debug > 2)
15079                ast_verbose("Avoiding deadlock\n");
15080             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15081             ast_mutex_unlock(&p->lock);
15082             ast_mutex_unlock(&iflock);
15083             goto retry;
15084          }
15085          if (option_debug > 2)
15086             ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15087          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15088          p->restartpending = 1;
15089          num_restart_pending++;
15090          ast_channel_unlock(p->owner);
15091       }
15092       ast_mutex_unlock(&p->lock);
15093    }
15094    ast_mutex_unlock(&iflock);
15095 }
15096 
15097 static int setup_dahdi(int reload);
15098 static int dahdi_restart(void)
15099 {
15100 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15101    int i, j;
15102 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15103    int cancel_code;
15104    struct dahdi_pvt *p;
15105 
15106    ast_mutex_lock(&restart_lock);
15107    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15108    dahdi_softhangup_all();
15109    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15110 #ifdef HAVE_OPENR2
15111    dahdi_r2_destroy_links();
15112 #endif
15113 
15114 #if defined(HAVE_PRI)
15115    for (i = 0; i < NUM_SPANS; i++) {
15116       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15117          cancel_code = pthread_cancel(pris[i].pri.master);
15118          pthread_kill(pris[i].pri.master, SIGURG);
15119          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
15120          pthread_join(pris[i].pri.master, NULL);
15121          ast_debug(4, "Joined thread of span %d\n", i);
15122       }
15123    }
15124 #endif
15125 
15126 #if defined(HAVE_SS7)
15127    for (i = 0; i < NUM_SPANS; i++) {
15128       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15129          cancel_code = pthread_cancel(linksets[i].ss7.master);
15130          pthread_kill(linksets[i].ss7.master, SIGURG);
15131          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
15132          pthread_join(linksets[i].ss7.master, NULL);
15133          ast_debug(4, "Joined thread of span %d\n", i);
15134       }
15135    }
15136 #endif   /* defined(HAVE_SS7) */
15137 
15138    ast_mutex_lock(&monlock);
15139    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15140       cancel_code = pthread_cancel(monitor_thread);
15141       pthread_kill(monitor_thread, SIGURG);
15142       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15143       pthread_join(monitor_thread, NULL);
15144       ast_debug(4, "Joined monitor thread\n");
15145    }
15146    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15147 
15148    ast_mutex_lock(&ss_thread_lock);
15149    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15150       int x = DAHDI_FLASH;
15151       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15152 
15153       ast_mutex_lock(&iflock);
15154       for (p = iflist; p; p = p->next) {
15155          if (p->owner) {
15156             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15157             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15158          }
15159       }
15160       ast_mutex_unlock(&iflock);
15161       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15162    }
15163 
15164    /* ensure any created channels before monitor threads were stopped are hungup */
15165    dahdi_softhangup_all();
15166    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15167    destroy_all_channels();
15168    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15169 
15170    ast_mutex_unlock(&monlock);
15171 
15172 #ifdef HAVE_PRI
15173    for (i = 0; i < NUM_SPANS; i++) {
15174       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15175          dahdi_close_pri_fd(&(pris[i]), j);
15176    }
15177 
15178    memset(pris, 0, sizeof(pris));
15179    for (i = 0; i < NUM_SPANS; i++) {
15180       sig_pri_init_pri(&pris[i].pri);
15181    }
15182    pri_set_error(dahdi_pri_error);
15183    pri_set_message(dahdi_pri_message);
15184 #endif
15185 #if defined(HAVE_SS7)
15186    for (i = 0; i < NUM_SPANS; i++) {
15187       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15188          dahdi_close_ss7_fd(&(linksets[i]), j);
15189    }
15190 
15191    memset(linksets, 0, sizeof(linksets));
15192    for (i = 0; i < NUM_SPANS; i++) {
15193       sig_ss7_init_linkset(&linksets[i].ss7);
15194    }
15195    ss7_set_error(dahdi_ss7_error);
15196    ss7_set_message(dahdi_ss7_message);
15197 #endif   /* defined(HAVE_SS7) */
15198 
15199    if (setup_dahdi(2) != 0) {
15200       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15201       ast_mutex_unlock(&ss_thread_lock);
15202       return 1;
15203    }
15204    ast_mutex_unlock(&ss_thread_lock);
15205    ast_mutex_unlock(&restart_lock);
15206    return 0;
15207 }
15208 
15209 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15210 {
15211    switch (cmd) {
15212    case CLI_INIT:
15213       e->command = "dahdi restart";
15214       e->usage =
15215          "Usage: dahdi restart\n"
15216          "  Restarts the DAHDI channels: destroys them all and then\n"
15217          "  re-reads them from chan_dahdi.conf.\n"
15218          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15219          "";
15220       return NULL;
15221    case CLI_GENERATE:
15222       return NULL;
15223    }
15224    if (a->argc != 2)
15225       return CLI_SHOWUSAGE;
15226 
15227    if (dahdi_restart() != 0)
15228       return CLI_FAILURE;
15229    return CLI_SUCCESS;
15230 }
15231 
15232 static int action_dahdirestart(struct mansession *s, const struct message *m)
15233 {
15234    if (dahdi_restart() != 0) {
15235       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15236       return 1;
15237    }
15238    astman_send_ack(s, m, "DAHDIRestart: Success");
15239    return 0;
15240 }
15241 
15242 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15243 {
15244 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15245 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15246    unsigned int targetnum = 0;
15247    int filtertype = 0;
15248    struct dahdi_pvt *tmp = NULL;
15249    char tmps[20] = "";
15250    char statestr[20] = "";
15251    char blockstr[20] = "";
15252 
15253    switch (cmd) {
15254    case CLI_INIT:
15255       e->command = "dahdi show channels [group|context]";
15256       e->usage =
15257          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15258          "  Shows a list of available channels with optional filtering\n"
15259          "  <group> must be a number between 0 and 63\n";
15260       return NULL;
15261    case CLI_GENERATE:
15262       return NULL;
15263    }
15264 
15265    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15266 
15267    if (!((a->argc == 3) || (a->argc == 5)))
15268       return CLI_SHOWUSAGE;
15269 
15270    if (a->argc == 5) {
15271       if (!strcasecmp(a->argv[3], "group")) {
15272          targetnum = atoi(a->argv[4]);
15273          if ((targetnum < 0) || (targetnum > 63))
15274             return CLI_SHOWUSAGE;
15275          targetnum = 1 << targetnum;
15276          filtertype = 1;
15277       } else if (!strcasecmp(a->argv[3], "context")) {
15278          filtertype = 2;
15279       }
15280    }
15281 
15282    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15283    ast_mutex_lock(&iflock);
15284    for (tmp = iflist; tmp; tmp = tmp->next) {
15285       if (filtertype) {
15286          switch(filtertype) {
15287          case 1: /* dahdi show channels group <group> */
15288             if (!(tmp->group & targetnum)) {
15289                continue;
15290             }
15291             break;
15292          case 2: /* dahdi show channels context <context> */
15293             if (strcasecmp(tmp->context, a->argv[4])) {
15294                continue;
15295             }
15296             break;
15297          default:
15298             break;
15299          }
15300       }
15301       if (tmp->channel > 0) {
15302          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15303       } else
15304          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15305 
15306       if (tmp->locallyblocked)
15307          blockstr[0] = 'L';
15308       else
15309          blockstr[0] = ' ';
15310 
15311       if (tmp->remotelyblocked)
15312          blockstr[1] = 'R';
15313       else
15314          blockstr[1] = ' ';
15315 
15316       blockstr[2] = '\0';
15317 
15318       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15319 
15320       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15321    }
15322    ast_mutex_unlock(&iflock);
15323    return CLI_SUCCESS;
15324 #undef FORMAT
15325 #undef FORMAT2
15326 }
15327 
15328 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15329 {
15330    int channel;
15331    struct dahdi_pvt *tmp = NULL;
15332    struct dahdi_confinfo ci;
15333    struct dahdi_params ps;
15334    int x;
15335 
15336    switch (cmd) {
15337    case CLI_INIT:
15338       e->command = "dahdi show channel";
15339       e->usage =
15340          "Usage: dahdi show channel <chan num>\n"
15341          "  Detailed information about a given channel\n";
15342       return NULL;
15343    case CLI_GENERATE:
15344       return NULL;
15345    }
15346 
15347    if (a->argc != 4)
15348       return CLI_SHOWUSAGE;
15349 
15350    channel = atoi(a->argv[3]);
15351 
15352    ast_mutex_lock(&iflock);
15353    for (tmp = iflist; tmp; tmp = tmp->next) {
15354       if (tmp->channel == channel) {
15355          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15356          ast_cli(a->fd, "Description: %s\n", tmp->description);
15357          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15358          ast_cli(a->fd, "Span: %d\n", tmp->span);
15359          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15360          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15361          ast_cli(a->fd, "Context: %s\n", tmp->context);
15362          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15363          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15364 #if defined(HAVE_PRI)
15365 #if defined(HAVE_PRI_SUBADDR)
15366          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15367 #endif   /* defined(HAVE_PRI_SUBADDR) */
15368 #endif   /* defined(HAVE_PRI) */
15369          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15370          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15371          if (tmp->vars) {
15372             struct ast_variable *v;
15373             ast_cli(a->fd, "Variables:\n");
15374             for (v = tmp->vars ; v ; v = v->next)
15375                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15376          }
15377          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15378          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15379          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15380          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15381          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15382          ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15383          ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15384          ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15385          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15386          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15387          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15388          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15389          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15390          if (tmp->busydetect) {
15391 #if defined(BUSYDETECT_TONEONLY)
15392             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15393 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15394             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15395 #endif
15396 #ifdef BUSYDETECT_DEBUG
15397             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15398 #endif
15399             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15400             ast_cli(a->fd, "    Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
15401          }
15402          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15403          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15404          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15405          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15406          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15407          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15408          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15409          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15410          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15411          ast_cli(a->fd, "Echo Cancellation:\n");
15412 
15413          if (tmp->echocancel.head.tap_length) {
15414             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15415             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15416                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15417             }
15418             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15419          } else {
15420             ast_cli(a->fd, "\tnone\n");
15421          }
15422          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15423          if (tmp->master)
15424             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15425          for (x = 0; x < MAX_SLAVES; x++) {
15426             if (tmp->slaves[x])
15427                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15428          }
15429 #ifdef HAVE_OPENR2
15430          if (tmp->mfcr2) {
15431             char calldir[OR2_MAX_PATH];
15432             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15433             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15434             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15435             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15436             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15437             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15438             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15439             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15440             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15441             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15442 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15443             ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15444             ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15445 #endif
15446             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15447 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15448             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15449 #endif
15450             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15451             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15452             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15453             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15454             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15455             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15456             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15457             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15458             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15459             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15460             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15461             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15462          }
15463 #endif
15464 #if defined(HAVE_SS7)
15465          if (tmp->ss7) {
15466             struct sig_ss7_chan *chan = tmp->sig_pvt;
15467 
15468             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15469          }
15470 #endif   /* defined(HAVE_SS7) */
15471 #ifdef HAVE_PRI
15472          if (tmp->pri) {
15473             struct sig_pri_chan *chan = tmp->sig_pvt;
15474 
15475             ast_cli(a->fd, "PRI Flags: ");
15476             if (chan->resetting)
15477                ast_cli(a->fd, "Resetting ");
15478             if (chan->call)
15479                ast_cli(a->fd, "Call ");
15480             if (chan->allocated) {
15481                ast_cli(a->fd, "Allocated ");
15482             }
15483             ast_cli(a->fd, "\n");
15484             if (tmp->logicalspan)
15485                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15486             else
15487                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15488          }
15489 #endif
15490          memset(&ci, 0, sizeof(ci));
15491          ps.channo = tmp->channel;
15492          if (tmp->subs[SUB_REAL].dfd > -1) {
15493             memset(&ci, 0, sizeof(ci));
15494             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15495                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15496             }
15497             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15498                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15499             }
15500             memset(&ps, 0, sizeof(ps));
15501             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15502                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15503             } else {
15504                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15505             }
15506          }
15507          ast_mutex_unlock(&iflock);
15508          return CLI_SUCCESS;
15509       }
15510    }
15511    ast_mutex_unlock(&iflock);
15512 
15513    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15514    return CLI_FAILURE;
15515 }
15516 
15517 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15518 {
15519    int i, j;
15520    switch (cmd) {
15521    case CLI_INIT:
15522       e->command = "dahdi show cadences";
15523       e->usage =
15524          "Usage: dahdi show cadences\n"
15525          "       Shows all cadences currently defined\n";
15526       return NULL;
15527    case CLI_GENERATE:
15528       return NULL;
15529    }
15530    for (i = 0; i < num_cadence; i++) {
15531       char output[1024];
15532       char tmp[16], tmp2[64];
15533       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15534       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15535 
15536       for (j = 0; j < 16; j++) {
15537          if (cadences[i].ringcadence[j] == 0)
15538             break;
15539          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15540          if (cidrings[i] * 2 - 1 == j)
15541             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15542          else
15543             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15544          if (j != 0)
15545             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15546          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15547       }
15548       ast_cli(a->fd,"%s\n",output);
15549    }
15550    return CLI_SUCCESS;
15551 }
15552 
15553 /* Based on irqmiss.c */
15554 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15555 {
15556    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15557    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15558    int span;
15559    int res;
15560    char alarmstr[50];
15561 
15562    int ctl;
15563    struct dahdi_spaninfo s;
15564 
15565    switch (cmd) {
15566    case CLI_INIT:
15567       e->command = "dahdi show status";
15568       e->usage =
15569          "Usage: dahdi show status\n"
15570          "       Shows a list of DAHDI cards with status\n";
15571       return NULL;
15572    case CLI_GENERATE:
15573       return NULL;
15574    }
15575    ctl = open("/dev/dahdi/ctl", O_RDWR);
15576    if (ctl < 0) {
15577       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15578       return CLI_FAILURE;
15579    }
15580    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15581 
15582    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15583       s.spanno = span;
15584       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15585       if (res) {
15586          continue;
15587       }
15588       alarmstr[0] = '\0';
15589       if (s.alarms > 0) {
15590          if (s.alarms & DAHDI_ALARM_BLUE)
15591             strcat(alarmstr, "BLU/");
15592          if (s.alarms & DAHDI_ALARM_YELLOW)
15593             strcat(alarmstr, "YEL/");
15594          if (s.alarms & DAHDI_ALARM_RED)
15595             strcat(alarmstr, "RED/");
15596          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15597             strcat(alarmstr, "LB/");
15598          if (s.alarms & DAHDI_ALARM_RECOVER)
15599             strcat(alarmstr, "REC/");
15600          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15601             strcat(alarmstr, "NOP/");
15602          if (!strlen(alarmstr))
15603             strcat(alarmstr, "UUU/");
15604          if (strlen(alarmstr)) {
15605             /* Strip trailing / */
15606             alarmstr[strlen(alarmstr) - 1] = '\0';
15607          }
15608       } else {
15609          if (s.numchans)
15610             strcpy(alarmstr, "OK");
15611          else
15612             strcpy(alarmstr, "UNCONFIGURED");
15613       }
15614 
15615       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15616          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15617          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15618          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15619          "CAS",
15620          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15621          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15622          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15623          "Unk",
15624          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15625             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15626             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15627          lbostr[s.lbo]
15628          );
15629    }
15630    close(ctl);
15631 
15632    return CLI_SUCCESS;
15633 #undef FORMAT
15634 #undef FORMAT2
15635 }
15636 
15637 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15638 {
15639    int pseudo_fd = -1;
15640    struct dahdi_versioninfo vi;
15641 
15642    switch (cmd) {
15643    case CLI_INIT:
15644       e->command = "dahdi show version";
15645       e->usage =
15646          "Usage: dahdi show version\n"
15647          "       Shows the DAHDI version in use\n";
15648       return NULL;
15649    case CLI_GENERATE:
15650       return NULL;
15651    }
15652    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15653       ast_cli(a->fd, "Failed to open control file to get version.\n");
15654       return CLI_SUCCESS;
15655    }
15656 
15657    strcpy(vi.version, "Unknown");
15658    strcpy(vi.echo_canceller, "Unknown");
15659 
15660    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15661       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15662    else
15663       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15664 
15665    close(pseudo_fd);
15666 
15667    return CLI_SUCCESS;
15668 }
15669 
15670 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15671 {
15672    int channel;
15673    int gain;
15674    int tx;
15675    struct dahdi_hwgain hwgain;
15676    struct dahdi_pvt *tmp = NULL;
15677 
15678    switch (cmd) {
15679    case CLI_INIT:
15680       e->command = "dahdi set hwgain";
15681       e->usage =
15682          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15683          "  Sets the hardware gain on a a given channel, overriding the\n"
15684          "   value provided at module loadtime, whether the channel is in\n"
15685          "   use or not.  Changes take effect immediately.\n"
15686          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15687          "   <chan num> is the channel number relative to the device\n"
15688          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15689       return NULL;
15690    case CLI_GENERATE:
15691       return NULL;
15692    }
15693 
15694    if (a->argc != 6)
15695       return CLI_SHOWUSAGE;
15696 
15697    if (!strcasecmp("rx", a->argv[3]))
15698       tx = 0; /* rx */
15699    else if (!strcasecmp("tx", a->argv[3]))
15700       tx = 1; /* tx */
15701    else
15702       return CLI_SHOWUSAGE;
15703 
15704    channel = atoi(a->argv[4]);
15705    gain = atof(a->argv[5])*10.0;
15706 
15707    ast_mutex_lock(&iflock);
15708 
15709    for (tmp = iflist; tmp; tmp = tmp->next) {
15710 
15711       if (tmp->channel != channel)
15712          continue;
15713 
15714       if (tmp->subs[SUB_REAL].dfd == -1)
15715          break;
15716 
15717       hwgain.newgain = gain;
15718       hwgain.tx = tx;
15719       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15720          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15721          ast_mutex_unlock(&iflock);
15722          return CLI_FAILURE;
15723       }
15724       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15725          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15726       break;
15727    }
15728 
15729    ast_mutex_unlock(&iflock);
15730 
15731    if (tmp)
15732       return CLI_SUCCESS;
15733 
15734    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15735    return CLI_FAILURE;
15736 
15737 }
15738 
15739 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15740 {
15741    int channel;
15742    float gain;
15743    int tx;
15744    int res;
15745    struct dahdi_pvt *tmp = NULL;
15746 
15747    switch (cmd) {
15748    case CLI_INIT:
15749       e->command = "dahdi set swgain";
15750       e->usage =
15751          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15752          "  Sets the software gain on a a given channel, overriding the\n"
15753          "   value provided at module loadtime, whether the channel is in\n"
15754          "   use or not.  Changes take effect immediately.\n"
15755          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15756          "   <chan num> is the channel number relative to the device\n"
15757          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15758       return NULL;
15759    case CLI_GENERATE:
15760       return NULL;
15761    }
15762 
15763    if (a->argc != 6)
15764       return CLI_SHOWUSAGE;
15765 
15766    if (!strcasecmp("rx", a->argv[3]))
15767       tx = 0; /* rx */
15768    else if (!strcasecmp("tx", a->argv[3]))
15769       tx = 1; /* tx */
15770    else
15771       return CLI_SHOWUSAGE;
15772 
15773    channel = atoi(a->argv[4]);
15774    gain = atof(a->argv[5]);
15775 
15776    ast_mutex_lock(&iflock);
15777    for (tmp = iflist; tmp; tmp = tmp->next) {
15778 
15779       if (tmp->channel != channel)
15780          continue;
15781 
15782       if (tmp->subs[SUB_REAL].dfd == -1)
15783          break;
15784 
15785       if (tx)
15786          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15787       else
15788          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15789 
15790       if (res) {
15791          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15792          ast_mutex_unlock(&iflock);
15793          return CLI_FAILURE;
15794       }
15795 
15796       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15797          tx ? "tx" : "rx", gain, channel);
15798       break;
15799    }
15800    ast_mutex_unlock(&iflock);
15801 
15802    if (tmp)
15803       return CLI_SUCCESS;
15804 
15805    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15806    return CLI_FAILURE;
15807 
15808 }
15809 
15810 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15811 {
15812    int channel;
15813    int on;
15814    struct dahdi_pvt *dahdi_chan = NULL;
15815 
15816    switch (cmd) {
15817    case CLI_INIT:
15818       e->command = "dahdi set dnd";
15819       e->usage =
15820          "Usage: dahdi set dnd <chan#> <on|off>\n"
15821          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15822          "  Changes take effect immediately.\n"
15823          "  <chan num> is the channel number\n"
15824          "  <on|off> Enable or disable DND mode?\n"
15825          ;
15826       return NULL;
15827    case CLI_GENERATE:
15828       return NULL;
15829    }
15830 
15831    if (a->argc != 5)
15832       return CLI_SHOWUSAGE;
15833 
15834    if ((channel = atoi(a->argv[3])) <= 0) {
15835       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15836       return CLI_SHOWUSAGE;
15837    }
15838 
15839    if (ast_true(a->argv[4]))
15840       on = 1;
15841    else if (ast_false(a->argv[4]))
15842       on = 0;
15843    else {
15844       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15845       return CLI_SHOWUSAGE;
15846    }
15847 
15848    ast_mutex_lock(&iflock);
15849    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15850       if (dahdi_chan->channel != channel)
15851          continue;
15852 
15853       /* Found the channel. Actually set it */
15854       dahdi_dnd(dahdi_chan, on);
15855       break;
15856    }
15857    ast_mutex_unlock(&iflock);
15858 
15859    if (!dahdi_chan) {
15860       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15861       return CLI_FAILURE;
15862    }
15863 
15864    return CLI_SUCCESS;
15865 }
15866 
15867 static struct ast_cli_entry dahdi_cli[] = {
15868    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15869    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15870    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15871    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15872    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15873    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15874    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15875    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15876    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15877    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15878 };
15879 
15880 #define TRANSFER  0
15881 #define HANGUP    1
15882 
15883 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15884 {
15885    if (p) {
15886       switch (mode) {
15887       case TRANSFER:
15888          p->fake_event = DAHDI_EVENT_WINKFLASH;
15889          break;
15890       case HANGUP:
15891          p->fake_event = DAHDI_EVENT_ONHOOK;
15892          break;
15893       default:
15894          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
15895       }
15896    }
15897    return 0;
15898 }
15899 static struct dahdi_pvt *find_channel(int channel)
15900 {
15901    struct dahdi_pvt *p;
15902 
15903    ast_mutex_lock(&iflock);
15904    for (p = iflist; p; p = p->next) {
15905       if (p->channel == channel) {
15906          break;
15907       }
15908    }
15909    ast_mutex_unlock(&iflock);
15910    return p;
15911 }
15912 
15913 /*!
15914  * \internal
15915  * \brief Get private struct using given numeric channel string.
15916  *
15917  * \param channel Numeric channel number string get private struct.
15918  *
15919  * \retval pvt on success.
15920  * \retval NULL on error.
15921  */
15922 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15923 {
15924    int chan_num;
15925 
15926    if (sscanf(channel, "%30d", &chan_num) != 1) {
15927       /* Not numeric string. */
15928       return NULL;
15929    }
15930 
15931    return find_channel(chan_num);
15932 }
15933 
15934 static int action_dahdidndon(struct mansession *s, const struct message *m)
15935 {
15936    struct dahdi_pvt *p;
15937    const char *channel = astman_get_header(m, "DAHDIChannel");
15938 
15939    if (ast_strlen_zero(channel)) {
15940       astman_send_error(s, m, "No channel specified");
15941       return 0;
15942    }
15943    p = find_channel_from_str(channel);
15944    if (!p) {
15945       astman_send_error(s, m, "No such channel");
15946       return 0;
15947    }
15948    dahdi_dnd(p, 1);
15949    astman_send_ack(s, m, "DND Enabled");
15950    return 0;
15951 }
15952 
15953 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15954 {
15955    struct dahdi_pvt *p;
15956    const char *channel = astman_get_header(m, "DAHDIChannel");
15957 
15958    if (ast_strlen_zero(channel)) {
15959       astman_send_error(s, m, "No channel specified");
15960       return 0;
15961    }
15962    p = find_channel_from_str(channel);
15963    if (!p) {
15964       astman_send_error(s, m, "No such channel");
15965       return 0;
15966    }
15967    dahdi_dnd(p, 0);
15968    astman_send_ack(s, m, "DND Disabled");
15969    return 0;
15970 }
15971 
15972 static int action_transfer(struct mansession *s, const struct message *m)
15973 {
15974    struct dahdi_pvt *p;
15975    const char *channel = astman_get_header(m, "DAHDIChannel");
15976 
15977    if (ast_strlen_zero(channel)) {
15978       astman_send_error(s, m, "No channel specified");
15979       return 0;
15980    }
15981    p = find_channel_from_str(channel);
15982    if (!p) {
15983       astman_send_error(s, m, "No such channel");
15984       return 0;
15985    }
15986    if (!analog_lib_handles(p->sig, 0, 0)) {
15987       astman_send_error(s, m, "Channel signaling is not analog");
15988       return 0;
15989    }
15990    dahdi_fake_event(p,TRANSFER);
15991    astman_send_ack(s, m, "DAHDITransfer");
15992    return 0;
15993 }
15994 
15995 static int action_transferhangup(struct mansession *s, const struct message *m)
15996 {
15997    struct dahdi_pvt *p;
15998    const char *channel = astman_get_header(m, "DAHDIChannel");
15999 
16000    if (ast_strlen_zero(channel)) {
16001       astman_send_error(s, m, "No channel specified");
16002       return 0;
16003    }
16004    p = find_channel_from_str(channel);
16005    if (!p) {
16006       astman_send_error(s, m, "No such channel");
16007       return 0;
16008    }
16009    if (!analog_lib_handles(p->sig, 0, 0)) {
16010       astman_send_error(s, m, "Channel signaling is not analog");
16011       return 0;
16012    }
16013    dahdi_fake_event(p,HANGUP);
16014    astman_send_ack(s, m, "DAHDIHangup");
16015    return 0;
16016 }
16017 
16018 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16019 {
16020    struct dahdi_pvt *p;
16021    const char *channel = astman_get_header(m, "DAHDIChannel");
16022    const char *number = astman_get_header(m, "Number");
16023    int i;
16024 
16025    if (ast_strlen_zero(channel)) {
16026       astman_send_error(s, m, "No channel specified");
16027       return 0;
16028    }
16029    if (ast_strlen_zero(number)) {
16030       astman_send_error(s, m, "No number specified");
16031       return 0;
16032    }
16033    p = find_channel_from_str(channel);
16034    if (!p) {
16035       astman_send_error(s, m, "No such channel");
16036       return 0;
16037    }
16038    if (!p->owner) {
16039       astman_send_error(s, m, "Channel does not have it's owner");
16040       return 0;
16041    }
16042    for (i = 0; i < strlen(number); i++) {
16043       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16044       dahdi_queue_frame(p, &f);
16045    }
16046    astman_send_ack(s, m, "DAHDIDialOffhook");
16047    return 0;
16048 }
16049 
16050 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16051 {
16052    struct dahdi_pvt *tmp = NULL;
16053    const char *id = astman_get_header(m, "ActionID");
16054    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16055    char idText[256] = "";
16056    int channels = 0;
16057    int dahdichanquery;
16058 
16059    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16060       /* Not numeric string. */
16061       dahdichanquery = -1;
16062    }
16063 
16064    astman_send_ack(s, m, "DAHDI channel status will follow");
16065    if (!ast_strlen_zero(id))
16066       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16067 
16068    ast_mutex_lock(&iflock);
16069 
16070    for (tmp = iflist; tmp; tmp = tmp->next) {
16071       if (tmp->channel > 0) {
16072          int alm;
16073 
16074          /* If a specific channel is queried for, only deliver status for that channel */
16075          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16076             continue;
16077 
16078          alm = get_alarms(tmp);
16079          channels++;
16080          if (tmp->owner) {
16081             /* Add data if we have a current call */
16082             astman_append(s,
16083                "Event: DAHDIShowChannels\r\n"
16084                "DAHDIChannel: %d\r\n"
16085                "Channel: %s\r\n"
16086                "Uniqueid: %s\r\n"
16087                "AccountCode: %s\r\n"
16088                "Signalling: %s\r\n"
16089                "SignallingCode: %d\r\n"
16090                "Context: %s\r\n"
16091                "DND: %s\r\n"
16092                "Alarm: %s\r\n"
16093                "Description: %s\r\n"
16094                "%s"
16095                "\r\n",
16096                tmp->channel,
16097                ast_channel_name(tmp->owner),
16098                ast_channel_uniqueid(tmp->owner),
16099                ast_channel_accountcode(tmp->owner),
16100                sig2str(tmp->sig),
16101                tmp->sig,
16102                tmp->context,
16103                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16104                alarm2str(alm),
16105                tmp->description, idText);
16106          } else {
16107             astman_append(s,
16108                "Event: DAHDIShowChannels\r\n"
16109                "DAHDIChannel: %d\r\n"
16110                "Signalling: %s\r\n"
16111                "SignallingCode: %d\r\n"
16112                "Context: %s\r\n"
16113                "DND: %s\r\n"
16114                "Alarm: %s\r\n"
16115                "Description: %s\r\n"
16116                "%s"
16117                "\r\n",
16118                tmp->channel, sig2str(tmp->sig), tmp->sig,
16119                tmp->context,
16120                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16121                alarm2str(alm),
16122                tmp->description, idText);
16123          }
16124       }
16125    }
16126 
16127    ast_mutex_unlock(&iflock);
16128 
16129    astman_append(s,
16130       "Event: DAHDIShowChannelsComplete\r\n"
16131       "%s"
16132       "Items: %d\r\n"
16133       "\r\n",
16134       idText,
16135       channels);
16136    return 0;
16137 }
16138 
16139 #if defined(HAVE_PRI)
16140 static int action_prishowspans(struct mansession *s, const struct message *m)
16141 {
16142    int count;
16143    int idx;
16144    int span_query;
16145    struct dahdi_pri *dspan;
16146    const char *id = astman_get_header(m, "ActionID");
16147    const char *span_str = astman_get_header(m, "Span");
16148    char action_id[256];
16149    const char *show_cmd = "PRIShowSpans";
16150 
16151    /* NOTE: Asking for span 0 gets all spans. */
16152    if (!ast_strlen_zero(span_str)) {
16153       span_query = atoi(span_str);
16154    } else {
16155       span_query = 0;
16156    }
16157 
16158    if (!ast_strlen_zero(id)) {
16159       snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16160    } else {
16161       action_id[0] = '\0';
16162    }
16163 
16164    astman_send_ack(s, m, "Span status will follow");
16165 
16166    count = 0;
16167    for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16168       dspan = &pris[idx];
16169 
16170       /* If a specific span is asked for, only deliver status for that span. */
16171       if (0 < span_query && dspan->pri.span != span_query) {
16172          continue;
16173       }
16174 
16175       if (dspan->pri.pri) {
16176          count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16177             action_id);
16178       }
16179    }
16180 
16181    astman_append(s,
16182       "Event: %sComplete\r\n"
16183       "Items: %d\r\n"
16184       "%s"
16185       "\r\n",
16186       show_cmd,
16187       count,
16188       action_id);
16189    return 0;
16190 }
16191 #endif   /* defined(HAVE_PRI) */
16192 
16193 #if defined(HAVE_SS7)
16194 static int linkset_addsigchan(int sigchan)
16195 {
16196    struct dahdi_ss7 *link;
16197    int res;
16198    int curfd;
16199    struct dahdi_params params;
16200    struct dahdi_bufferinfo bi;
16201    struct dahdi_spaninfo si;
16202 
16203    if (sigchan < 0) {
16204       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16205       return -1;
16206    }
16207    if (cur_ss7type < 0) {
16208       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16209       return -1;
16210    }
16211    if (cur_pointcode < 0) {
16212       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16213       return -1;
16214    }
16215    if (cur_adjpointcode < 0) {
16216       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16217       return -1;
16218    }
16219    if (cur_defaultdpc < 0) {
16220       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16221       return -1;
16222    }
16223    if (cur_networkindicator < 0) {
16224       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16225       return -1;
16226    }
16227    link = ss7_resolve_linkset(cur_linkset);
16228    if (!link) {
16229       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16230       return -1;
16231    }
16232    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16233       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16234       return -1;
16235    }
16236 
16237    curfd = link->ss7.numsigchans;
16238 
16239    /* Open signaling channel */
16240    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16241    if (link->ss7.fds[curfd] < 0) {
16242       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16243          strerror(errno));
16244       return -1;
16245    }
16246    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16247       dahdi_close_ss7_fd(link, curfd);
16248       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16249          strerror(errno));
16250       return -1;
16251    }
16252 
16253    /* Get signaling channel parameters */
16254    memset(&params, 0, sizeof(params));
16255    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16256    if (res) {
16257       dahdi_close_ss7_fd(link, curfd);
16258       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16259          strerror(errno));
16260       return -1;
16261    }
16262    if (params.sigtype != DAHDI_SIG_HDLCFCS
16263       && params.sigtype != DAHDI_SIG_HARDHDLC
16264       && params.sigtype != DAHDI_SIG_MTP2) {
16265       dahdi_close_ss7_fd(link, curfd);
16266       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16267       return -1;
16268    }
16269 
16270    /* Set signaling channel buffer policy. */
16271    memset(&bi, 0, sizeof(bi));
16272    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16273    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16274    bi.numbufs = 32;
16275    bi.bufsize = 512;
16276    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16277       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16278          sigchan, strerror(errno));
16279       dahdi_close_ss7_fd(link, curfd);
16280       return -1;
16281    }
16282 
16283    /* Get current signaling channel alarm status. */
16284    memset(&si, 0, sizeof(si));
16285    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16286    if (res) {
16287       dahdi_close_ss7_fd(link, curfd);
16288       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16289          strerror(errno));
16290    }
16291 
16292    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16293       (params.sigtype == DAHDI_SIG_MTP2)
16294          ? SS7_TRANSPORT_DAHDIMTP2
16295          : SS7_TRANSPORT_DAHDIDCHAN,
16296       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16297    if (res) {
16298       dahdi_close_ss7_fd(link, curfd);
16299       return -1;
16300    }
16301 
16302    ++link->ss7.numsigchans;
16303 
16304    return 0;
16305 }
16306 #endif   /* defined(HAVE_SS7) */
16307 
16308 #if defined(HAVE_SS7)
16309 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16310 {
16311    int span;
16312    switch (cmd) {
16313    case CLI_INIT:
16314       e->command = "ss7 set debug {on|off} linkset";
16315       e->usage =
16316          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16317          "       Enables debugging on a given SS7 linkset\n";
16318       return NULL;
16319    case CLI_GENERATE:
16320       return NULL;
16321    }
16322    if (a->argc < 6)
16323       return CLI_SHOWUSAGE;
16324    span = atoi(a->argv[5]);
16325    if ((span < 1) || (span > NUM_SPANS)) {
16326       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16327       return CLI_SUCCESS;
16328    }
16329    if (!linksets[span-1].ss7.ss7) {
16330       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16331    } else {
16332       if (!strcasecmp(a->argv[3], "on")) {
16333          linksets[span - 1].ss7.debug = 1;
16334          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16335          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16336       } else {
16337          linksets[span - 1].ss7.debug = 0;
16338          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16339          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16340       }
16341    }
16342 
16343    return CLI_SUCCESS;
16344 }
16345 #endif   /* defined(HAVE_SS7) */
16346 
16347 #if defined(HAVE_SS7)
16348 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16349 {
16350    int linkset, cic;
16351    int blocked = -1, i;
16352    switch (cmd) {
16353    case CLI_INIT:
16354       e->command = "ss7 block cic";
16355       e->usage =
16356          "Usage: ss7 block cic <linkset> <CIC>\n"
16357          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16358       return NULL;
16359    case CLI_GENERATE:
16360       return NULL;
16361    }
16362    if (a->argc == 5)
16363       linkset = atoi(a->argv[3]);
16364    else
16365       return CLI_SHOWUSAGE;
16366 
16367    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16368       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16369       return CLI_SUCCESS;
16370    }
16371 
16372    if (!linksets[linkset-1].ss7.ss7) {
16373       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16374       return CLI_SUCCESS;
16375    }
16376 
16377    cic = atoi(a->argv[4]);
16378 
16379    if (cic < 1) {
16380       ast_cli(a->fd, "Invalid CIC specified!\n");
16381       return CLI_SUCCESS;
16382    }
16383 
16384    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16385       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16386          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16387          if (!blocked) {
16388             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16389             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16390             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16391          }
16392       }
16393    }
16394 
16395    if (blocked < 0) {
16396       ast_cli(a->fd, "Invalid CIC specified!\n");
16397       return CLI_SUCCESS;
16398    }
16399 
16400    if (!blocked)
16401       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16402    else
16403       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16404 
16405    /* Break poll on the linkset so it sends our messages */
16406    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16407 
16408    return CLI_SUCCESS;
16409 }
16410 #endif   /* defined(HAVE_SS7) */
16411 
16412 #if defined(HAVE_SS7)
16413 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16414 {
16415    int linkset;
16416    int i;
16417    switch (cmd) {
16418    case CLI_INIT:
16419       e->command = "ss7 block linkset";
16420       e->usage =
16421          "Usage: ss7 block linkset <linkset number>\n"
16422          "       Sends a remote blocking request for all CICs on the given linkset\n";
16423       return NULL;
16424    case CLI_GENERATE:
16425       return NULL;
16426    }
16427    if (a->argc == 4)
16428       linkset = atoi(a->argv[3]);
16429    else
16430       return CLI_SHOWUSAGE;
16431 
16432    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16433       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16434       return CLI_SUCCESS;
16435    }
16436 
16437    if (!linksets[linkset-1].ss7.ss7) {
16438       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16439       return CLI_SUCCESS;
16440    }
16441 
16442    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16443       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16444       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16445       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16446       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16447    }
16448 
16449    /* Break poll on the linkset so it sends our messages */
16450    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16451 
16452    return CLI_SUCCESS;
16453 }
16454 #endif   /* defined(HAVE_SS7) */
16455 
16456 #if defined(HAVE_SS7)
16457 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16458 {
16459    int linkset, cic;
16460    int i, blocked = -1;
16461    switch (cmd) {
16462    case CLI_INIT:
16463       e->command = "ss7 unblock cic";
16464       e->usage =
16465          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16466          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16467       return NULL;
16468    case CLI_GENERATE:
16469       return NULL;
16470    }
16471 
16472    if (a->argc == 5)
16473       linkset = atoi(a->argv[3]);
16474    else
16475       return CLI_SHOWUSAGE;
16476 
16477    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16478       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16479       return CLI_SUCCESS;
16480    }
16481 
16482    if (!linksets[linkset-1].ss7.ss7) {
16483       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16484       return CLI_SUCCESS;
16485    }
16486 
16487    cic = atoi(a->argv[4]);
16488 
16489    if (cic < 1) {
16490       ast_cli(a->fd, "Invalid CIC specified!\n");
16491       return CLI_SUCCESS;
16492    }
16493 
16494    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16495       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16496          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16497          if (blocked) {
16498             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16499             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16500             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16501          }
16502       }
16503    }
16504 
16505    if (blocked > 0)
16506       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16507 
16508    /* Break poll on the linkset so it sends our messages */
16509    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16510 
16511    return CLI_SUCCESS;
16512 }
16513 #endif   /* defined(HAVE_SS7) */
16514 
16515 #if defined(HAVE_SS7)
16516 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16517 {
16518    int linkset;
16519    int i;
16520    switch (cmd) {
16521    case CLI_INIT:
16522       e->command = "ss7 unblock linkset";
16523       e->usage =
16524          "Usage: ss7 unblock linkset <linkset number>\n"
16525          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16526       return NULL;
16527    case CLI_GENERATE:
16528       return NULL;
16529    }
16530 
16531    if (a->argc == 4)
16532       linkset = atoi(a->argv[3]);
16533    else
16534       return CLI_SHOWUSAGE;
16535 
16536    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16537       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16538       return CLI_SUCCESS;
16539    }
16540 
16541    if (!linksets[linkset-1].ss7.ss7) {
16542       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16543       return CLI_SUCCESS;
16544    }
16545 
16546    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16547       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16548       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16549       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16550       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16551    }
16552 
16553    /* Break poll on the linkset so it sends our messages */
16554    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16555 
16556    return CLI_SUCCESS;
16557 }
16558 #endif   /* defined(HAVE_SS7) */
16559 
16560 #if defined(HAVE_SS7)
16561 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16562 {
16563    int linkset;
16564    struct sig_ss7_linkset *ss7;
16565    switch (cmd) {
16566    case CLI_INIT:
16567       e->command = "ss7 show linkset";
16568       e->usage =
16569          "Usage: ss7 show linkset <span>\n"
16570          "       Shows the status of an SS7 linkset.\n";
16571       return NULL;
16572    case CLI_GENERATE:
16573       return NULL;
16574    }
16575 
16576    if (a->argc < 4)
16577       return CLI_SHOWUSAGE;
16578    linkset = atoi(a->argv[3]);
16579    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16580       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16581       return CLI_SUCCESS;
16582    }
16583    ss7 = &linksets[linkset - 1].ss7;
16584    if (!ss7->ss7) {
16585       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16586       return CLI_SUCCESS;
16587    }
16588 
16589    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16590 
16591    return CLI_SUCCESS;
16592 }
16593 #endif   /* defined(HAVE_SS7) */
16594 
16595 #if defined(HAVE_SS7)
16596 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16597 {
16598    int linkset;
16599 
16600    switch (cmd) {
16601    case CLI_INIT:
16602       e->command = "ss7 show channels";
16603       e->usage =
16604          "Usage: ss7 show channels\n"
16605          "       Displays SS7 channel information at a glance.\n";
16606       return NULL;
16607    case CLI_GENERATE:
16608       return NULL;
16609    }
16610 
16611    if (a->argc != 3)
16612       return CLI_SHOWUSAGE;
16613 
16614    sig_ss7_cli_show_channels_header(a->fd);
16615    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16616       if (linksets[linkset].ss7.ss7) {
16617          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16618       }
16619    }
16620    return CLI_SUCCESS;
16621 }
16622 #endif   /* defined(HAVE_SS7) */
16623 
16624 #if defined(HAVE_SS7)
16625 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16626 {
16627    switch (cmd) {
16628    case CLI_INIT:
16629       e->command = "ss7 show version";
16630       e->usage =
16631          "Usage: ss7 show version\n"
16632          "  Show the libss7 version\n";
16633       return NULL;
16634    case CLI_GENERATE:
16635       return NULL;
16636    }
16637 
16638    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16639 
16640    return CLI_SUCCESS;
16641 }
16642 #endif   /* defined(HAVE_SS7) */
16643 
16644 #if defined(HAVE_SS7)
16645 static struct ast_cli_entry dahdi_ss7_cli[] = {
16646    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16647    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16648    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16649    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16650    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16651    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16652    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16653    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16654 };
16655 #endif   /* defined(HAVE_SS7) */
16656 
16657 #if defined(HAVE_PRI)
16658 #if defined(HAVE_PRI_CCSS)
16659 /*!
16660  * \internal
16661  * \brief CC agent initialization.
16662  * \since 1.8
16663  *
16664  * \param agent CC core agent control.
16665  * \param chan Original channel the agent will attempt to recall.
16666  *
16667  * \details
16668  * This callback is called when the CC core is initialized.  Agents should allocate
16669  * any private data necessary for the call and assign it to the private_data
16670  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16671  * specific agent type, they should be set in this function as well.
16672  *
16673  * \retval 0 on success.
16674  * \retval -1 on error.
16675  */
16676 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16677 {
16678    struct dahdi_pvt *pvt;
16679    struct sig_pri_chan *pvt_chan;
16680    int res;
16681 
16682    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16683 
16684    pvt = chan->tech_pvt;
16685    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16686       pvt_chan = pvt->sig_pvt;
16687    } else {
16688       pvt_chan = NULL;
16689    }
16690    if (!pvt_chan) {
16691       return -1;
16692    }
16693 
16694    ast_module_ref(ast_module_info->self);
16695 
16696    res = sig_pri_cc_agent_init(agent, pvt_chan);
16697    if (res) {
16698       ast_module_unref(ast_module_info->self);
16699    }
16700    return res;
16701 }
16702 #endif   /* defined(HAVE_PRI_CCSS) */
16703 #endif   /* defined(HAVE_PRI) */
16704 
16705 #if defined(HAVE_PRI)
16706 #if defined(HAVE_PRI_CCSS)
16707 /*!
16708  * \internal
16709  * \brief Destroy private data on the agent.
16710  * \since 1.8
16711  *
16712  * \param agent CC core agent control.
16713  *
16714  * \details
16715  * The core will call this function upon completion
16716  * or failure of CC.
16717  *
16718  * \return Nothing
16719  */
16720 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16721 {
16722    sig_pri_cc_agent_destructor(agent);
16723 
16724    ast_module_unref(ast_module_info->self);
16725 }
16726 #endif   /* defined(HAVE_PRI_CCSS) */
16727 #endif   /* defined(HAVE_PRI) */
16728 
16729 #if defined(HAVE_PRI)
16730 #if defined(HAVE_PRI_CCSS)
16731 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16732    .type = dahdi_pri_cc_type,
16733    .init = dahdi_pri_cc_agent_init,
16734    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16735    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16736    .respond = sig_pri_cc_agent_req_rsp,
16737    .status_request = sig_pri_cc_agent_status_req,
16738    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16739    .party_b_free = sig_pri_cc_agent_party_b_free,
16740    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16741    .callee_available = sig_pri_cc_agent_callee_available,
16742    .destructor = dahdi_pri_cc_agent_destructor,
16743 };
16744 #endif   /* defined(HAVE_PRI_CCSS) */
16745 #endif   /* defined(HAVE_PRI) */
16746 
16747 #if defined(HAVE_PRI)
16748 #if defined(HAVE_PRI_CCSS)
16749 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16750    .type = dahdi_pri_cc_type,
16751    .request_cc = sig_pri_cc_monitor_req_cc,
16752    .suspend = sig_pri_cc_monitor_suspend,
16753    .unsuspend = sig_pri_cc_monitor_unsuspend,
16754    .status_response = sig_pri_cc_monitor_status_rsp,
16755    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16756    .destructor = sig_pri_cc_monitor_destructor,
16757 };
16758 #endif   /* defined(HAVE_PRI_CCSS) */
16759 #endif   /* defined(HAVE_PRI) */
16760 
16761 static int __unload_module(void)
16762 {
16763    struct dahdi_pvt *p;
16764 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16765    int i, j;
16766 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16767 
16768 #ifdef HAVE_PRI
16769    for (i = 0; i < NUM_SPANS; i++) {
16770       if (pris[i].pri.master != AST_PTHREADT_NULL)
16771          pthread_cancel(pris[i].pri.master);
16772    }
16773    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16774    ast_unregister_application(dahdi_send_keypad_facility_app);
16775 #ifdef HAVE_PRI_PROG_W_CAUSE
16776    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16777 #endif
16778 #endif
16779 #if defined(HAVE_SS7)
16780    for (i = 0; i < NUM_SPANS; i++) {
16781       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16782          pthread_cancel(linksets[i].ss7.master);
16783       }
16784    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16785 #endif   /* defined(HAVE_SS7) */
16786 #if defined(HAVE_OPENR2)
16787    dahdi_r2_destroy_links();
16788    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16789    ast_unregister_application(dahdi_accept_r2_call_app);
16790 #endif
16791 
16792    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16793    ast_manager_unregister("DAHDIDialOffhook");
16794    ast_manager_unregister("DAHDIHangup");
16795    ast_manager_unregister("DAHDITransfer");
16796    ast_manager_unregister("DAHDIDNDoff");
16797    ast_manager_unregister("DAHDIDNDon");
16798    ast_manager_unregister("DAHDIShowChannels");
16799    ast_manager_unregister("DAHDIRestart");
16800 #if defined(HAVE_PRI)
16801    ast_manager_unregister("PRIShowSpans");
16802 #endif   /* defined(HAVE_PRI) */
16803    ast_data_unregister(NULL);
16804    ast_channel_unregister(&dahdi_tech);
16805 
16806    /* Hangup all interfaces if they have an owner */
16807    ast_mutex_lock(&iflock);
16808    for (p = iflist; p; p = p->next) {
16809       if (p->owner)
16810          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16811    }
16812    ast_mutex_unlock(&iflock);
16813 
16814    ast_mutex_lock(&monlock);
16815    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16816       pthread_cancel(monitor_thread);
16817       pthread_kill(monitor_thread, SIGURG);
16818       pthread_join(monitor_thread, NULL);
16819    }
16820    monitor_thread = AST_PTHREADT_STOP;
16821    ast_mutex_unlock(&monlock);
16822 
16823    destroy_all_channels();
16824 
16825 #if defined(HAVE_PRI)
16826    for (i = 0; i < NUM_SPANS; i++) {
16827       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16828          pthread_join(pris[i].pri.master, NULL);
16829       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16830          dahdi_close_pri_fd(&(pris[i]), j);
16831       }
16832       sig_pri_stop_pri(&pris[i].pri);
16833    }
16834 #if defined(HAVE_PRI_CCSS)
16835    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16836    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16837 #endif   /* defined(HAVE_PRI_CCSS) */
16838    sig_pri_unload();
16839 #endif
16840 
16841 #if defined(HAVE_SS7)
16842    for (i = 0; i < NUM_SPANS; i++) {
16843       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16844          pthread_join(linksets[i].ss7.master, NULL);
16845       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16846          dahdi_close_ss7_fd(&(linksets[i]), j);
16847       }
16848    }
16849 #endif   /* defined(HAVE_SS7) */
16850    ast_cond_destroy(&ss_thread_complete);
16851 
16852    dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
16853    return 0;
16854 }
16855 
16856 static int unload_module(void)
16857 {
16858 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16859    int y;
16860 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16861 #ifdef HAVE_PRI
16862    for (y = 0; y < NUM_SPANS; y++)
16863       ast_mutex_destroy(&pris[y].pri.lock);
16864 #endif
16865 #if defined(HAVE_SS7)
16866    for (y = 0; y < NUM_SPANS; y++)
16867       ast_mutex_destroy(&linksets[y].ss7.lock);
16868 #endif   /* defined(HAVE_SS7) */
16869    return __unload_module();
16870 }
16871 
16872 static void string_replace(char *str, int char1, int char2)
16873 {
16874    for (; *str; str++) {
16875       if (*str == char1) {
16876          *str = char2;
16877       }
16878    }
16879 }
16880 
16881 static char *parse_spanchan(char *chanstr, char **subdir)
16882 {
16883    char *p;
16884 
16885    if ((p = strrchr(chanstr, '!')) == NULL) {
16886       *subdir = NULL;
16887       return chanstr;
16888    }
16889    *p++ = '\0';
16890    string_replace(chanstr, '!', '/');
16891    *subdir = chanstr;
16892    return p;
16893 }
16894 
16895 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16896 {
16897    char *c, *chan;
16898    char *subdir;
16899    int x, start, finish;
16900    struct dahdi_pvt *tmp;
16901 
16902    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16903       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16904       return -1;
16905    }
16906 
16907    c = ast_strdupa(value);
16908    c = parse_spanchan(c, &subdir);
16909 
16910    while ((chan = strsep(&c, ","))) {
16911       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16912          /* Range */
16913       } else if (sscanf(chan, "%30d", &start)) {
16914          /* Just one */
16915          finish = start;
16916       } else if (!strcasecmp(chan, "pseudo")) {
16917          finish = start = CHAN_PSEUDO;
16918          if (found_pseudo)
16919             *found_pseudo = 1;
16920       } else {
16921          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16922          return -1;
16923       }
16924       if (finish < start) {
16925          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16926          x = finish;
16927          finish = start;
16928          start = x;
16929       }
16930 
16931       for (x = start; x <= finish; x++) {
16932          char fn[PATH_MAX];
16933          int real_channel = x;
16934 
16935          if (!ast_strlen_zero(subdir)) {
16936             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16937             if (real_channel < 0) {
16938                if (conf->ignore_failed_channels) {
16939                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16940                         subdir, x, real_channel);
16941                   continue;
16942                } else {
16943                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16944                         subdir, x, real_channel);
16945                   return -1;
16946                }
16947             }
16948          }
16949          tmp = mkintf(real_channel, conf, reload);
16950 
16951          if (tmp) {
16952             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16953          } else {
16954             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16955                   (reload == 1) ? "reconfigure" : "register", value);
16956             return -1;
16957          }
16958       }
16959    }
16960 
16961    return 0;
16962 }
16963 
16964 /** The length of the parameters list of 'dahdichan'.
16965  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16966 #define MAX_CHANLIST_LEN 80
16967 
16968 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16969 {
16970    char *parse = ast_strdupa(data);
16971    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16972    unsigned int param_count;
16973    unsigned int x;
16974 
16975    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16976       return;
16977 
16978    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16979 
16980    /* first parameter is tap length, process it here */
16981 
16982    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16983 
16984    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16985       confp->chan.echocancel.head.tap_length = x;
16986    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16987       confp->chan.echocancel.head.tap_length = 128;
16988 
16989    /* now process any remaining parameters */
16990 
16991    for (x = 1; x < param_count; x++) {
16992       struct {
16993          char *name;
16994          char *value;
16995       } param;
16996 
16997       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16998          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16999          continue;
17000       }
17001 
17002       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17003          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17004          continue;
17005       }
17006 
17007       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17008 
17009       if (param.value) {
17010          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17011             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17012             continue;
17013          }
17014       }
17015       confp->chan.echocancel.head.param_count++;
17016    }
17017 }
17018 
17019 #if defined(HAVE_PRI)
17020 #if defined(HAVE_PRI_DISPLAY_TEXT)
17021 /*!
17022  * \internal
17023  * \brief Determine the configured display text options.
17024  * \since 10.0
17025  *
17026  * \param value Configuration value string.
17027  *
17028  * \return Configured display text option flags.
17029  */
17030 static unsigned long dahdi_display_text_option(const char *value)
17031 {
17032    char *val_str;
17033    char *opt_str;
17034    unsigned long options;
17035 
17036    options = 0;
17037    val_str = ast_strdupa(value);
17038 
17039    for (;;) {
17040       opt_str = strsep(&val_str, ",");
17041       if (!opt_str) {
17042          break;
17043       }
17044       opt_str = ast_strip(opt_str);
17045       if (!*opt_str) {
17046          continue;
17047       }
17048 
17049       if (!strcasecmp(opt_str, "block")) {
17050          options |= PRI_DISPLAY_OPTION_BLOCK;
17051       } else if (!strcasecmp(opt_str, "name_initial")) {
17052          options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17053       } else if (!strcasecmp(opt_str, "name_update")) {
17054          options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17055       } else if (!strcasecmp(opt_str, "name")) {
17056          options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17057       } else if (!strcasecmp(opt_str, "text")) {
17058          options |= PRI_DISPLAY_OPTION_TEXT;
17059       }
17060    }
17061    return options;
17062 }
17063 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
17064 #endif   /* defined(HAVE_PRI) */
17065 
17066 #if defined(HAVE_PRI)
17067 #if defined(HAVE_PRI_DATETIME_SEND)
17068 /*!
17069  * \internal
17070  * \brief Determine the configured date/time send policy option.
17071  * \since 10.0
17072  *
17073  * \param value Configuration value string.
17074  *
17075  * \return Configured date/time send policy option.
17076  */
17077 static int dahdi_datetime_send_option(const char *value)
17078 {
17079    int option;
17080 
17081    option = PRI_DATE_TIME_SEND_DEFAULT;
17082 
17083    if (ast_false(value)) {
17084       option = PRI_DATE_TIME_SEND_NO;
17085    } else if (!strcasecmp(value, "date")) {
17086       option = PRI_DATE_TIME_SEND_DATE;
17087    } else if (!strcasecmp(value, "date_hh")) {
17088       option = PRI_DATE_TIME_SEND_DATE_HH;
17089    } else if (!strcasecmp(value, "date_hhmm")) {
17090       option = PRI_DATE_TIME_SEND_DATE_HHMM;
17091    } else if (!strcasecmp(value, "date_hhmmss")) {
17092       option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17093    }
17094 
17095    return option;
17096 }
17097 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
17098 #endif   /* defined(HAVE_PRI) */
17099 
17100 /*! process_dahdi() - ignore keyword 'channel' and similar */
17101 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17102 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17103 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17104 
17105 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17106 {
17107    int count_pattern = 0;
17108    int norval = 0;
17109    char *temp = NULL;
17110 
17111    for (; ;) {
17112       /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
17113       if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) { 
17114          ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17115          break;
17116       }
17117 
17118       busy_cadence->pattern[count_pattern] = norval; 
17119       
17120       count_pattern++;
17121       if (count_pattern == 4) {
17122          break;
17123       }
17124 
17125       temp = strchr(v->value, ',');
17126       if (temp == NULL) {
17127          break;
17128       }
17129       v->value = temp + 1;
17130    }
17131    busy_cadence->length = count_pattern;
17132 
17133    if (count_pattern % 2 != 0) { 
17134       /* The pattern length must be divisible by two */
17135       ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17136    }
17137    
17138 }
17139 
17140 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17141 {
17142    struct dahdi_pvt *tmp;
17143    int y;
17144    int found_pseudo = 0;
17145    struct ast_variable *dahdichan = NULL;
17146 
17147    for (; v; v = v->next) {
17148       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17149          continue;
17150 
17151       /* Create the interface list */
17152       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17153          if (options & PROC_DAHDI_OPT_NOCHAN) {
17154             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17155             continue;
17156          }
17157          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17158             if (confp->ignore_failed_channels) {
17159                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17160                continue;
17161             } else {
17162                return -1;
17163             }
17164          }
17165          ast_debug(1, "Channel '%s' configured.\n", v->value);
17166       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17167          confp->ignore_failed_channels = ast_true(v->value);
17168       } else if (!strcasecmp(v->name, "buffers")) {
17169          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17170             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17171             confp->chan.buf_no = numbufs;
17172             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17173          }
17174       } else if (!strcasecmp(v->name, "faxbuffers")) {
17175          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17176             confp->chan.usefaxbuffers = 1;
17177          }
17178       } else if (!strcasecmp(v->name, "dahdichan")) {
17179          /* Only process the last dahdichan value. */
17180          dahdichan = v;
17181       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17182          usedistinctiveringdetection = ast_true(v->value);
17183       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17184          distinctiveringaftercid = ast_true(v->value);
17185       } else if (!strcasecmp(v->name, "dring1context")) {
17186          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17187       } else if (!strcasecmp(v->name, "dring2context")) {
17188          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17189       } else if (!strcasecmp(v->name, "dring3context")) {
17190          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17191       } else if (!strcasecmp(v->name, "dring1range")) {
17192          confp->chan.drings.ringnum[0].range = atoi(v->value);
17193       } else if (!strcasecmp(v->name, "dring2range")) {
17194          confp->chan.drings.ringnum[1].range = atoi(v->value);
17195       } else if (!strcasecmp(v->name, "dring3range")) {
17196          confp->chan.drings.ringnum[2].range = atoi(v->value);
17197       } else if (!strcasecmp(v->name, "dring1")) {
17198          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]);
17199       } else if (!strcasecmp(v->name, "dring2")) {
17200          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]);
17201       } else if (!strcasecmp(v->name, "dring3")) {
17202          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]);
17203       } else if (!strcasecmp(v->name, "usecallerid")) {
17204          confp->chan.use_callerid = ast_true(v->value);
17205       } else if (!strcasecmp(v->name, "cidsignalling")) {
17206          if (!strcasecmp(v->value, "bell"))
17207             confp->chan.cid_signalling = CID_SIG_BELL;
17208          else if (!strcasecmp(v->value, "v23"))
17209             confp->chan.cid_signalling = CID_SIG_V23;
17210          else if (!strcasecmp(v->value, "dtmf"))
17211             confp->chan.cid_signalling = CID_SIG_DTMF;
17212          else if (!strcasecmp(v->value, "smdi"))
17213             confp->chan.cid_signalling = CID_SIG_SMDI;
17214          else if (!strcasecmp(v->value, "v23_jp"))
17215             confp->chan.cid_signalling = CID_SIG_V23_JP;
17216          else if (ast_true(v->value))
17217             confp->chan.cid_signalling = CID_SIG_BELL;
17218       } else if (!strcasecmp(v->name, "cidstart")) {
17219          if (!strcasecmp(v->value, "ring"))
17220             confp->chan.cid_start = CID_START_RING;
17221          else if (!strcasecmp(v->value, "polarity_in"))
17222             confp->chan.cid_start = CID_START_POLARITY_IN;
17223          else if (!strcasecmp(v->value, "polarity"))
17224             confp->chan.cid_start = CID_START_POLARITY;
17225          else if (!strcasecmp(v->value, "dtmf"))
17226             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17227          else if (ast_true(v->value))
17228             confp->chan.cid_start = CID_START_RING;
17229       } else if (!strcasecmp(v->name, "threewaycalling")) {
17230          confp->chan.threewaycalling = ast_true(v->value);
17231       } else if (!strcasecmp(v->name, "cancallforward")) {
17232          confp->chan.cancallforward = ast_true(v->value);
17233       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17234          if (ast_true(v->value))
17235             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17236          else
17237             confp->chan.dtmfrelax = 0;
17238       } else if (!strcasecmp(v->name, "mailbox")) {
17239          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17240       } else if (!strcasecmp(v->name, "description")) {
17241          ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17242       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17243          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17244             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17245          }
17246       } else if (!strcasecmp(v->name, "adsi")) {
17247          confp->chan.adsi = ast_true(v->value);
17248       } else if (!strcasecmp(v->name, "usesmdi")) {
17249          confp->chan.use_smdi = ast_true(v->value);
17250       } else if (!strcasecmp(v->name, "smdiport")) {
17251          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17252       } else if (!strcasecmp(v->name, "transfer")) {
17253          confp->chan.transfer = ast_true(v->value);
17254       } else if (!strcasecmp(v->name, "canpark")) {
17255          confp->chan.canpark = ast_true(v->value);
17256       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17257          confp->chan.echocanbridged = ast_true(v->value);
17258       } else if (!strcasecmp(v->name, "busydetect")) {
17259          confp->chan.busydetect = ast_true(v->value);
17260       } else if (!strcasecmp(v->name, "busycount")) {
17261          confp->chan.busycount = atoi(v->value);
17262       } else if (!strcasecmp(v->name, "busypattern")) {
17263          parse_busy_pattern(v, &confp->chan.busy_cadence);
17264       } else if (!strcasecmp(v->name, "callprogress")) {
17265          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17266          if (ast_true(v->value))
17267             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17268       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17269          confp->chan.waitfordialtone = atoi(v->value);
17270       } else if (!strcasecmp(v->name, "faxdetect")) {
17271          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17272          if (!strcasecmp(v->value, "incoming")) {
17273             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17274          } else if (!strcasecmp(v->value, "outgoing")) {
17275             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17276          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17277             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17278       } else if (!strcasecmp(v->name, "echocancel")) {
17279          process_echocancel(confp, v->value, v->lineno);
17280       } else if (!strcasecmp(v->name, "echotraining")) {
17281          if (sscanf(v->value, "%30d", &y) == 1) {
17282             if ((y < 10) || (y > 4000)) {
17283                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17284             } else {
17285                confp->chan.echotraining = y;
17286             }
17287          } else if (ast_true(v->value)) {
17288             confp->chan.echotraining = 400;
17289          } else
17290             confp->chan.echotraining = 0;
17291       } else if (!strcasecmp(v->name, "hidecallerid")) {
17292          confp->chan.hidecallerid = ast_true(v->value);
17293       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17294          confp->chan.hidecalleridname = ast_true(v->value);
17295       } else if (!strcasecmp(v->name, "pulsedial")) {
17296          confp->chan.pulse = ast_true(v->value);
17297       } else if (!strcasecmp(v->name, "callreturn")) {
17298          confp->chan.callreturn = ast_true(v->value);
17299       } else if (!strcasecmp(v->name, "callwaiting")) {
17300          confp->chan.callwaiting = ast_true(v->value);
17301       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17302          confp->chan.callwaitingcallerid = ast_true(v->value);
17303       } else if (!strcasecmp(v->name, "context")) {
17304          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17305       } else if (!strcasecmp(v->name, "language")) {
17306          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17307       } else if (!strcasecmp(v->name, "progzone")) {
17308          ast_copy_string(progzone, v->value, sizeof(progzone));
17309       } else if (!strcasecmp(v->name, "mohinterpret")
17310          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17311          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17312       } else if (!strcasecmp(v->name, "mohsuggest")) {
17313          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17314       } else if (!strcasecmp(v->name, "parkinglot")) {
17315          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17316       } else if (!strcasecmp(v->name, "stripmsd")) {
17317          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17318          confp->chan.stripmsd = atoi(v->value);
17319       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17320          numbufs = atoi(v->value);
17321       } else if (!strcasecmp(v->name, "group")) {
17322          confp->chan.group = ast_get_group(v->value);
17323       } else if (!strcasecmp(v->name, "callgroup")) {
17324          if (!strcasecmp(v->value, "none"))
17325             confp->chan.callgroup = 0;
17326          else
17327             confp->chan.callgroup = ast_get_group(v->value);
17328       } else if (!strcasecmp(v->name, "pickupgroup")) {
17329          if (!strcasecmp(v->value, "none"))
17330             confp->chan.pickupgroup = 0;
17331          else
17332             confp->chan.pickupgroup = ast_get_group(v->value);
17333       } else if (!strcasecmp(v->name, "setvar")) {
17334          char *varname = ast_strdupa(v->value), *varval = NULL;
17335          struct ast_variable *tmpvar;
17336          if (varname && (varval = strchr(varname, '='))) {
17337             *varval++ = '\0';
17338             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17339                tmpvar->next = confp->chan.vars;
17340                confp->chan.vars = tmpvar;
17341             }
17342          }
17343       } else if (!strcasecmp(v->name, "immediate")) {
17344          confp->chan.immediate = ast_true(v->value);
17345       } else if (!strcasecmp(v->name, "transfertobusy")) {
17346          confp->chan.transfertobusy = ast_true(v->value);
17347       } else if (!strcasecmp(v->name, "mwimonitor")) {
17348          confp->chan.mwimonitor_neon = 0;
17349          confp->chan.mwimonitor_fsk = 0;
17350          confp->chan.mwimonitor_rpas = 0;
17351          if (strcasestr(v->value, "fsk")) {
17352             confp->chan.mwimonitor_fsk = 1;
17353          }
17354          if (strcasestr(v->value, "rpas")) {
17355             confp->chan.mwimonitor_rpas = 1;
17356          }
17357          if (strcasestr(v->value, "neon")) {
17358             confp->chan.mwimonitor_neon = 1;
17359          }
17360          /* If set to true or yes, assume that simple fsk is desired */
17361          if (ast_true(v->value)) {
17362             confp->chan.mwimonitor_fsk = 1;
17363          }
17364       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17365          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17366             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17367          }
17368       } else if (!strcasecmp(v->name, "rxgain")) {
17369          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17370             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17371          }
17372       } else if (!strcasecmp(v->name, "txgain")) {
17373          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17374             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17375          }
17376       } else if (!strcasecmp(v->name, "txdrc")) {
17377          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17378             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17379          }
17380       } else if (!strcasecmp(v->name, "rxdrc")) {
17381          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17382             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17383          }
17384       } else if (!strcasecmp(v->name, "tonezone")) {
17385          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17386             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17387          }
17388       } else if (!strcasecmp(v->name, "callerid")) {
17389          if (!strcasecmp(v->value, "asreceived")) {
17390             confp->chan.cid_num[0] = '\0';
17391             confp->chan.cid_name[0] = '\0';
17392          } else {
17393             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17394          }
17395       } else if (!strcasecmp(v->name, "fullname")) {
17396          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17397       } else if (!strcasecmp(v->name, "cid_number")) {
17398          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17399       } else if (!strcasecmp(v->name, "cid_tag")) {
17400          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17401       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17402          confp->chan.dahditrcallerid = ast_true(v->value);
17403       } else if (!strcasecmp(v->name, "restrictcid")) {
17404          confp->chan.restrictcid = ast_true(v->value);
17405       } else if (!strcasecmp(v->name, "usecallingpres")) {
17406          confp->chan.use_callingpres = ast_true(v->value);
17407       } else if (!strcasecmp(v->name, "accountcode")) {
17408          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17409       } else if (!strcasecmp(v->name, "amaflags")) {
17410          y = ast_cdr_amaflags2int(v->value);
17411          if (y < 0)
17412             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17413          else
17414             confp->chan.amaflags = y;
17415       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17416          confp->chan.polarityonanswerdelay = atoi(v->value);
17417       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17418          confp->chan.answeronpolarityswitch = ast_true(v->value);
17419       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17420          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17421       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17422          confp->chan.sendcalleridafter = atoi(v->value);
17423       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17424          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17425       } else if (ast_cc_is_config_param(v->name)) {
17426          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17427       } else if (!strcasecmp(v->name, "mwisendtype")) {
17428 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17429          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17430             mwisend_rpas = 1;
17431          } else {
17432             mwisend_rpas = 0;
17433          }
17434 #else
17435          /* Default is fsk, to turn it off you must specify nofsk */
17436          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17437          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17438             confp->chan.mwisend_fsk = 0;
17439          } else {             /* Default FSK */
17440             confp->chan.mwisend_fsk = 1;
17441          }
17442          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17443             confp->chan.mwisend_rpas = 1;
17444          } else {
17445             confp->chan.mwisend_rpas = 0;
17446          }
17447          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17448             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17449          }
17450          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17451             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17452          }
17453          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17454             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17455          }
17456 #endif
17457       } else if (reload != 1) {
17458           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17459             int orig_radio = confp->chan.radio;
17460             int orig_outsigmod = confp->chan.outsigmod;
17461             int orig_auto = confp->is_sig_auto;
17462 
17463             confp->chan.radio = 0;
17464             confp->chan.outsigmod = -1;
17465             confp->is_sig_auto = 0;
17466             if (!strcasecmp(v->value, "em")) {
17467                confp->chan.sig = SIG_EM;
17468             } else if (!strcasecmp(v->value, "em_e1")) {
17469                confp->chan.sig = SIG_EM_E1;
17470             } else if (!strcasecmp(v->value, "em_w")) {
17471                confp->chan.sig = SIG_EMWINK;
17472             } else if (!strcasecmp(v->value, "fxs_ls")) {
17473                confp->chan.sig = SIG_FXSLS;
17474             } else if (!strcasecmp(v->value, "fxs_gs")) {
17475                confp->chan.sig = SIG_FXSGS;
17476             } else if (!strcasecmp(v->value, "fxs_ks")) {
17477                confp->chan.sig = SIG_FXSKS;
17478             } else if (!strcasecmp(v->value, "fxo_ls")) {
17479                confp->chan.sig = SIG_FXOLS;
17480             } else if (!strcasecmp(v->value, "fxo_gs")) {
17481                confp->chan.sig = SIG_FXOGS;
17482             } else if (!strcasecmp(v->value, "fxo_ks")) {
17483                confp->chan.sig = SIG_FXOKS;
17484             } else if (!strcasecmp(v->value, "fxs_rx")) {
17485                confp->chan.sig = SIG_FXSKS;
17486                confp->chan.radio = 1;
17487             } else if (!strcasecmp(v->value, "fxo_rx")) {
17488                confp->chan.sig = SIG_FXOLS;
17489                confp->chan.radio = 1;
17490             } else if (!strcasecmp(v->value, "fxs_tx")) {
17491                confp->chan.sig = SIG_FXSLS;
17492                confp->chan.radio = 1;
17493             } else if (!strcasecmp(v->value, "fxo_tx")) {
17494                confp->chan.sig = SIG_FXOGS;
17495                confp->chan.radio = 1;
17496             } else if (!strcasecmp(v->value, "em_rx")) {
17497                confp->chan.sig = SIG_EM;
17498                confp->chan.radio = 1;
17499             } else if (!strcasecmp(v->value, "em_tx")) {
17500                confp->chan.sig = SIG_EM;
17501                confp->chan.radio = 1;
17502             } else if (!strcasecmp(v->value, "em_rxtx")) {
17503                confp->chan.sig = SIG_EM;
17504                confp->chan.radio = 2;
17505             } else if (!strcasecmp(v->value, "em_txrx")) {
17506                confp->chan.sig = SIG_EM;
17507                confp->chan.radio = 2;
17508             } else if (!strcasecmp(v->value, "sf")) {
17509                confp->chan.sig = SIG_SF;
17510             } else if (!strcasecmp(v->value, "sf_w")) {
17511                confp->chan.sig = SIG_SFWINK;
17512             } else if (!strcasecmp(v->value, "sf_featd")) {
17513                confp->chan.sig = SIG_FEATD;
17514             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17515                confp->chan.sig = SIG_FEATDMF;
17516             } else if (!strcasecmp(v->value, "sf_featb")) {
17517                confp->chan.sig = SIG_SF_FEATB;
17518             } else if (!strcasecmp(v->value, "sf")) {
17519                confp->chan.sig = SIG_SF;
17520             } else if (!strcasecmp(v->value, "sf_rx")) {
17521                confp->chan.sig = SIG_SF;
17522                confp->chan.radio = 1;
17523             } else if (!strcasecmp(v->value, "sf_tx")) {
17524                confp->chan.sig = SIG_SF;
17525                confp->chan.radio = 1;
17526             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17527                confp->chan.sig = SIG_SF;
17528                confp->chan.radio = 2;
17529             } else if (!strcasecmp(v->value, "sf_txrx")) {
17530                confp->chan.sig = SIG_SF;
17531                confp->chan.radio = 2;
17532             } else if (!strcasecmp(v->value, "featd")) {
17533                confp->chan.sig = SIG_FEATD;
17534             } else if (!strcasecmp(v->value, "featdmf")) {
17535                confp->chan.sig = SIG_FEATDMF;
17536             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17537                confp->chan.sig = SIG_FEATDMF_TA;
17538             } else if (!strcasecmp(v->value, "e911")) {
17539                confp->chan.sig = SIG_E911;
17540             } else if (!strcasecmp(v->value, "fgccama")) {
17541                confp->chan.sig = SIG_FGC_CAMA;
17542             } else if (!strcasecmp(v->value, "fgccamamf")) {
17543                confp->chan.sig = SIG_FGC_CAMAMF;
17544             } else if (!strcasecmp(v->value, "featb")) {
17545                confp->chan.sig = SIG_FEATB;
17546 #ifdef HAVE_PRI
17547             } else if (!strcasecmp(v->value, "pri_net")) {
17548                confp->chan.sig = SIG_PRI;
17549                confp->pri.pri.nodetype = PRI_NETWORK;
17550             } else if (!strcasecmp(v->value, "pri_cpe")) {
17551                confp->chan.sig = SIG_PRI;
17552                confp->pri.pri.nodetype = PRI_CPE;
17553             } else if (!strcasecmp(v->value, "bri_cpe")) {
17554                confp->chan.sig = SIG_BRI;
17555                confp->pri.pri.nodetype = PRI_CPE;
17556             } else if (!strcasecmp(v->value, "bri_net")) {
17557                confp->chan.sig = SIG_BRI;
17558                confp->pri.pri.nodetype = PRI_NETWORK;
17559             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17560                confp->chan.sig = SIG_BRI_PTMP;
17561                confp->pri.pri.nodetype = PRI_CPE;
17562             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17563 #if defined(HAVE_PRI_CALL_HOLD)
17564                confp->chan.sig = SIG_BRI_PTMP;
17565                confp->pri.pri.nodetype = PRI_NETWORK;
17566 #else
17567                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17568 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17569 #endif
17570 #if defined(HAVE_SS7)
17571             } else if (!strcasecmp(v->value, "ss7")) {
17572                confp->chan.sig = SIG_SS7;
17573 #endif   /* defined(HAVE_SS7) */
17574 #ifdef HAVE_OPENR2
17575             } else if (!strcasecmp(v->value, "mfcr2")) {
17576                confp->chan.sig = SIG_MFCR2;
17577 #endif
17578             } else if (!strcasecmp(v->value, "auto")) {
17579                confp->is_sig_auto = 1;
17580             } else {
17581                confp->chan.outsigmod = orig_outsigmod;
17582                confp->chan.radio = orig_radio;
17583                confp->is_sig_auto = orig_auto;
17584                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17585             }
17586           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17587             if (!strcasecmp(v->value, "em")) {
17588                confp->chan.outsigmod = SIG_EM;
17589             } else if (!strcasecmp(v->value, "em_e1")) {
17590                confp->chan.outsigmod = SIG_EM_E1;
17591             } else if (!strcasecmp(v->value, "em_w")) {
17592                confp->chan.outsigmod = SIG_EMWINK;
17593             } else if (!strcasecmp(v->value, "sf")) {
17594                confp->chan.outsigmod = SIG_SF;
17595             } else if (!strcasecmp(v->value, "sf_w")) {
17596                confp->chan.outsigmod = SIG_SFWINK;
17597             } else if (!strcasecmp(v->value, "sf_featd")) {
17598                confp->chan.outsigmod = SIG_FEATD;
17599             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17600                confp->chan.outsigmod = SIG_FEATDMF;
17601             } else if (!strcasecmp(v->value, "sf_featb")) {
17602                confp->chan.outsigmod = SIG_SF_FEATB;
17603             } else if (!strcasecmp(v->value, "sf")) {
17604                confp->chan.outsigmod = SIG_SF;
17605             } else if (!strcasecmp(v->value, "featd")) {
17606                confp->chan.outsigmod = SIG_FEATD;
17607             } else if (!strcasecmp(v->value, "featdmf")) {
17608                confp->chan.outsigmod = SIG_FEATDMF;
17609             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17610                confp->chan.outsigmod = SIG_FEATDMF_TA;
17611             } else if (!strcasecmp(v->value, "e911")) {
17612                confp->chan.outsigmod = SIG_E911;
17613             } else if (!strcasecmp(v->value, "fgccama")) {
17614                confp->chan.outsigmod = SIG_FGC_CAMA;
17615             } else if (!strcasecmp(v->value, "fgccamamf")) {
17616                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17617             } else if (!strcasecmp(v->value, "featb")) {
17618                confp->chan.outsigmod = SIG_FEATB;
17619             } else {
17620                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17621             }
17622 #ifdef HAVE_PRI
17623          } else if (!strcasecmp(v->name, "pridialplan")) {
17624             if (!strcasecmp(v->value, "national")) {
17625                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17626             } else if (!strcasecmp(v->value, "unknown")) {
17627                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17628             } else if (!strcasecmp(v->value, "private")) {
17629                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17630             } else if (!strcasecmp(v->value, "international")) {
17631                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17632             } else if (!strcasecmp(v->value, "local")) {
17633                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17634             } else if (!strcasecmp(v->value, "dynamic")) {
17635                confp->pri.pri.dialplan = -1;
17636             } else if (!strcasecmp(v->value, "redundant")) {
17637                confp->pri.pri.dialplan = -2;
17638             } else {
17639                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17640             }
17641          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17642             if (!strcasecmp(v->value, "national")) {
17643                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17644             } else if (!strcasecmp(v->value, "unknown")) {
17645                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17646             } else if (!strcasecmp(v->value, "private")) {
17647                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17648             } else if (!strcasecmp(v->value, "international")) {
17649                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17650             } else if (!strcasecmp(v->value, "local")) {
17651                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17652             } else if (!strcasecmp(v->value, "from_channel")) {
17653                confp->pri.pri.localdialplan = 0;
17654             } else if (!strcasecmp(v->value, "dynamic")) {
17655                confp->pri.pri.localdialplan = -1;
17656             } else if (!strcasecmp(v->value, "redundant")) {
17657                confp->pri.pri.localdialplan = -2;
17658             } else {
17659                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17660             }
17661          } else if (!strcasecmp(v->name, "pricpndialplan")) {
17662             if (!strcasecmp(v->value, "national")) {
17663                confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
17664             } else if (!strcasecmp(v->value, "unknown")) {
17665                confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
17666             } else if (!strcasecmp(v->value, "private")) {
17667                confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
17668             } else if (!strcasecmp(v->value, "international")) {
17669                confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
17670             } else if (!strcasecmp(v->value, "local")) {
17671                confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
17672             } else if (!strcasecmp(v->value, "from_channel")) {
17673                confp->pri.pri.cpndialplan = 0;
17674             } else if (!strcasecmp(v->value, "dynamic")) {
17675                confp->pri.pri.cpndialplan = -1;
17676             } else if (!strcasecmp(v->value, "redundant")) {
17677                confp->pri.pri.cpndialplan = -2;
17678             } else {
17679                ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
17680             }
17681          } else if (!strcasecmp(v->name, "switchtype")) {
17682             if (!strcasecmp(v->value, "national"))
17683                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17684             else if (!strcasecmp(v->value, "ni1"))
17685                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17686             else if (!strcasecmp(v->value, "dms100"))
17687                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17688             else if (!strcasecmp(v->value, "4ess"))
17689                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17690             else if (!strcasecmp(v->value, "5ess"))
17691                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17692             else if (!strcasecmp(v->value, "euroisdn"))
17693                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17694             else if (!strcasecmp(v->value, "qsig"))
17695                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17696             else {
17697                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17698                return -1;
17699             }
17700          } else if (!strcasecmp(v->name, "msn")) {
17701             ast_copy_string(confp->pri.pri.msn_list, v->value,
17702                sizeof(confp->pri.pri.msn_list));
17703          } else if (!strcasecmp(v->name, "nsf")) {
17704             if (!strcasecmp(v->value, "sdn"))
17705                confp->pri.pri.nsf = PRI_NSF_SDN;
17706             else if (!strcasecmp(v->value, "megacom"))
17707                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17708             else if (!strcasecmp(v->value, "tollfreemegacom"))
17709                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17710             else if (!strcasecmp(v->value, "accunet"))
17711                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17712             else if (!strcasecmp(v->value, "none"))
17713                confp->pri.pri.nsf = PRI_NSF_NONE;
17714             else {
17715                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17716                confp->pri.pri.nsf = PRI_NSF_NONE;
17717             }
17718          } else if (!strcasecmp(v->name, "priindication")) {
17719             if (!strcasecmp(v->value, "outofband"))
17720                confp->chan.priindication_oob = 1;
17721             else if (!strcasecmp(v->value, "inband"))
17722                confp->chan.priindication_oob = 0;
17723             else
17724                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17725                   v->value, v->lineno);
17726          } else if (!strcasecmp(v->name, "priexclusive")) {
17727             confp->chan.priexclusive = ast_true(v->value);
17728          } else if (!strcasecmp(v->name, "internationalprefix")) {
17729             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17730          } else if (!strcasecmp(v->name, "nationalprefix")) {
17731             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17732          } else if (!strcasecmp(v->name, "localprefix")) {
17733             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17734          } else if (!strcasecmp(v->name, "privateprefix")) {
17735             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17736          } else if (!strcasecmp(v->name, "unknownprefix")) {
17737             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17738          } else if (!strcasecmp(v->name, "resetinterval")) {
17739             if (!strcasecmp(v->value, "never"))
17740                confp->pri.pri.resetinterval = -1;
17741             else if (atoi(v->value) >= 60)
17742                confp->pri.pri.resetinterval = atoi(v->value);
17743             else
17744                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17745                   v->value, v->lineno);
17746          } else if (!strcasecmp(v->name, "minunused")) {
17747             confp->pri.pri.minunused = atoi(v->value);
17748          } else if (!strcasecmp(v->name, "minidle")) {
17749             confp->pri.pri.minidle = atoi(v->value);
17750          } else if (!strcasecmp(v->name, "idleext")) {
17751             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17752          } else if (!strcasecmp(v->name, "idledial")) {
17753             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17754          } else if (!strcasecmp(v->name, "overlapdial")) {
17755             if (ast_true(v->value)) {
17756                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17757             } else if (!strcasecmp(v->value, "incoming")) {
17758                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17759             } else if (!strcasecmp(v->value, "outgoing")) {
17760                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17761             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17762                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17763             } else {
17764                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17765             }
17766 #ifdef HAVE_PRI_PROG_W_CAUSE
17767          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17768             if (!strcasecmp(v->value, "logical")) {
17769                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17770             } else if (!strcasecmp(v->value, "physical")) {
17771                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17772             } else {
17773                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17774             }
17775 #endif
17776          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17777             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17778 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17779          } else if (!strcasecmp(v->name, "service_message_support")) {
17780             /* assuming switchtype for this channel group has been configured already */
17781             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17782                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17783                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17784                confp->pri.pri.enable_service_message_support = 1;
17785             } else {
17786                confp->pri.pri.enable_service_message_support = 0;
17787             }
17788 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17789 #ifdef HAVE_PRI_INBANDDISCONNECT
17790          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17791             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17792 #endif
17793          } else if (!strcasecmp(v->name, "pritimer")) {
17794 #ifdef PRI_GETSET_TIMERS
17795             char tmp[20];
17796             char *timerc;
17797             char *c;
17798             int timer;
17799             int timeridx;
17800 
17801             ast_copy_string(tmp, v->value, sizeof(tmp));
17802             c = tmp;
17803             timerc = strsep(&c, ",");
17804             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17805                timeridx = pri_timer2idx(timerc);
17806                timer = atoi(c);
17807                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17808                   ast_log(LOG_WARNING,
17809                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17810                      v->lineno);
17811                } else if (!timer) {
17812                   ast_log(LOG_WARNING,
17813                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17814                      c, timerc, v->lineno);
17815                } else {
17816                   confp->pri.pri.pritimers[timeridx] = timer;
17817                }
17818             } else {
17819                ast_log(LOG_WARNING,
17820                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17821                   v->value, v->lineno);
17822             }
17823 #endif /* PRI_GETSET_TIMERS */
17824          } else if (!strcasecmp(v->name, "facilityenable")) {
17825             confp->pri.pri.facilityenable = ast_true(v->value);
17826 #if defined(HAVE_PRI_AOC_EVENTS)
17827          } else if (!strcasecmp(v->name, "aoc_enable")) {
17828             confp->pri.pri.aoc_passthrough_flag = 0;
17829             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17830                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17831             }
17832             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17833                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17834             }
17835             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17836                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17837             }
17838          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17839             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17840 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17841 #if defined(HAVE_PRI_CALL_HOLD)
17842          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17843             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17844 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17845          } else if (!strcasecmp(v->name, "moh_signaling")
17846             || !strcasecmp(v->name, "moh_signalling")) {
17847             if (!strcasecmp(v->value, "moh")) {
17848                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
17849             } else if (!strcasecmp(v->value, "notify")) {
17850                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
17851 #if defined(HAVE_PRI_CALL_HOLD)
17852             } else if (!strcasecmp(v->value, "hold")) {
17853                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
17854 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17855             } else {
17856                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
17857             }
17858 #if defined(HAVE_PRI_CCSS)
17859          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17860             if (!strcasecmp(v->value, "global")) {
17861                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17862             } else if (!strcasecmp(v->value, "specific")) {
17863                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17864             } else {
17865                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17866             }
17867          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17868             if (!strcasecmp(v->value, "release")) {
17869                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17870             } else if (!strcasecmp(v->value, "retain")) {
17871                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17872             } else if (!strcasecmp(v->value, "do_not_care")) {
17873                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17874             } else {
17875                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17876             }
17877          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17878             if (!strcasecmp(v->value, "release")) {
17879                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17880             } else if (!strcasecmp(v->value, "retain")) {
17881                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17882             } else {
17883                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17884             }
17885 #endif   /* defined(HAVE_PRI_CCSS) */
17886 #if defined(HAVE_PRI_CALL_WAITING)
17887          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17888             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17889             if (confp->pri.pri.max_call_waiting_calls < 0) {
17890                /* Negative values are not allowed. */
17891                confp->pri.pri.max_call_waiting_calls = 0;
17892             }
17893          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17894             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17895 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17896 #if defined(HAVE_PRI_MWI)
17897          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17898             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17899                sizeof(confp->pri.pri.mwi_mailboxes));
17900          } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
17901             ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
17902                sizeof(confp->pri.pri.mwi_vm_numbers));
17903 #endif   /* defined(HAVE_PRI_MWI) */
17904          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17905             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17906 #if defined(HAVE_PRI_DISPLAY_TEXT)
17907          } else if (!strcasecmp(v->name, "display_send")) {
17908             confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
17909          } else if (!strcasecmp(v->name, "display_receive")) {
17910             confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
17911 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
17912 #if defined(HAVE_PRI_MCID)
17913          } else if (!strcasecmp(v->name, "mcid_send")) {
17914             confp->pri.pri.mcid_send = ast_true(v->value);
17915 #endif   /* defined(HAVE_PRI_MCID) */
17916 #if defined(HAVE_PRI_DATETIME_SEND)
17917          } else if (!strcasecmp(v->name, "datetime_send")) {
17918             confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
17919 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
17920 #if defined(HAVE_PRI_L2_PERSISTENCE)
17921          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17922             if (!strcasecmp(v->value, "keep_up")) {
17923                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17924             } else if (!strcasecmp(v->value, "leave_down")) {
17925                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17926             } else {
17927                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17928             }
17929 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17930 #endif /* HAVE_PRI */
17931 #if defined(HAVE_SS7)
17932          } else if (!strcasecmp(v->name, "ss7type")) {
17933             if (!strcasecmp(v->value, "itu")) {
17934                cur_ss7type = SS7_ITU;
17935             } else if (!strcasecmp(v->value, "ansi")) {
17936                cur_ss7type = SS7_ANSI;
17937             } else
17938                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17939          } else if (!strcasecmp(v->name, "linkset")) {
17940             cur_linkset = atoi(v->value);
17941          } else if (!strcasecmp(v->name, "pointcode")) {
17942             cur_pointcode = parse_pointcode(v->value);
17943          } else if (!strcasecmp(v->name, "adjpointcode")) {
17944             cur_adjpointcode = parse_pointcode(v->value);
17945          } else if (!strcasecmp(v->name, "defaultdpc")) {
17946             cur_defaultdpc = parse_pointcode(v->value);
17947          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17948             cur_cicbeginswith = atoi(v->value);
17949          } else if (!strcasecmp(v->name, "networkindicator")) {
17950             if (!strcasecmp(v->value, "national"))
17951                cur_networkindicator = SS7_NI_NAT;
17952             else if (!strcasecmp(v->value, "national_spare"))
17953                cur_networkindicator = SS7_NI_NAT_SPARE;
17954             else if (!strcasecmp(v->value, "international"))
17955                cur_networkindicator = SS7_NI_INT;
17956             else if (!strcasecmp(v->value, "international_spare"))
17957                cur_networkindicator = SS7_NI_INT_SPARE;
17958             else
17959                cur_networkindicator = -1;
17960          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17961             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17962          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17963             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17964          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17965             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17966          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17967             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17968          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17969             if (!strcasecmp(v->value, "national")) {
17970                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17971             } else if (!strcasecmp(v->value, "international")) {
17972                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17973             } else if (!strcasecmp(v->value, "subscriber")) {
17974                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17975             } else if (!strcasecmp(v->value, "unknown")) {
17976                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17977             } else if (!strcasecmp(v->value, "dynamic")) {
17978                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17979             } else {
17980                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17981             }
17982          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17983             if (!strcasecmp(v->value, "national")) {
17984                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17985             } else if (!strcasecmp(v->value, "international")) {
17986                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17987             } else if (!strcasecmp(v->value, "subscriber")) {
17988                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17989             } else if (!strcasecmp(v->value, "unknown")) {
17990                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17991             } else if (!strcasecmp(v->value, "dynamic")) {
17992                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17993             } else {
17994                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17995             }
17996          } else if (!strcasecmp(v->name, "sigchan")) {
17997             int sigchan, res;
17998             sigchan = atoi(v->value);
17999             res = linkset_addsigchan(sigchan);
18000             if (res < 0)
18001                return -1;
18002 
18003          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18004             struct dahdi_ss7 *link;
18005             link = ss7_resolve_linkset(cur_linkset);
18006             if (!link) {
18007                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
18008                return -1;
18009             }
18010             if (ast_true(v->value))
18011                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18012 #endif   /* defined(HAVE_SS7) */
18013 #ifdef HAVE_OPENR2
18014          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18015             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18016             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);
18017          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18018             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18019          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18020             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18021             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18022                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18023                confp->mfcr2.variant = OR2_VAR_ITU;
18024             }
18025          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18026             confp->mfcr2.mfback_timeout = atoi(v->value);
18027             if (!confp->mfcr2.mfback_timeout) {
18028                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18029                confp->mfcr2.mfback_timeout = -1;
18030             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18031                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18032             }
18033          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18034             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18035             if (confp->mfcr2.metering_pulse_timeout > 500) {
18036                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18037             }
18038 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18039          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18040             confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18041          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18042             confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18043          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18044             confp->mfcr2.dtmf_time_on = atoi(v->value);
18045          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18046             confp->mfcr2.dtmf_time_off = atoi(v->value);
18047 #endif
18048 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18049          } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18050             confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18051 #endif
18052          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18053             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18054          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18055             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18056          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18057             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18058          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18059             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18060          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18061             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18062          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18063             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18064          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18065             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18066 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18067          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18068             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18069 #endif
18070          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18071             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18072          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18073             confp->mfcr2.max_ani = atoi(v->value);
18074             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18075                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18076             }
18077          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18078             confp->mfcr2.max_dnis = atoi(v->value);
18079             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18080                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18081             }
18082          } else if (!strcasecmp(v->name, "mfcr2_category")) {
18083             confp->mfcr2.category = openr2_proto_get_category(v->value);
18084             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18085                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18086                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18087                      v->value, v->lineno);
18088             }
18089          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18090             openr2_log_level_t tmplevel;
18091             char *clevel;
18092             char *logval = ast_strdupa(v->value);
18093             while (logval) {
18094                clevel = strsep(&logval,",");
18095                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18096                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18097                   continue;
18098                }
18099                confp->mfcr2.loglevel |= tmplevel;
18100             }
18101 #endif /* HAVE_OPENR2 */
18102          } else if (!strcasecmp(v->name, "cadence")) {
18103             /* setup to scan our argument */
18104             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18105             int i;
18106             struct dahdi_ring_cadence new_cadence;
18107             int cid_location = -1;
18108             int firstcadencepos = 0;
18109             char original_args[80];
18110             int cadence_is_ok = 1;
18111 
18112             ast_copy_string(original_args, v->value, sizeof(original_args));
18113             /* 16 cadences allowed (8 pairs) */
18114             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]);
18115 
18116             /* Cadence must be even (on/off) */
18117             if (element_count % 2 == 1) {
18118                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18119                cadence_is_ok = 0;
18120             }
18121 
18122             /* Ring cadences cannot be negative */
18123             for (i = 0; i < element_count; i++) {
18124                if (c[i] == 0) {
18125                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18126                   cadence_is_ok = 0;
18127                   break;
18128                } else if (c[i] < 0) {
18129                   if (i % 2 == 1) {
18130                      /* Silence duration, negative possibly okay */
18131                      if (cid_location == -1) {
18132                         cid_location = i;
18133                         c[i] *= -1;
18134                      } else {
18135                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18136                         cadence_is_ok = 0;
18137                         break;
18138                      }
18139                   } else {
18140                      if (firstcadencepos == 0) {
18141                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18142                                  /* duration will be passed negative to the DAHDI driver */
18143                      } else {
18144                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18145                         cadence_is_ok = 0;
18146                         break;
18147                      }
18148                   }
18149                }
18150             }
18151 
18152             /* Substitute our scanned cadence */
18153             for (i = 0; i < 16; i++) {
18154                new_cadence.ringcadence[i] = c[i];
18155             }
18156 
18157             if (cadence_is_ok) {
18158                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18159                if (element_count < 2) {
18160                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18161                } else {
18162                   if (cid_location == -1) {
18163                      /* user didn't say; default to first pause */
18164                      cid_location = 1;
18165                   } else {
18166                      /* convert element_index to cidrings value */
18167                      cid_location = (cid_location + 1) / 2;
18168                   }
18169                   /* ---we like their cadence; try to install it--- */
18170                   if (!user_has_defined_cadences++)
18171                      /* this is the first user-defined cadence; clear the default user cadences */
18172                      num_cadence = 0;
18173                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18174                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18175                   else {
18176                      cadences[num_cadence] = new_cadence;
18177                      cidrings[num_cadence++] = cid_location;
18178                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18179                   }
18180                }
18181             }
18182          } else if (!strcasecmp(v->name, "ringtimeout")) {
18183             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18184          } else if (!strcasecmp(v->name, "prewink")) {
18185             confp->timing.prewinktime = atoi(v->value);
18186          } else if (!strcasecmp(v->name, "preflash")) {
18187             confp->timing.preflashtime = atoi(v->value);
18188          } else if (!strcasecmp(v->name, "wink")) {
18189             confp->timing.winktime = atoi(v->value);
18190          } else if (!strcasecmp(v->name, "flash")) {
18191             confp->timing.flashtime = atoi(v->value);
18192          } else if (!strcasecmp(v->name, "start")) {
18193             confp->timing.starttime = atoi(v->value);
18194          } else if (!strcasecmp(v->name, "rxwink")) {
18195             confp->timing.rxwinktime = atoi(v->value);
18196          } else if (!strcasecmp(v->name, "rxflash")) {
18197             confp->timing.rxflashtime = atoi(v->value);
18198          } else if (!strcasecmp(v->name, "debounce")) {
18199             confp->timing.debouncetime = atoi(v->value);
18200          } else if (!strcasecmp(v->name, "toneduration")) {
18201             int toneduration;
18202             int ctlfd;
18203             int res;
18204             struct dahdi_dialparams dps;
18205 
18206             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18207             if (ctlfd == -1) {
18208                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18209                return -1;
18210             }
18211 
18212             toneduration = atoi(v->value);
18213             if (toneduration > -1) {
18214                memset(&dps, 0, sizeof(dps));
18215 
18216                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18217                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18218                if (res < 0) {
18219                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18220                   close(ctlfd);
18221                   return -1;
18222                }
18223             }
18224             close(ctlfd);
18225          } else if (!strcasecmp(v->name, "defaultcic")) {
18226             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18227          } else if (!strcasecmp(v->name, "defaultozz")) {
18228             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18229          } else if (!strcasecmp(v->name, "mwilevel")) {
18230             mwilevel = atoi(v->value);
18231          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18232             dtmfcid_level = atoi(v->value);
18233          } else if (!strcasecmp(v->name, "reportalarms")) {
18234             if (!strcasecmp(v->value, "all"))
18235                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18236             if (!strcasecmp(v->value, "none"))
18237                report_alarms = 0;
18238             else if (!strcasecmp(v->value, "channels"))
18239                report_alarms = REPORT_CHANNEL_ALARMS;
18240             else if (!strcasecmp(v->value, "spans"))
18241                report_alarms = REPORT_SPAN_ALARMS;
18242           }
18243       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18244          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18245    }
18246 
18247    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18248    if (confp->chan.vars) {
18249       ast_variables_destroy(confp->chan.vars);
18250       confp->chan.vars = NULL;
18251    }
18252 
18253    if (dahdichan) {
18254       /* Process the deferred dahdichan value. */
18255       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18256          &found_pseudo)) {
18257          if (confp->ignore_failed_channels) {
18258             ast_log(LOG_WARNING,
18259                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18260                dahdichan->value);
18261          } else {
18262             return -1;
18263          }
18264       }
18265    }
18266 
18267    /* mark the first channels of each DAHDI span to watch for their span alarms */
18268    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18269       if (!tmp->destroy && tmp->span != y) {
18270          tmp->manages_span_alarms = 1;
18271          y = tmp->span; 
18272       } else {
18273          tmp->manages_span_alarms = 0;
18274       }
18275    }
18276 
18277    /*< \todo why check for the pseudo in the per-channel section.
18278     * Any actual use for manual setup of the pseudo channel? */
18279    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18280       /* use the default configuration for a channel, so
18281          that any settings from real configured channels
18282          don't "leak" into the pseudo channel config
18283       */
18284       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18285 
18286       if (conf.chan.cc_params) {
18287          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18288       } else {
18289          tmp = NULL;
18290       }
18291       if (tmp) {
18292          ast_verb(3, "Automatically generated pseudo channel\n");
18293       } else {
18294          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18295       }
18296       ast_cc_config_params_destroy(conf.chan.cc_params);
18297    }
18298    return 0;
18299 }
18300 
18301 /*!
18302  * \internal
18303  * \brief Deep copy struct dahdi_chan_conf.
18304  * \since 1.8
18305  *
18306  * \param dest Destination.
18307  * \param src Source.
18308  *
18309  * \return Nothing
18310  */
18311 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18312 {
18313    struct ast_cc_config_params *cc_params;
18314 
18315    cc_params = dest->chan.cc_params;
18316    *dest = *src;
18317    dest->chan.cc_params = cc_params;
18318    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18319 }
18320 
18321 /*!
18322  * \internal
18323  * \brief Setup DAHDI channel driver.
18324  *
18325  * \param reload enum: load_module(0), reload(1), restart(2).
18326  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18327  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18328  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18329  *
18330  * \retval 0 on success.
18331  * \retval -1 on error.
18332  */
18333 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18334 {
18335    struct ast_config *cfg;
18336    struct ast_config *ucfg;
18337    struct ast_variable *v;
18338    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18339    const char *chans;
18340    const char *cat;
18341    int res;
18342 
18343 #ifdef HAVE_PRI
18344    char *c;
18345    int spanno;
18346    int i;
18347    int logicalspan;
18348    int trunkgroup;
18349    int dchannels[SIG_PRI_NUM_DCHANS];
18350 #endif
18351    int have_cfg_now;
18352    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18353 
18354    cfg = ast_config_load(config, config_flags);
18355    have_cfg_now = !!cfg;
18356    if (!cfg) {
18357       /* Error if we have no config file */
18358       if (had_cfg_before) {
18359          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18360          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18361       }
18362       cfg = ast_config_new();/* Dummy config */
18363       if (!cfg) {
18364          return 0;
18365       }
18366       ucfg = ast_config_load("users.conf", config_flags);
18367       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18368          ast_config_destroy(cfg);
18369          return 0;
18370       }
18371       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18372          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18373          ast_config_destroy(cfg);
18374          return 0;
18375       }
18376    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18377       ucfg = ast_config_load("users.conf", config_flags);
18378       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18379          return 0;
18380       }
18381       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18382          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18383          return 0;
18384       }
18385       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18386       cfg = ast_config_load(config, config_flags);
18387       have_cfg_now = !!cfg;
18388       if (!cfg) {
18389          if (had_cfg_before) {
18390             /* We should have been able to load the config. */
18391             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18392             ast_config_destroy(ucfg);
18393             return 0;
18394          }
18395          cfg = ast_config_new();/* Dummy config */
18396          if (!cfg) {
18397             ast_config_destroy(ucfg);
18398             return 0;
18399          }
18400       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18401          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18402          ast_config_destroy(ucfg);
18403          return 0;
18404       }
18405    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18406       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18407       return 0;
18408    } else {
18409       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18410       ucfg = ast_config_load("users.conf", config_flags);
18411       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18412          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18413          ast_config_destroy(cfg);
18414          return 0;
18415       }
18416    }
18417    had_cfg_before = have_cfg_now;
18418 
18419    /* It's a little silly to lock it, but we might as well just to be sure */
18420    ast_mutex_lock(&iflock);
18421 #ifdef HAVE_PRI
18422    if (reload != 1) {
18423       /* Process trunkgroups first */
18424       v = ast_variable_browse(cfg, "trunkgroups");
18425       while (v) {
18426          if (!strcasecmp(v->name, "trunkgroup")) {
18427             trunkgroup = atoi(v->value);
18428             if (trunkgroup > 0) {
18429                if ((c = strchr(v->value, ','))) {
18430                   i = 0;
18431                   memset(dchannels, 0, sizeof(dchannels));
18432                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18433                      dchannels[i] = atoi(c + 1);
18434                      if (dchannels[i] < 0) {
18435                         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);
18436                      } else
18437                         i++;
18438                      c = strchr(c + 1, ',');
18439                   }
18440                   if (i) {
18441                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18442                         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);
18443                   } else
18444                         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");
18445                   } else
18446                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18447                } else
18448                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18449             } else
18450                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18451          } else if (!strcasecmp(v->name, "spanmap")) {
18452             spanno = atoi(v->value);
18453             if (spanno > 0) {
18454                if ((c = strchr(v->value, ','))) {
18455                   trunkgroup = atoi(c + 1);
18456                   if (trunkgroup > 0) {
18457                      if ((c = strchr(c + 1, ',')))
18458                         logicalspan = atoi(c + 1);
18459                      else
18460                         logicalspan = 0;
18461                      if (logicalspan >= 0) {
18462                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18463                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18464                      } else
18465                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18466                      } else
18467                         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);
18468                   } else
18469                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18470                } else
18471                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18472             } else
18473                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18474          } else {
18475             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18476          }
18477          v = v->next;
18478       }
18479    }
18480 #endif
18481 
18482    /* Copy the default jb config over global_jbconf */
18483    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18484 
18485    mwimonitornotify[0] = '\0';
18486 
18487    v = ast_variable_browse(cfg, "channels");
18488    if ((res = process_dahdi(base_conf,
18489       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18490       v, reload, 0))) {
18491       ast_mutex_unlock(&iflock);
18492       ast_config_destroy(cfg);
18493       if (ucfg) {
18494          ast_config_destroy(ucfg);
18495       }
18496       return res;
18497    }
18498 
18499    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18500    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18501       /* [channels] and [trunkgroups] are used. Let's also reserve
18502        * [globals] and [general] for future use
18503        */
18504       if (!strcasecmp(cat, "general") ||
18505          !strcasecmp(cat, "trunkgroups") ||
18506          !strcasecmp(cat, "globals") ||
18507          !strcasecmp(cat, "channels")) {
18508          continue;
18509       }
18510 
18511       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18512       if (ast_strlen_zero(chans)) {
18513          /* Section is useless without a dahdichan value present. */
18514          continue;
18515       }
18516 
18517       /* Copy base_conf to conf. */
18518       deep_copy_dahdi_chan_conf(conf, base_conf);
18519 
18520       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18521          ast_mutex_unlock(&iflock);
18522          ast_config_destroy(cfg);
18523          if (ucfg) {
18524             ast_config_destroy(ucfg);
18525          }
18526          return res;
18527       }
18528    }
18529 
18530    ast_config_destroy(cfg);
18531 
18532    if (ucfg) {
18533       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18534       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18535       process_dahdi(base_conf,
18536          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18537          ast_variable_browse(ucfg, "general"), 1, 0);
18538 
18539       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18540          if (!strcasecmp(cat, "general")) {
18541             continue;
18542          }
18543 
18544          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18545          if (ast_strlen_zero(chans)) {
18546             /* Section is useless without a dahdichan value present. */
18547             continue;
18548          }
18549 
18550          /* Copy base_conf to conf. */
18551          deep_copy_dahdi_chan_conf(conf, base_conf);
18552 
18553          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18554             ast_config_destroy(ucfg);
18555             ast_mutex_unlock(&iflock);
18556             return res;
18557          }
18558       }
18559       ast_config_destroy(ucfg);
18560    }
18561    ast_mutex_unlock(&iflock);
18562 
18563 #ifdef HAVE_PRI
18564    if (reload != 1) {
18565       int x;
18566       for (x = 0; x < NUM_SPANS; x++) {
18567          if (pris[x].pri.pvts[0]) {
18568             prepare_pri(pris + x);
18569             if (sig_pri_start_pri(&pris[x].pri)) {
18570                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18571                return -1;
18572             } else
18573                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18574          }
18575       }
18576    }
18577 #endif
18578 #if defined(HAVE_SS7)
18579    if (reload != 1) {
18580       int x;
18581       for (x = 0; x < NUM_SPANS; x++) {
18582          if (linksets[x].ss7.ss7) {
18583             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18584             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18585                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18586                return -1;
18587             } else
18588                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18589          }
18590       }
18591    }
18592 #endif   /* defined(HAVE_SS7) */
18593 #ifdef HAVE_OPENR2
18594    if (reload != 1) {
18595       int x;
18596       for (x = 0; x < r2links_count; x++) {
18597          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18598             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18599             return -1;
18600          } else {
18601             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18602          }
18603       }
18604    }
18605 #endif
18606    /* And start the monitor for the first time */
18607    restart_monitor();
18608    return 0;
18609 }
18610 
18611 /*!
18612  * \internal
18613  * \brief Setup DAHDI channel driver.
18614  *
18615  * \param reload enum: load_module(0), reload(1), restart(2).
18616  *
18617  * \retval 0 on success.
18618  * \retval -1 on error.
18619  */
18620 static int setup_dahdi(int reload)
18621 {
18622    int res;
18623    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18624    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18625    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18626 
18627    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18628       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18629    } else {
18630       res = -1;
18631    }
18632    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18633    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18634    ast_cc_config_params_destroy(conf.chan.cc_params);
18635 
18636    return res;
18637 }
18638 
18639 /*!
18640  * \internal
18641  * \brief Callback used to generate the dahdi status tree.
18642  * \param[in] search The search pattern tree.
18643  * \retval NULL on error.
18644  * \retval non-NULL The generated tree.
18645  */
18646 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18647       struct ast_data *data_root)
18648 {
18649    int ctl, res, span;
18650    struct ast_data *data_span, *data_alarms;
18651    struct dahdi_spaninfo s;
18652 
18653    ctl = open("/dev/dahdi/ctl", O_RDWR);
18654    if (ctl < 0) {
18655       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18656       return -1;
18657    }
18658    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18659       s.spanno = span;
18660       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18661       if (res) {
18662          continue;
18663       }
18664 
18665       data_span = ast_data_add_node(data_root, "span");
18666       if (!data_span) {
18667          continue;
18668       }
18669       ast_data_add_str(data_span, "description", s.desc);
18670 
18671       /* insert the alarms status */
18672       data_alarms = ast_data_add_node(data_span, "alarms");
18673       if (!data_alarms) {
18674          continue;
18675       }
18676 
18677       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18678       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18679       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18680       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18681       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18682       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18683 
18684       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18685       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18686       ast_data_add_int(data_span, "crc4", s.crc4count);
18687       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18688                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18689                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18690                      "CAS");
18691       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18692                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18693                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18694                      "Unknown");
18695       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18696                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18697                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18698       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18699 
18700       /* if this span doesn't match remove it. */
18701       if (!ast_data_search_match(search, data_span)) {
18702          ast_data_remove_node(data_root, data_span);
18703       }
18704    }
18705    close(ctl);
18706 
18707    return 0;
18708 }
18709 
18710 /*!
18711  * \internal
18712  * \brief Callback used to generate the dahdi channels tree.
18713  * \param[in] search The search pattern tree.
18714  * \retval NULL on error.
18715  * \retval non-NULL The generated tree.
18716  */
18717 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18718       struct ast_data *data_root)
18719 {
18720    struct dahdi_pvt *tmp;
18721    struct ast_data *data_channel;
18722 
18723    ast_mutex_lock(&iflock);
18724    for (tmp = iflist; tmp; tmp = tmp->next) {
18725       data_channel = ast_data_add_node(data_root, "channel");
18726       if (!data_channel) {
18727          continue;
18728       }
18729 
18730       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18731 
18732       /* if this channel doesn't match remove it. */
18733       if (!ast_data_search_match(search, data_channel)) {
18734          ast_data_remove_node(data_root, data_channel);
18735       }
18736    }
18737    ast_mutex_unlock(&iflock);
18738 
18739    return 0;
18740 }
18741 
18742 /*!
18743  * \internal
18744  * \brief Callback used to generate the dahdi channels tree.
18745  * \param[in] search The search pattern tree.
18746  * \retval NULL on error.
18747  * \retval non-NULL The generated tree.
18748  */
18749 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18750       struct ast_data *data_root)
18751 {
18752    int pseudo_fd = -1;
18753    struct dahdi_versioninfo vi = {
18754       .version = "Unknown",
18755       .echo_canceller = "Unknown"
18756    };
18757 
18758    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18759       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18760       return -1;
18761    }
18762 
18763    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18764       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18765    }
18766 
18767    close(pseudo_fd);
18768 
18769    ast_data_add_str(data_root, "value", vi.version);
18770    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18771 
18772    return 0;
18773 }
18774 
18775 static const struct ast_data_handler dahdi_status_data_provider = {
18776    .version = AST_DATA_HANDLER_VERSION,
18777    .get = dahdi_status_data_provider_get
18778 };
18779 
18780 static const struct ast_data_handler dahdi_channels_data_provider = {
18781    .version = AST_DATA_HANDLER_VERSION,
18782    .get = dahdi_channels_data_provider_get
18783 };
18784 
18785 static const struct ast_data_handler dahdi_version_data_provider = {
18786    .version = AST_DATA_HANDLER_VERSION,
18787    .get = dahdi_version_data_provider_get
18788 };
18789 
18790 static const struct ast_data_entry dahdi_data_providers[] = {
18791    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18792    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18793    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18794 };
18795 
18796 static int load_module(void)
18797 {
18798    int res;
18799    struct ast_format tmpfmt;
18800 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18801    int y;
18802 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18803 
18804    if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
18805       return AST_MODULE_LOAD_FAILURE;
18806    }
18807    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
18808    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
18809    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
18810 
18811 #ifdef HAVE_PRI
18812    memset(pris, 0, sizeof(pris));
18813    for (y = 0; y < NUM_SPANS; y++) {
18814       sig_pri_init_pri(&pris[y].pri);
18815    }
18816    pri_set_error(dahdi_pri_error);
18817    pri_set_message(dahdi_pri_message);
18818    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18819 #ifdef HAVE_PRI_PROG_W_CAUSE
18820    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18821 #endif
18822 #if defined(HAVE_PRI_CCSS)
18823    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18824       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18825       __unload_module();
18826       return AST_MODULE_LOAD_FAILURE;
18827    }
18828 #endif   /* defined(HAVE_PRI_CCSS) */
18829    if (sig_pri_load(
18830 #if defined(HAVE_PRI_CCSS)
18831       dahdi_pri_cc_type
18832 #else
18833       NULL
18834 #endif   /* defined(HAVE_PRI_CCSS) */
18835       )) {
18836       __unload_module();
18837       return AST_MODULE_LOAD_FAILURE;
18838    }
18839 #endif
18840 #if defined(HAVE_SS7)
18841    memset(linksets, 0, sizeof(linksets));
18842    for (y = 0; y < NUM_SPANS; y++) {
18843       sig_ss7_init_linkset(&linksets[y].ss7);
18844    }
18845    ss7_set_error(dahdi_ss7_error);
18846    ss7_set_message(dahdi_ss7_message);
18847 #endif   /* defined(HAVE_SS7) */
18848    res = setup_dahdi(0);
18849    /* Make sure we can register our DAHDI channel type */
18850    if (res)
18851       return AST_MODULE_LOAD_DECLINE;
18852    if (ast_channel_register(&dahdi_tech)) {
18853       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18854       __unload_module();
18855       return AST_MODULE_LOAD_FAILURE;
18856    }
18857 #ifdef HAVE_PRI
18858    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18859 #endif
18860 #if defined(HAVE_SS7)
18861    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18862 #endif   /* defined(HAVE_SS7) */
18863 #ifdef HAVE_OPENR2
18864    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18865    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18866 #endif
18867 
18868    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18869    /* register all the data providers */
18870    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18871    memset(round_robin, 0, sizeof(round_robin));
18872    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18873    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18874    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18875    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18876    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18877    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18878    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18879 #if defined(HAVE_PRI)
18880    ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
18881 #endif   /* defined(HAVE_PRI) */
18882 
18883    ast_cond_init(&ss_thread_complete, NULL);
18884 
18885    return res;
18886 }
18887 
18888 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18889 {
18890 #define  END_SILENCE_LEN 400
18891 #define  HEADER_MS 50
18892 #define  TRAILER_MS 5
18893 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18894 #define  ASCII_BYTES_PER_CHAR 80
18895 
18896    unsigned char *buf,*mybuf;
18897    struct dahdi_pvt *p = c->tech_pvt;
18898    struct pollfd fds[1];
18899    int size,res,fd,len,x;
18900    int bytes=0;
18901    int idx;
18902 
18903    /*
18904     * Initial carrier (imaginary)
18905     *
18906     * Note: The following float variables are used by the
18907     * PUT_CLID_MARKMS and PUT_CLID() macros.
18908     */
18909    float cr = 1.0;
18910    float ci = 0.0;
18911    float scont = 0.0;
18912 
18913    if (!text[0]) {
18914       return(0); /* if nothing to send, don't */
18915    }
18916    idx = dahdi_get_index(c, p, 0);
18917    if (idx < 0) {
18918       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18919       return -1;
18920    }
18921    if ((!p->tdd) && (!p->mate)) {
18922 #if defined(HAVE_PRI)
18923 #if defined(HAVE_PRI_DISPLAY_TEXT)
18924       ast_mutex_lock(&p->lock);
18925       if (dahdi_sig_pri_lib_handles(p->sig)) {
18926          sig_pri_sendtext(p->sig_pvt, text);
18927       }
18928       ast_mutex_unlock(&p->lock);
18929 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
18930 #endif   /* defined(HAVE_PRI) */
18931       return(0);  /* if not in TDD mode, just return */
18932    }
18933    if (p->mate)
18934       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18935    else
18936       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18937    if (!buf)
18938       return -1;
18939    mybuf = buf;
18940    if (p->mate) {
18941       struct ast_format tmp;
18942       /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
18943       struct ast_format *codec = &tmp;
18944       ast_format_set(codec, AST_LAW(p), 0);
18945       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18946          PUT_CLID_MARKMS;
18947       }
18948       /* Put actual message */
18949       for (x = 0; text[x]; x++) {
18950          PUT_CLID(text[x]);
18951       }
18952       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18953          PUT_CLID_MARKMS;
18954       }
18955       len = bytes;
18956       buf = mybuf;
18957    } else {
18958       len = tdd_generate(p->tdd, buf, text);
18959       if (len < 1) {
18960          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18961          ast_free(mybuf);
18962          return -1;
18963       }
18964    }
18965    memset(buf + len, 0x7f, END_SILENCE_LEN);
18966    len += END_SILENCE_LEN;
18967    fd = p->subs[idx].dfd;
18968    while (len) {
18969       if (ast_check_hangup(c)) {
18970          ast_free(mybuf);
18971          return -1;
18972       }
18973       size = len;
18974       if (size > READ_SIZE)
18975          size = READ_SIZE;
18976       fds[0].fd = fd;
18977       fds[0].events = POLLOUT | POLLPRI;
18978       fds[0].revents = 0;
18979       res = poll(fds, 1, -1);
18980       if (!res) {
18981          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18982          continue;
18983       }
18984       /* if got exception */
18985       if (fds[0].revents & POLLPRI) {
18986          ast_free(mybuf);
18987          return -1;
18988       }
18989       if (!(fds[0].revents & POLLOUT)) {
18990          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18991          continue;
18992       }
18993       res = write(fd, buf, size);
18994       if (res != size) {
18995          if (res == -1) {
18996             ast_free(mybuf);
18997             return -1;
18998          }
18999          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19000          break;
19001       }
19002       len -= size;
19003       buf += size;
19004    }
19005    ast_free(mybuf);
19006    return(0);
19007 }
19008 
19009 
19010 static int reload(void)
19011 {
19012    int res = 0;
19013 
19014    res = setup_dahdi(1);
19015    if (res) {
19016       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19017       return -1;
19018    }
19019    return 0;
19020 }
19021 
19022 /* This is a workaround so that menuselect displays a proper description
19023  * AST_MODULE_INFO(, , "DAHDI Telephony"
19024  */
19025 
19026 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19027    .load = load_module,
19028    .unload = unload_module,
19029    .reload = reload,
19030    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19031       .nonoptreq = "res_smdi",
19032    );

Generated on Sat Feb 11 06:33:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6