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  * \ingroup channel_drivers
00033  *
00034  * \todo Deprecate the "musiconhold" configuration option post 1.4
00035  */
00036 
00037 /*! \li \ref chan_dahdi.c uses the configuration file \ref chan_dahdi.conf
00038  * \addtogroup configuration_file
00039  */
00040 
00041 /*! \page chan_dahdi.conf chan_dahdi.conf
00042  * \verbinclude chan_dahdi.conf.sample
00043  */
00044 
00045 /*** MODULEINFO
00046    <use type="module">res_smdi</use>
00047    <depend>dahdi</depend>
00048    <depend>tonezone</depend>
00049    <use type="external">pri</use>
00050    <use type="external">ss7</use>
00051    <use type="external">openr2</use>
00052    <support_level>core</support_level>
00053  ***/
00054 
00055 #include "asterisk.h"
00056 
00057 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 432834 $")
00058 
00059 #if defined(__NetBSD__) || defined(__FreeBSD__)
00060 #include <pthread.h>
00061 #include <signal.h>
00062 #else
00063 #include <sys/signal.h>
00064 #endif
00065 #include <sys/stat.h>
00066 #include <math.h>
00067 
00068 #include "sig_analog.h"
00069 /* Analog signaling is currently still present in chan_dahdi for use with
00070  * radio. Sig_analog does not currently handle any radio operations. If
00071  * radio only uses analog signaling, then the radio handling logic could
00072  * be placed in sig_analog and the duplicated code could be removed.
00073  */
00074 
00075 #if defined(HAVE_PRI)
00076 #include "sig_pri.h"
00077 #ifndef PRI_RESTART
00078 #error "Upgrade your libpri"
00079 #endif
00080 #endif   /* defined(HAVE_PRI) */
00081 
00082 #if defined(HAVE_SS7)
00083 #include "sig_ss7.h"
00084 #if !defined(LIBSS7_ABI_COMPATIBILITY)
00085 #error "Upgrade your libss7"
00086 #elif LIBSS7_ABI_COMPATIBILITY != 2
00087 #error "Your installed libss7 is not compatible"
00088 #endif
00089 #endif   /* defined(HAVE_SS7) */
00090 
00091 #if defined(HAVE_OPENR2)
00092 /* put this here until sig_mfcr2 comes along */
00093 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00094 #endif   /* defined(HAVE_OPENR2) */
00095 
00096 #include "asterisk/lock.h"
00097 #include "asterisk/channel.h"
00098 #include "asterisk/config.h"
00099 #include "asterisk/module.h"
00100 #include "asterisk/pbx.h"
00101 #include "asterisk/file.h"
00102 #include "asterisk/ulaw.h"
00103 #include "asterisk/alaw.h"
00104 #include "asterisk/callerid.h"
00105 #include "asterisk/adsi.h"
00106 #include "asterisk/cli.h"
00107 #include "asterisk/pickup.h"
00108 #include "asterisk/features.h"
00109 #include "asterisk/musiconhold.h"
00110 #include "asterisk/say.h"
00111 #include "asterisk/tdd.h"
00112 #include "asterisk/app.h"
00113 #include "asterisk/dsp.h"
00114 #include "asterisk/astdb.h"
00115 #include "asterisk/manager.h"
00116 #include "asterisk/causes.h"
00117 #include "asterisk/term.h"
00118 #include "asterisk/utils.h"
00119 #include "asterisk/transcap.h"
00120 #include "asterisk/stringfields.h"
00121 #include "asterisk/abstract_jb.h"
00122 #include "asterisk/smdi.h"
00123 #include "asterisk/devicestate.h"
00124 #include "asterisk/paths.h"
00125 #include "asterisk/ccss.h"
00126 #include "asterisk/data.h"
00127 #include "asterisk/features_config.h"
00128 #include "asterisk/bridge.h"
00129 #include "asterisk/stasis_channels.h"
00130 #include "asterisk/parking.h"
00131 #include "asterisk/format_cache.h"
00132 #include "chan_dahdi.h"
00133 #include "dahdi/bridge_native_dahdi.h"
00134 
00135 /*** DOCUMENTATION
00136    <application name="DAHDISendKeypadFacility" language="en_US">
00137       <synopsis>
00138          Send digits out of band over a PRI.
00139       </synopsis>
00140       <syntax>
00141          <parameter name="digits" required="true" />
00142       </syntax>
00143       <description>
00144          <para>This application will send the given string of digits in a Keypad
00145          Facility IE over the current channel.</para>
00146       </description>
00147    </application>
00148    <application name="DAHDISendCallreroutingFacility" language="en_US">
00149       <synopsis>
00150          Send an ISDN call rerouting/deflection facility message.
00151       </synopsis>
00152       <syntax argsep=",">
00153          <parameter name="destination" required="true">
00154             <para>Destination number.</para>
00155          </parameter>
00156          <parameter name="original">
00157             <para>Original called number.</para>
00158          </parameter>
00159          <parameter name="reason">
00160             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00161          </parameter>
00162       </syntax>
00163       <description>
00164          <para>This application will send an ISDN switch specific call
00165          rerouting/deflection facility message over the current channel.
00166          Supported switches depend upon the version of libpri in use.</para>
00167       </description>
00168    </application>
00169    <application name="DAHDIAcceptR2Call" language="en_US">
00170       <synopsis>
00171          Accept an R2 call if its not already accepted (you still need to answer it)
00172       </synopsis>
00173       <syntax>
00174          <parameter name="charge" required="true">
00175             <para>Yes or No.</para>
00176             <para>Whether you want to accept the call with charge or without charge.</para>
00177          </parameter>
00178       </syntax>
00179       <description>
00180          <para>This application will Accept the R2 call either with charge or no charge.</para>
00181       </description>
00182    </application>
00183    <manager name="DAHDITransfer" language="en_US">
00184       <synopsis>
00185          Transfer DAHDI Channel.
00186       </synopsis>
00187       <syntax>
00188          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00189          <parameter name="DAHDIChannel" required="true">
00190             <para>DAHDI channel number to transfer.</para>
00191          </parameter>
00192       </syntax>
00193       <description>
00194          <para>Simulate a flash hook event by the user connected to the channel.</para>
00195          <note><para>Valid only for analog channels.</para></note>
00196       </description>
00197    </manager>
00198    <manager name="DAHDIHangup" language="en_US">
00199       <synopsis>
00200          Hangup DAHDI Channel.
00201       </synopsis>
00202       <syntax>
00203          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00204          <parameter name="DAHDIChannel" required="true">
00205             <para>DAHDI channel number to hangup.</para>
00206          </parameter>
00207       </syntax>
00208       <description>
00209          <para>Simulate an on-hook event by the user connected to the channel.</para>
00210          <note><para>Valid only for analog channels.</para></note>
00211       </description>
00212    </manager>
00213    <manager name="DAHDIDialOffhook" language="en_US">
00214       <synopsis>
00215          Dial over DAHDI channel while offhook.
00216       </synopsis>
00217       <syntax>
00218          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00219          <parameter name="DAHDIChannel" required="true">
00220             <para>DAHDI channel number to dial digits.</para>
00221          </parameter>
00222          <parameter name="Number" required="true">
00223             <para>Digits to dial.</para>
00224          </parameter>
00225       </syntax>
00226       <description>
00227          <para>Generate DTMF control frames to the bridged peer.</para>
00228       </description>
00229    </manager>
00230    <manager name="DAHDIDNDon" language="en_US">
00231       <synopsis>
00232          Toggle DAHDI channel Do Not Disturb status ON.
00233       </synopsis>
00234       <syntax>
00235          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00236          <parameter name="DAHDIChannel" required="true">
00237             <para>DAHDI channel number to set DND on.</para>
00238          </parameter>
00239       </syntax>
00240       <description>
00241          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00242          <note><para>Feature only supported by analog channels.</para></note>
00243       </description>
00244    </manager>
00245    <manager name="DAHDIDNDoff" language="en_US">
00246       <synopsis>
00247          Toggle DAHDI channel Do Not Disturb status OFF.
00248       </synopsis>
00249       <syntax>
00250          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00251          <parameter name="DAHDIChannel" required="true">
00252             <para>DAHDI channel number to set DND off.</para>
00253          </parameter>
00254       </syntax>
00255       <description>
00256          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00257          <note><para>Feature only supported by analog channels.</para></note>
00258       </description>
00259    </manager>
00260    <manager name="DAHDIShowChannels" language="en_US">
00261       <synopsis>
00262          Show status of DAHDI channels.
00263       </synopsis>
00264       <syntax>
00265          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00266          <parameter name="DAHDIChannel">
00267             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00268          </parameter>
00269       </syntax>
00270       <description>
00271          <para>Similar to the CLI command "dahdi show channels".</para>
00272       </description>
00273    </manager>
00274    <manager name="DAHDIRestart" language="en_US">
00275       <synopsis>
00276          Fully Restart DAHDI channels (terminates calls).
00277       </synopsis>
00278       <syntax>
00279          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00280       </syntax>
00281       <description>
00282          <para>Equivalent to the CLI command "dahdi restart".</para>
00283       </description>
00284    </manager>
00285    <manager name="PRIShowSpans" language="en_US">
00286       <synopsis>
00287          Show status of PRI spans.
00288       </synopsis>
00289       <syntax>
00290          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00291          <parameter name="Span">
00292             <para>Specify the specific span to show.  Show all spans if zero or not present.</para>
00293          </parameter>
00294       </syntax>
00295       <description>
00296          <para>Similar to the CLI command "pri show spans".</para>
00297       </description>
00298    </manager>
00299    <manager name="PRIDebugSet" language="en_US">
00300       <synopsis>
00301          Set PRI debug levels for a span
00302       </synopsis>
00303       <syntax>
00304          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00305          <parameter name="Span" required="true">
00306             <para>Which span to affect.</para>
00307          </parameter>
00308          <parameter name="Level" required="true">
00309             <para>What debug level to set. May be a numerical value or a text value from the list below</para>
00310             <enumlist>
00311                <enum name="off" />
00312                <enum name="on" />
00313                <enum name="hex" />
00314                <enum name="intense" />
00315             </enumlist>
00316          </parameter>
00317       </syntax>
00318       <description>
00319          <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
00320       </description>
00321    </manager>
00322    <manager name="PRIDebugFileSet" language="en_US">
00323       <synopsis>
00324          Set the file used for PRI debug message output
00325       </synopsis>
00326       <syntax>
00327          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00328          <parameter name="File" required="true">
00329             <para>Path of file to write debug output.</para>
00330          </parameter>
00331       </syntax>
00332       <description>
00333          <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
00334       </description>
00335    </manager>
00336    <manager name="PRIDebugFileUnset" language="en_US">
00337       <synopsis>
00338          Disables file output for PRI debug messages
00339       </synopsis>
00340       <syntax>
00341          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00342       </syntax>
00343    </manager>
00344    <managerEvent language="en_US" name="AlarmClear">
00345       <managerEventInstance class="EVENT_FLAG_SYSTEM">
00346          <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
00347          <syntax>
00348             <parameter name="DAHDIChannel">
00349                <para>The DAHDI channel on which the alarm was cleared.</para>
00350                <note><para>This is not an Asterisk channel identifier.</para></note>
00351             </parameter>
00352          </syntax>
00353       </managerEventInstance>
00354    </managerEvent>
00355    <managerEvent language="en_US" name="SpanAlarmClear">
00356       <managerEventInstance class="EVENT_FLAG_SYSTEM">
00357          <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
00358          <syntax>
00359             <parameter name="Span">
00360                <para>The span on which the alarm was cleared.</para>
00361             </parameter>
00362          </syntax>
00363       </managerEventInstance>
00364    </managerEvent>
00365    <managerEvent language="en_US" name="DNDState">
00366       <managerEventInstance class="EVENT_FLAG_SYSTEM">
00367          <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
00368          <syntax>
00369             <parameter name="DAHDIChannel">
00370                <para>The DAHDI channel on which DND status changed.</para>
00371                <note><para>This is not an Asterisk channel identifier.</para></note>
00372             </parameter>
00373             <parameter name="Status">
00374                <enumlist>
00375                   <enum name="enabled"/>
00376                   <enum name="disabled"/>
00377                </enumlist>
00378             </parameter>
00379          </syntax>
00380       </managerEventInstance>
00381    </managerEvent>
00382    <managerEvent language="en_US" name="Alarm">
00383       <managerEventInstance class="EVENT_FLAG_SYSTEM">
00384          <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
00385          <syntax>
00386             <parameter name="DAHDIChannel">
00387                <para>The channel on which the alarm occurred.</para>
00388                <note><para>This is not an Asterisk channel identifier.</para></note>
00389             </parameter>
00390             <parameter name="Alarm">
00391                <para>A textual description of the alarm that occurred.</para>
00392             </parameter>
00393          </syntax>
00394       </managerEventInstance>
00395    </managerEvent>
00396    <managerEvent language="en_US" name="SpanAlarm">
00397       <managerEventInstance class="EVENT_FLAG_SYSTEM">
00398          <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
00399          <syntax>
00400             <parameter name="Span">
00401                <para>The span on which the alarm occurred.</para>
00402             </parameter>
00403             <parameter name="Alarm">
00404                <para>A textual description of the alarm that occurred.</para>
00405             </parameter>
00406          </syntax>
00407       </managerEventInstance>
00408    </managerEvent>
00409    <managerEvent language="en_US" name="DAHDIChannel">
00410       <managerEventInstance class="EVENT_FLAG_CALL">
00411          <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
00412          <syntax>
00413             <channel_snapshot/>
00414             <parameter name="DAHDISpan">
00415                <para>The DAHDI span associated with this channel.</para>
00416             </parameter>
00417             <parameter name="DAHDIChannel">
00418                <para>The DAHDI channel associated with this channel.</para>
00419             </parameter>
00420          </syntax>
00421       </managerEventInstance>
00422    </managerEvent>
00423  ***/
00424 
00425 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00426 
00427 static const char * const lbostr[] = {
00428 "0 db (CSU)/0-133 feet (DSX-1)",
00429 "133-266 feet (DSX-1)",
00430 "266-399 feet (DSX-1)",
00431 "399-533 feet (DSX-1)",
00432 "533-655 feet (DSX-1)",
00433 "-7.5db (CSU)",
00434 "-15db (CSU)",
00435 "-22.5db (CSU)"
00436 };
00437 
00438 /*! Global jitterbuffer configuration - by default, jb is disabled
00439  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00440 static struct ast_jb_conf default_jbconf =
00441 {
00442    .flags = 0,
00443    .max_size = 200,
00444    .resync_threshold = 1000,
00445    .impl = "fixed",
00446    .target_extra = 40,
00447 };
00448 static struct ast_jb_conf global_jbconf;
00449 
00450 /*!
00451  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00452  * the user hangs up to reset the state machine so ring works properly.
00453  * This is used to be able to support kewlstart by putting the zhone in
00454  * groundstart mode since their forward disconnect supervision is entirely
00455  * broken even though their documentation says it isn't and their support
00456  * is entirely unwilling to provide any assistance with their channel banks
00457  * even though their web site says they support their products for life.
00458  */
00459 /* #define ZHONE_HACK */
00460 
00461 /*! \brief Typically, how many rings before we should send Caller*ID */
00462 #define DEFAULT_CIDRINGS 1
00463 
00464 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
00465 
00466 
00467 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00468 #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))
00469 
00470 static const char tdesc[] = "DAHDI Telephony"
00471 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00472    " w/"
00473    #if defined(HAVE_PRI)
00474       "PRI"
00475    #endif   /* defined(HAVE_PRI) */
00476    #if defined(HAVE_SS7)
00477       #if defined(HAVE_PRI)
00478       " & "
00479       #endif   /* defined(HAVE_PRI) */
00480       "SS7"
00481    #endif   /* defined(HAVE_SS7) */
00482    #if defined(HAVE_OPENR2)
00483       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00484       " & "
00485       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00486       "MFC/R2"
00487    #endif   /* defined(HAVE_OPENR2) */
00488 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00489 ;
00490 
00491 static const char config[] = "chan_dahdi.conf";
00492 
00493 #ifdef LOTS_OF_SPANS
00494 #define NUM_SPANS DAHDI_MAX_SPANS
00495 #else
00496 #define NUM_SPANS       32
00497 #endif
00498 
00499 #define CHAN_PSEUDO  -2
00500 
00501 #define CALLPROGRESS_PROGRESS    1
00502 #define CALLPROGRESS_FAX_OUTGOING   2
00503 #define CALLPROGRESS_FAX_INCOMING   4
00504 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00505 
00506 #define NUM_CADENCE_MAX 25
00507 static int num_cadence = 4;
00508 static int user_has_defined_cadences = 0;
00509 
00510 static int has_pseudo;
00511 
00512 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00513    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00514    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00515    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00516    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00517 };
00518 
00519 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00520  * is 1, the second pause is 2 and so on.
00521  */
00522 
00523 static int cidrings[NUM_CADENCE_MAX] = {
00524    2,                            /*!< Right after first long ring */
00525    4,                            /*!< Right after long part */
00526    3,                            /*!< After third chirp */
00527    2,                            /*!< Second spell */
00528 };
00529 
00530 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00531 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00532 
00533 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00534          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00535 
00536 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00537 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00538 
00539 static char defaultcic[64] = "";
00540 static char defaultozz[64] = "";
00541 
00542 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00543 static char mwimonitornotify[PATH_MAX] = "";
00544 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00545 static int  mwisend_rpas = 0;
00546 #endif
00547 
00548 static char progzone[10] = "";
00549 
00550 static int usedistinctiveringdetection = 0;
00551 static int distinctiveringaftercid = 0;
00552 
00553 static int numbufs = 4;
00554 
00555 static int mwilevel = 512;
00556 static int dtmfcid_level = 256;
00557 
00558 #define REPORT_CHANNEL_ALARMS 1
00559 #define REPORT_SPAN_ALARMS    2
00560 static int report_alarms = REPORT_CHANNEL_ALARMS;
00561 
00562 #ifdef HAVE_PRI
00563 static int pridebugfd = -1;
00564 static char pridebugfilename[1024] = "";
00565 #endif
00566 
00567 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00568 static int firstdigittimeout = 16000;
00569 
00570 /*! \brief How long to wait for following digits (FXO logic) */
00571 static int gendigittimeout = 8000;
00572 
00573 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00574 static int matchdigittimeout = 3000;
00575 
00576 /*! \brief Protect the interface list (of dahdi_pvt's) */
00577 AST_MUTEX_DEFINE_STATIC(iflock);
00578 
00579 
00580 static int ifcount = 0;
00581 
00582 #ifdef HAVE_PRI
00583 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00584 #endif
00585 
00586 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00587    when it's doing something critical. */
00588 AST_MUTEX_DEFINE_STATIC(monlock);
00589 
00590 /*! \brief This is the thread for the monitor which checks for input on the channels
00591    which are not currently in use. */
00592 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00593 static ast_cond_t ss_thread_complete;
00594 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00595 AST_MUTEX_DEFINE_STATIC(restart_lock);
00596 static int ss_thread_count = 0;
00597 static int num_restart_pending = 0;
00598 
00599 static int restart_monitor(void);
00600 
00601 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00602 
00603 static void mwi_event_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
00604 {
00605    /* This module does not handle MWI in an event-based manner.  However, it
00606     * subscribes to MWI for each mailbox that is configured so that the core
00607     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00608     * event cache instead of checking the mailbox directly. */
00609 }
00610 
00611 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00612 static inline int dahdi_get_event(int fd)
00613 {
00614    int j;
00615    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00616       return -1;
00617    return j;
00618 }
00619 
00620 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00621 static inline int dahdi_wait_event(int fd)
00622 {
00623    int i, j = 0;
00624    i = DAHDI_IOMUX_SIGEVENT;
00625    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00626       return -1;
00627    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00628       return -1;
00629    return j;
00630 }
00631 
00632 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00633 #define READ_SIZE 160
00634 
00635 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00636 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00637 
00638 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00639 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00640 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00641 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00642 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00643 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00644 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00645 
00646 /*!
00647  * \brief Configured ring timeout base.
00648  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00649  */
00650 static int ringt_base = DEFAULT_RINGT;
00651 
00652 #if defined(HAVE_SS7)
00653 
00654 struct dahdi_ss7 {
00655    struct sig_ss7_linkset ss7;
00656 };
00657 
00658 static struct dahdi_ss7 linksets[NUM_SPANS];
00659 
00660 static int cur_ss7type = -1;
00661 static int cur_slc = -1;
00662 static int cur_linkset = -1;
00663 static int cur_pointcode = -1;
00664 static int cur_cicbeginswith = -1;
00665 static int cur_adjpointcode = -1;
00666 static int cur_networkindicator = -1;
00667 static int cur_defaultdpc = -1;
00668 #endif   /* defined(HAVE_SS7) */
00669 
00670 #ifdef HAVE_OPENR2
00671 struct dahdi_mfcr2_conf {
00672    openr2_variant_t variant;
00673    int mfback_timeout;
00674    int metering_pulse_timeout;
00675    int max_ani;
00676    int max_dnis;
00677 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00678    int dtmf_time_on;
00679    int dtmf_time_off;
00680 #endif
00681 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00682    int dtmf_end_timeout;
00683 #endif
00684    signed int get_ani_first:2;
00685 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00686    signed int skip_category_request:2;
00687 #endif
00688    unsigned int call_files:1;
00689    unsigned int allow_collect_calls:1;
00690    unsigned int charge_calls:1;
00691    unsigned int accept_on_offer:1;
00692    unsigned int forced_release:1;
00693    unsigned int double_answer:1;
00694    signed int immediate_accept:2;
00695 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00696    signed int dtmf_dialing:2;
00697    signed int dtmf_detection:2;
00698 #endif
00699    char logdir[OR2_MAX_PATH];
00700    char r2proto_file[OR2_MAX_PATH];
00701    openr2_log_level_t loglevel;
00702    openr2_calling_party_category_t category;
00703 };
00704 
00705 /* MFC-R2 pseudo-link structure */
00706 struct dahdi_mfcr2 {
00707    pthread_t r2master;            /*!< Thread of master */
00708    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00709    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00710    int numchans;                          /*!< Number of channels in this R2 block */
00711    struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
00712 };
00713 
00714 /* malloc'd array of malloc'd r2links */
00715 static struct dahdi_mfcr2 **r2links;
00716 /* how many r2links have been malloc'd */
00717 static int r2links_count = 0;
00718 
00719 #endif /* HAVE_OPENR2 */
00720 
00721 #ifdef HAVE_PRI
00722 
00723 struct dahdi_pri {
00724    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00725    int mastertrunkgroup;               /*!< What trunk group is our master */
00726    int prilogicalspan;                 /*!< Logical span number within trunk group */
00727    struct sig_pri_span pri;
00728 };
00729 
00730 static struct dahdi_pri pris[NUM_SPANS];
00731 
00732 #if defined(HAVE_PRI_CCSS)
00733 /*! DAHDI PRI CCSS agent and monitor type name. */
00734 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00735 #endif   /* defined(HAVE_PRI_CCSS) */
00736 
00737 #else
00738 /*! Shut up the compiler */
00739 struct dahdi_pri;
00740 #endif
00741 
00742 /* Polarity states */
00743 #define POLARITY_IDLE   0
00744 #define POLARITY_REV    1
00745 
00746 const char * const subnames[] = {
00747    "Real",
00748    "Callwait",
00749    "Threeway"
00750 };
00751 
00752 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
00753    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
00754    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
00755    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
00756    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
00757    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
00758    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
00759    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
00760    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
00761    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
00762    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
00763    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
00764    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
00765    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
00766    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
00767    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
00768    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
00769    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
00770    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
00771    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
00772    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
00773    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
00774    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
00775    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
00776    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
00777    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
00778    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
00779    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
00780    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
00781    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
00782    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
00783    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
00784    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
00785    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
00786    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
00787    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
00788    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
00789    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
00790    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
00791    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
00792    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
00793    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
00794    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
00795    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
00796    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
00797    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
00798    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
00799    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
00800    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
00801    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
00802    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
00803    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
00804    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
00805    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
00806    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
00807    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
00808    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
00809    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_UNSIGNED_INTEGER)      \
00810    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_UNSIGNED_INTEGER)     \
00811    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
00812    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
00813    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
00814    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
00815    MEMBER(dahdi_pvt, description, AST_DATA_STRING)          \
00816    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
00817    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
00818    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
00819    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
00820    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
00821 
00822 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
00823 
00824 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
00825 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
00826 
00827 #if defined(HAVE_PRI)
00828 struct doomed_pri {
00829    struct sig_pri_span *pri;
00830    AST_LIST_ENTRY(doomed_pri) list;
00831 };
00832 static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
00833 
00834 static void pri_destroy_span(struct sig_pri_span *pri);
00835 
00836 static struct dahdi_parms_pseudo {
00837    int buf_no;             /*!< Number of buffers */
00838    int buf_policy;            /*!< Buffer policy */
00839    int faxbuf_no;              /*!< Number of Fax buffers */
00840    int faxbuf_policy;          /*!< Fax buffer policy */
00841 } dahdi_pseudo_parms;
00842 #endif   /* defined(HAVE_PRI) */
00843 
00844 /*! \brief Channel configuration from chan_dahdi.conf .
00845  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00846  * Generally there is a field here for every possible configuration item.
00847  *
00848  * The state of fields is saved along the parsing and whenever a 'channel'
00849  * statement is reached, the current dahdi_chan_conf is used to configure the
00850  * channel (struct dahdi_pvt)
00851  *
00852  * \see dahdi_chan_init for the default values.
00853  */
00854 struct dahdi_chan_conf {
00855    struct dahdi_pvt chan;
00856 #ifdef HAVE_PRI
00857    struct dahdi_pri pri;
00858 #endif
00859 
00860 #if defined(HAVE_SS7)
00861    struct dahdi_ss7 ss7;
00862 #endif   /* defined(HAVE_SS7) */
00863 
00864 #ifdef HAVE_OPENR2
00865    struct dahdi_mfcr2_conf mfcr2;
00866 #endif
00867    struct dahdi_params timing;
00868    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
00869    /*! Continue configuration even if a channel is not there. */
00870    int ignore_failed_channels;
00871 
00872    /*!
00873     * \brief The serial port to listen for SMDI data on
00874     * \note Set from the "smdiport" string read in from chan_dahdi.conf
00875     */
00876    char smdi_port[SMDI_MAX_FILENAME_LEN];
00877 
00878    /*!
00879     * \brief Don't create channels below this number
00880     * \note by default is 0 (no limit)
00881     */
00882    int wanted_channels_start;
00883 
00884    /*!
00885     * \brief Don't create channels above this number (infinity by default)
00886     * \note by default is 0 (special value that means "no limit").
00887     */
00888    int wanted_channels_end;
00889 };
00890 
00891 /*! returns a new dahdi_chan_conf with default values (by-value) */
00892 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
00893 {
00894    /* recall that if a field is not included here it is initialized
00895     * to 0 or equivalent
00896     */
00897    struct dahdi_chan_conf conf = {
00898 #ifdef HAVE_PRI
00899       .pri.pri = {
00900          .nsf = PRI_NSF_NONE,
00901          .switchtype = PRI_SWITCH_NI2,
00902          .dialplan = PRI_UNKNOWN + 1,
00903          .localdialplan = PRI_NATIONAL_ISDN + 1,
00904          .nodetype = PRI_CPE,
00905          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
00906 
00907 #if defined(HAVE_PRI_CCSS)
00908          .cc_ptmp_recall_mode = 1,/* specificRecall */
00909          .cc_qsig_signaling_link_req = 1,/* retain */
00910          .cc_qsig_signaling_link_rsp = 1,/* retain */
00911 #endif   /* defined(HAVE_PRI_CCSS) */
00912 
00913          .minunused = 2,
00914          .idleext = "",
00915          .idledial = "",
00916          .internationalprefix = "",
00917          .nationalprefix = "",
00918          .localprefix = "",
00919          .privateprefix = "",
00920          .unknownprefix = "",
00921          .colp_send = SIG_PRI_COLP_UPDATE,
00922          .resetinterval = -1,
00923       },
00924 #endif
00925 #if defined(HAVE_SS7)
00926       .ss7.ss7 = {
00927          .called_nai = SS7_NAI_NATIONAL,
00928          .calling_nai = SS7_NAI_NATIONAL,
00929          .internationalprefix = "",
00930          .nationalprefix = "",
00931          .subscriberprefix = "",
00932          .unknownprefix = "",
00933          .networkroutedprefix = ""
00934       },
00935 #endif   /* defined(HAVE_SS7) */
00936 #ifdef HAVE_OPENR2
00937       .mfcr2 = {
00938          .variant = OR2_VAR_ITU,
00939          .mfback_timeout = -1,
00940          .metering_pulse_timeout = -1,
00941          .max_ani = 10,
00942          .max_dnis = 4,
00943          .get_ani_first = -1,
00944 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00945          .skip_category_request = -1,
00946 #endif
00947          .call_files = 0,
00948          .allow_collect_calls = 0,
00949          .charge_calls = 1,
00950          .accept_on_offer = 1,
00951          .forced_release = 0,
00952          .double_answer = 0,
00953          .immediate_accept = -1,
00954 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00955          .dtmf_dialing = -1,
00956          .dtmf_detection = -1,
00957          .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
00958          .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
00959 #endif
00960 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00961          .dtmf_end_timeout = -1,
00962 #endif
00963          .logdir = "",
00964          .r2proto_file = "",
00965          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
00966          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
00967       },
00968 #endif
00969       .chan = {
00970          .context = "default",
00971          .cid_num = "",
00972          .cid_name = "",
00973          .cid_tag = "",
00974          .mohinterpret = "default",
00975          .mohsuggest = "",
00976          .parkinglot = "",
00977          .transfertobusy = 1,
00978 
00979          .cid_signalling = CID_SIG_BELL,
00980          .cid_start = CID_START_RING,
00981          .dahditrcallerid = 0,
00982          .use_callerid = 1,
00983          .sig = -1,
00984          .outsigmod = -1,
00985 
00986          .cid_rxgain = +5.0,
00987 
00988          .tonezone = -1,
00989 
00990          .echocancel.head.tap_length = 1,
00991 
00992          .busycount = 3,
00993 
00994          .accountcode = "",
00995 
00996          .mailbox = "",
00997 
00998 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
00999          .mwisend_fsk = 1,
01000 #endif
01001          .polarityonanswerdelay = 600,
01002 
01003          .sendcalleridafter = DEFAULT_CIDRINGS,
01004 
01005          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01006          .buf_no = numbufs,
01007          .usefaxbuffers = 0,
01008          .cc_params = ast_cc_config_params_init(),
01009       },
01010       .timing = {
01011          .prewinktime = -1,
01012          .preflashtime = -1,
01013          .winktime = -1,
01014          .flashtime = -1,
01015          .starttime = -1,
01016          .rxwinktime = -1,
01017          .rxflashtime = -1,
01018          .debouncetime = -1
01019       },
01020       .is_sig_auto = 1,
01021       .ignore_failed_channels = 1,
01022       .smdi_port = "/dev/ttyS0",
01023    };
01024 
01025    return conf;
01026 }
01027 
01028 
01029 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
01030    const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
01031    const char *data, int *cause);
01032 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01033 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01034 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01035 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01036 static int dahdi_hangup(struct ast_channel *ast);
01037 static int dahdi_answer(struct ast_channel *ast);
01038 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01039 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01040 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01041 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01042 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01043 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01044 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01045 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01046 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01047 static int dahdi_devicestate(const char *data);
01048 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01049 
01050 static struct ast_channel_tech dahdi_tech = {
01051    .type = "DAHDI",
01052    .description = tdesc,
01053    .requester = dahdi_request,
01054    .send_digit_begin = dahdi_digit_begin,
01055    .send_digit_end = dahdi_digit_end,
01056    .send_text = dahdi_sendtext,
01057    .call = dahdi_call,
01058    .hangup = dahdi_hangup,
01059    .answer = dahdi_answer,
01060    .read = dahdi_read,
01061    .write = dahdi_write,
01062    .exception = dahdi_exception,
01063    .indicate = dahdi_indicate,
01064    .fixup = dahdi_fixup,
01065    .setoption = dahdi_setoption,
01066    .queryoption = dahdi_queryoption,
01067    .func_channel_read = dahdi_func_read,
01068    .func_channel_write = dahdi_func_write,
01069    .devicestate = dahdi_devicestate,
01070    .cc_callback = dahdi_cc_callback,
01071 };
01072 
01073 #define GET_CHANNEL(p) ((p)->channel)
01074 
01075 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01076 {
01077    switch (sig) {
01078    case SIG_FXOLS:
01079       return ANALOG_SIG_FXOLS;
01080    case SIG_FXOGS:
01081       return ANALOG_SIG_FXOGS;
01082    case SIG_FXOKS:
01083       return ANALOG_SIG_FXOKS;
01084    case SIG_FXSLS:
01085       return ANALOG_SIG_FXSLS;
01086    case SIG_FXSGS:
01087       return ANALOG_SIG_FXSGS;
01088    case SIG_FXSKS:
01089       return ANALOG_SIG_FXSKS;
01090    case SIG_EMWINK:
01091       return ANALOG_SIG_EMWINK;
01092    case SIG_EM:
01093       return ANALOG_SIG_EM;
01094    case SIG_EM_E1:
01095       return ANALOG_SIG_EM_E1;
01096    case SIG_FEATD:
01097       return ANALOG_SIG_FEATD;
01098    case SIG_FEATDMF:
01099       return ANALOG_SIG_FEATDMF;
01100    case SIG_E911:
01101       return SIG_E911;
01102    case SIG_FGC_CAMA:
01103       return ANALOG_SIG_FGC_CAMA;
01104    case SIG_FGC_CAMAMF:
01105       return ANALOG_SIG_FGC_CAMAMF;
01106    case SIG_FEATB:
01107       return ANALOG_SIG_FEATB;
01108    case SIG_SFWINK:
01109       return ANALOG_SIG_SFWINK;
01110    case SIG_SF:
01111       return ANALOG_SIG_SF;
01112    case SIG_SF_FEATD:
01113       return ANALOG_SIG_SF_FEATD;
01114    case SIG_SF_FEATDMF:
01115       return ANALOG_SIG_SF_FEATDMF;
01116    case SIG_FEATDMF_TA:
01117       return ANALOG_SIG_FEATDMF_TA;
01118    case SIG_SF_FEATB:
01119       return ANALOG_SIG_FEATB;
01120    default:
01121       return -1;
01122    }
01123 }
01124 
01125 
01126 static int analog_tone_to_dahditone(enum analog_tone tone)
01127 {
01128    switch (tone) {
01129    case ANALOG_TONE_RINGTONE:
01130       return DAHDI_TONE_RINGTONE;
01131    case ANALOG_TONE_STUTTER:
01132       return DAHDI_TONE_STUTTER;
01133    case ANALOG_TONE_CONGESTION:
01134       return DAHDI_TONE_CONGESTION;
01135    case ANALOG_TONE_DIALTONE:
01136       return DAHDI_TONE_DIALTONE;
01137    case ANALOG_TONE_DIALRECALL:
01138       return DAHDI_TONE_DIALRECALL;
01139    case ANALOG_TONE_INFO:
01140       return DAHDI_TONE_INFO;
01141    default:
01142       return -1;
01143    }
01144 }
01145 
01146 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01147 {
01148    int index;
01149 
01150    switch (analogsub) {
01151    case ANALOG_SUB_REAL:
01152       index = SUB_REAL;
01153       break;
01154    case ANALOG_SUB_CALLWAIT:
01155       index = SUB_CALLWAIT;
01156       break;
01157    case ANALOG_SUB_THREEWAY:
01158       index = SUB_THREEWAY;
01159       break;
01160    default:
01161       ast_log(LOG_ERROR, "Unidentified sub!\n");
01162       index = SUB_REAL;
01163    }
01164 
01165    return index;
01166 }
01167 
01168 /*!
01169  * \internal
01170  * \brief release all members on the doomed pris list
01171  * \since 13.0
01172  *
01173  * Called priodically by the monitor threads to release spans marked for
01174  * removal.
01175  */
01176 static void release_doomed_pris(void)
01177 {
01178 #ifdef HAVE_PRI
01179    struct doomed_pri *entry;
01180 
01181    AST_LIST_LOCK(&doomed_pris);
01182    while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
01183       /* The span destruction must be done with this lock not held */
01184       AST_LIST_UNLOCK(&doomed_pris);
01185       ast_debug(4, "Destroying span %d from doomed queue.\n",
01186             entry->pri->span);
01187       pri_destroy_span(entry->pri);
01188       ast_free(entry);
01189       AST_LIST_LOCK(&doomed_pris);
01190    }
01191    AST_LIST_UNLOCK(&doomed_pris);
01192 #endif
01193 }
01194 
01195 #ifdef HAVE_PRI
01196 /*!
01197  * \brief Queue a span for destruction
01198  * \since 13.0
01199  *
01200  * \param pri the span to destroy
01201  *
01202  * Add a span to the list of spans to be destroyed later on
01203  * by the monitor thread. Allows destroying a span while holding its
01204  * lock.
01205  */
01206 static void pri_queue_for_destruction(struct sig_pri_span *pri)
01207 {
01208    struct doomed_pri *entry;
01209 
01210    AST_LIST_LOCK(&doomed_pris);
01211    AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
01212       if (entry->pri == pri) {
01213          AST_LIST_UNLOCK(&doomed_pris);
01214          return;
01215       }
01216    }
01217    entry = ast_calloc(sizeof(struct doomed_pri), 1);
01218    if (!entry) {
01219       /* Nothing useful to do here. Panic? */
01220       ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
01221       AST_LIST_UNLOCK(&doomed_pris);
01222       return;
01223    }
01224    entry->pri = pri;
01225    ast_debug(4, "Queue span %d for destruction.\n", pri->span);
01226    AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
01227    AST_LIST_UNLOCK(&doomed_pris);
01228 }
01229 #endif
01230 
01231 /*!
01232  * \internal
01233  * \brief Send a dial string to DAHDI.
01234  * \since 12.0.0
01235  *
01236  * \param pvt DAHDI private pointer
01237  * \param operation DAHDI dial operation to do to string
01238  * \param dial_str Dial string to send
01239  *
01240  * \retval 0 on success.
01241  * \retval non-zero on error.
01242  */
01243 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
01244 {
01245    int res;
01246    int offset;
01247    const char *pos;
01248    struct dahdi_dialoperation zo = {
01249       .op = operation,
01250    };
01251 
01252    /* Convert the W's to ww. */
01253    pos = dial_str;
01254    for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
01255       if (!*pos) {
01256          break;
01257       }
01258       if (*pos == 'W') {
01259          /* Convert 'W' to "ww" */
01260          ++pos;
01261          if (offset >= sizeof(zo.dialstr) - 3) {
01262             /* No room to expand */
01263             break;
01264          }
01265          zo.dialstr[offset] = 'w';
01266          ++offset;
01267          zo.dialstr[offset] = 'w';
01268          continue;
01269       }
01270       zo.dialstr[offset] = *pos++;
01271    }
01272    /* The zo initialization has already terminated the dialstr. */
01273 
01274    ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
01275       pvt->channel, dial_str, zo.dialstr);
01276    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
01277    if (res) {
01278       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
01279          pvt->channel, dial_str, strerror(errno));
01280    }
01281 
01282    return res;
01283 }
01284 
01285 static enum analog_event dahdievent_to_analogevent(int event);
01286 static int bump_gains(struct dahdi_pvt *p);
01287 static int dahdi_setlinear(int dfd, int linear);
01288 
01289 static int my_start_cid_detect(void *pvt, int cid_signalling)
01290 {
01291    struct dahdi_pvt *p = pvt;
01292    int index = SUB_REAL;
01293    p->cs = callerid_new(cid_signalling);
01294    if (!p->cs) {
01295       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01296       return -1;
01297    }
01298    bump_gains(p);
01299    dahdi_setlinear(p->subs[index].dfd, 0);
01300 
01301    return 0;
01302 }
01303 
01304 static int restore_gains(struct dahdi_pvt *p);
01305 
01306 static int my_stop_cid_detect(void *pvt)
01307 {
01308    struct dahdi_pvt *p = pvt;
01309    int index = SUB_REAL;
01310 
01311    if (p->cs) {
01312       callerid_free(p->cs);
01313    }
01314 
01315    /* Restore linear mode after Caller*ID processing */
01316    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01317    restore_gains(p);
01318 
01319    return 0;
01320 }
01321 
01322 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01323 {
01324    struct dahdi_pvt *p = pvt;
01325    struct analog_pvt *analog_p = p->sig_pvt;
01326    struct pollfd poller;
01327    char *name, *num;
01328    int index = SUB_REAL;
01329    int res;
01330    unsigned char buf[256];
01331    int flags;
01332 
01333    poller.fd = p->subs[SUB_REAL].dfd;
01334    poller.events = POLLPRI | POLLIN;
01335    poller.revents = 0;
01336 
01337    res = poll(&poller, 1, timeout);
01338 
01339    if (poller.revents & POLLPRI) {
01340       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01341       return 1;
01342    }
01343 
01344    if (poller.revents & POLLIN) {
01345       /*** NOTES ***/
01346       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01347        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01348        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01349        * a failure and die, and returning 2 means no event was received. */
01350       res = read(p->subs[index].dfd, buf, sizeof(buf));
01351       if (res < 0) {
01352          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01353          return -1;
01354       }
01355 
01356       if (analog_p->ringt > 0) {
01357          if (!(--analog_p->ringt)) {
01358             /* only return if we timeout from a ring event */
01359             return -1;
01360          }
01361       }
01362 
01363       if (p->cid_signalling == CID_SIG_V23_JP) {
01364          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01365       } else {
01366          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01367       }
01368       if (res < 0) {
01369          /*
01370           * The previous diagnostic message output likely
01371           * explains why it failed.
01372           */
01373          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01374          return -1;
01375       }
01376 
01377       if (res == 1) {
01378          callerid_get(p->cs, &name, &num, &flags);
01379          if (name)
01380             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01381          if (num)
01382             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01383 
01384          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01385          return 0;
01386       }
01387    }
01388 
01389    *ev = ANALOG_EVENT_NONE;
01390    return 2;
01391 }
01392 
01393 static const char *event2str(int event);
01394 
01395 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01396 {
01397    unsigned char buf[256];
01398    int distMatches;
01399    int curRingData[RING_PATTERNS];
01400    int receivedRingT;
01401    int counter1;
01402    int counter;
01403    int i;
01404    int res;
01405    int checkaftercid = 0;
01406    const char *matched_context;
01407    struct dahdi_pvt *p = pvt;
01408    struct analog_pvt *analog_p = p->sig_pvt;
01409 
01410    if (ringdata == NULL) {
01411       ringdata = curRingData;
01412    } else {
01413       checkaftercid = 1;
01414    }
01415 
01416    /* We must have a ring by now so lets try to listen for distinctive ringing */
01417    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01418       /* Clear the current ring data array so we don't have old data in it. */
01419       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01420          ringdata[receivedRingT] = 0;
01421       receivedRingT = 0;
01422 
01423       if (checkaftercid && distinctiveringaftercid) {
01424          ast_verb(3, "Detecting post-CID distinctive ring\n");
01425       }
01426 
01427       for (;;) {
01428          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01429          res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
01430          if (res) {
01431             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01432             ast_hangup(chan);
01433             return 1;
01434          }
01435          if (i & DAHDI_IOMUX_SIGEVENT) {
01436             res = dahdi_get_event(p->subs[idx].dfd);
01437             ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
01438             if (res == DAHDI_EVENT_NOALARM) {
01439                p->inalarm = 0;
01440                analog_p->inalarm = 0;
01441             } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
01442                /* Let us detect distinctive ring */
01443                ringdata[receivedRingT] = analog_p->ringt;
01444 
01445                if (analog_p->ringt < analog_p->ringt_base / 2) {
01446                   break;
01447                }
01448                /* Increment the ringT counter so we can match it against
01449                   values in chan_dahdi.conf for distinctive ring */
01450                if (++receivedRingT == RING_PATTERNS) {
01451                   break;
01452                }
01453             }
01454          } else if (i & DAHDI_IOMUX_READ) {
01455             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01456             if (res < 0) {
01457                if (errno != ELAST) {
01458                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01459                   ast_hangup(chan);
01460                   return 1;
01461                }
01462                break;
01463             }
01464             if (analog_p->ringt > 0) {
01465                if (!(--analog_p->ringt)) {
01466                   break;
01467                }
01468             }
01469          }
01470       }
01471    }
01472 
01473    /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01474    ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
01475    matched_context = p->defcontext;
01476    for (counter = 0; counter < 3; counter++) {
01477       int range = p->drings.ringnum[counter].range;
01478 
01479       distMatches = 0;
01480       ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
01481          p->drings.ringnum[counter].ring[0],
01482          p->drings.ringnum[counter].ring[1],
01483          p->drings.ringnum[counter].ring[2],
01484          range);
01485       for (counter1 = 0; counter1 < 3; counter1++) {
01486          int ring = p->drings.ringnum[counter].ring[counter1];
01487 
01488          if (ring == -1) {
01489             ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01490                ringdata[counter1]);
01491             distMatches++;
01492          } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
01493             ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
01494                ringdata[counter1], ring - range, ring + range);
01495             distMatches++;
01496          } else {
01497             /* The current dring pattern cannot match. */
01498             break;
01499          }
01500       }
01501 
01502       if (distMatches == 3) {
01503          /* The ring matches, set the context to whatever is for distinctive ring.. */
01504          matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
01505          ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
01506          break;
01507       }
01508    }
01509 
01510    /* Set selected distinctive ring context if not already set. */
01511    if (strcmp(p->context, matched_context) != 0) {
01512       ast_copy_string(p->context, matched_context, sizeof(p->context));
01513       ast_channel_context_set(chan, matched_context);
01514    }
01515 
01516    return 0;
01517 }
01518 
01519 static int my_stop_callwait(void *pvt)
01520 {
01521    struct dahdi_pvt *p = pvt;
01522    p->callwaitingrepeat = 0;
01523    p->cidcwexpire = 0;
01524    p->cid_suppress_expire = 0;
01525 
01526    return 0;
01527 }
01528 
01529 static int send_callerid(struct dahdi_pvt *p);
01530 static int save_conference(struct dahdi_pvt *p);
01531 static int restore_conference(struct dahdi_pvt *p);
01532 
01533 static int my_callwait(void *pvt)
01534 {
01535    struct dahdi_pvt *p = pvt;
01536 
01537    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01538    if (p->cidspill) {
01539       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01540       ast_free(p->cidspill);
01541    }
01542 
01543    /*
01544     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01545     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01546     */
01547    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01548       return -1;
01549    save_conference(p);
01550    /* Silence */
01551    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01552    if (!p->callwaitrings && p->callwaitingcallerid) {
01553       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01554       p->callwaitcas = 1;
01555       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01556    } else {
01557       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01558       p->callwaitcas = 0;
01559       p->cidlen = 2400 + READ_SIZE * 4;
01560    }
01561    p->cidpos = 0;
01562    send_callerid(p);
01563 
01564    return 0;
01565 }
01566 
01567 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01568 {
01569    struct dahdi_pvt *p = pvt;
01570 
01571    ast_debug(2, "Starting cid spill\n");
01572 
01573    if (p->cidspill) {
01574       ast_log(LOG_WARNING, "cidspill already exists??\n");
01575       ast_free(p->cidspill);
01576    }
01577 
01578    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01579       if (cwcid == 0) {
01580          p->cidlen = ast_callerid_generate(p->cidspill,
01581             caller->id.name.str,
01582             caller->id.number.str,
01583             AST_LAW(p));
01584       } else {
01585          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01586             caller->id.name.str, caller->id.number.str);
01587          p->callwaitcas = 0;
01588          p->cidcwexpire = 0;
01589          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01590             caller->id.name.str,
01591             caller->id.number.str,
01592             AST_LAW(p));
01593          p->cidlen += READ_SIZE * 4;
01594       }
01595       p->cidpos = 0;
01596       p->cid_suppress_expire = 0;
01597       send_callerid(p);
01598    }
01599    return 0;
01600 }
01601 
01602 static int my_dsp_reset_and_flush_digits(void *pvt)
01603 {
01604    struct dahdi_pvt *p = pvt;
01605    if (p->dsp)
01606       ast_dsp_digitreset(p->dsp);
01607 
01608    return 0;
01609 }
01610 
01611 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01612 {
01613    struct dahdi_pvt *p = pvt;
01614 
01615    if (p->channel == CHAN_PSEUDO)
01616       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01617 
01618    if (mode == ANALOG_DIGITMODE_DTMF) {
01619       /* If we do hardware dtmf, no need for a DSP */
01620       if (p->hardwaredtmf) {
01621          if (p->dsp) {
01622             ast_dsp_free(p->dsp);
01623             p->dsp = NULL;
01624          }
01625          return 0;
01626       }
01627 
01628       if (!p->dsp) {
01629          p->dsp = ast_dsp_new();
01630          if (!p->dsp) {
01631             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01632             return -1;
01633          }
01634       }
01635 
01636       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01637    } else if (mode == ANALOG_DIGITMODE_MF) {
01638       if (!p->dsp) {
01639          p->dsp = ast_dsp_new();
01640          if (!p->dsp) {
01641             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01642             return -1;
01643          }
01644       }
01645       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01646    }
01647    return 0;
01648 }
01649 
01650 static int dahdi_wink(struct dahdi_pvt *p, int index);
01651 
01652 static int my_wink(void *pvt, enum analog_sub sub)
01653 {
01654    struct dahdi_pvt *p = pvt;
01655    int index = analogsub_to_dahdisub(sub);
01656    if (index != SUB_REAL) {
01657       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
01658    }
01659    return dahdi_wink(p, index);
01660 }
01661 
01662 static void wakeup_sub(struct dahdi_pvt *p, int a);
01663 
01664 static int reset_conf(struct dahdi_pvt *p);
01665 
01666 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
01667 
01668 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
01669 {
01670    struct ast_frame *f = *dest;
01671    struct dahdi_pvt *p = pvt;
01672    int idx = analogsub_to_dahdisub(analog_index);
01673 
01674    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
01675       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
01676       (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
01677 
01678    if (f->subclass.integer == 'f') {
01679       if (f->frametype == AST_FRAME_DTMF_END) {
01680          /* Fax tone -- Handle and return NULL */
01681          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
01682             /* If faxbuffers are configured, use them for the fax transmission */
01683             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
01684                struct dahdi_bufferinfo bi = {
01685                   .txbufpolicy = p->faxbuf_policy,
01686                   .bufsize = p->bufsize,
01687                   .numbufs = p->faxbuf_no
01688                };
01689                int res;
01690 
01691                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
01692                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
01693                } else {
01694                   p->bufferoverrideinuse = 1;
01695                }
01696             }
01697             p->faxhandled = 1;
01698             if (p->dsp) {
01699                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
01700                ast_dsp_set_features(p->dsp, p->dsp_features);
01701                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
01702             }
01703             if (strcmp(ast_channel_exten(ast), "fax")) {
01704                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
01705 
01706                /* We need to unlock 'ast' here because ast_exists_extension has the
01707                 * potential to start autoservice on the channel. Such action is prone
01708                 * to deadlock.
01709                 */
01710                ast_mutex_unlock(&p->lock);
01711                ast_channel_unlock(ast);
01712                if (ast_exists_extension(ast, target_context, "fax", 1,
01713                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
01714                   ast_channel_lock(ast);
01715                   ast_mutex_lock(&p->lock);
01716                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
01717                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
01718                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
01719                   if (ast_async_goto(ast, target_context, "fax", 1))
01720                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
01721                } else {
01722                   ast_channel_lock(ast);
01723                   ast_mutex_lock(&p->lock);
01724                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
01725                }
01726             } else {
01727                ast_debug(1, "Already in a fax extension, not redirecting\n");
01728             }
01729          } else {
01730             ast_debug(1, "Fax already handled\n");
01731          }
01732          dahdi_confmute(p, 0);
01733       }
01734       p->subs[idx].f.frametype = AST_FRAME_NULL;
01735       p->subs[idx].f.subclass.integer = 0;
01736       *dest = &p->subs[idx].f;
01737    }
01738 }
01739 
01740 static void my_lock_private(void *pvt)
01741 {
01742    struct dahdi_pvt *p = pvt;
01743    ast_mutex_lock(&p->lock);
01744 }
01745 
01746 static void my_unlock_private(void *pvt)
01747 {
01748    struct dahdi_pvt *p = pvt;
01749    ast_mutex_unlock(&p->lock);
01750 }
01751 
01752 static void my_deadlock_avoidance_private(void *pvt)
01753 {
01754    struct dahdi_pvt *p = pvt;
01755 
01756    DEADLOCK_AVOIDANCE(&p->lock);
01757 }
01758 
01759 static struct ast_manager_event_blob *dahdichannel_to_ami(struct stasis_message *msg)
01760 {
01761    RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
01762    struct ast_channel_blob *obj = stasis_message_data(msg);
01763    struct ast_json *span, *channel;
01764 
01765    channel_string = ast_manager_build_channel_state_string(obj->snapshot);
01766    if (!channel_string) {
01767       return NULL;
01768    }
01769 
01770    span = ast_json_object_get(obj->blob, "span");
01771    channel = ast_json_object_get(obj->blob, "channel");
01772 
01773    return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
01774       "%s"
01775       "DAHDISpan: %u\r\n"
01776       "DAHDIChannel: %s\r\n",
01777       ast_str_buffer(channel_string),
01778       (unsigned int)ast_json_integer_get(span),
01779       ast_json_string_get(channel));
01780 }
01781 
01782 STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,
01783    .to_ami = dahdichannel_to_ami,
01784    );
01785 
01786 /*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
01787 static void publish_dahdichannel(struct ast_channel *chan, int span, const char *dahdi_channel)
01788 {
01789    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
01790 
01791    ast_assert(dahdi_channel != NULL);
01792 
01793    blob = ast_json_pack("{s: i, s: s}",
01794       "span", span,
01795       "channel", dahdi_channel);
01796    if (!blob) {
01797       return;
01798    }
01799 
01800    ast_channel_lock(chan);
01801    ast_channel_publish_blob(chan, dahdichannel_type(), blob);
01802    ast_channel_unlock(chan);
01803 }
01804 
01805 /*!
01806  * \internal
01807  * \brief Post an AMI DAHDI channel association event.
01808  * \since 1.8
01809  *
01810  * \param p DAHDI private pointer
01811  * \param chan Channel associated with the private pointer
01812  *
01813  * \return Nothing
01814  */
01815 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
01816 {
01817    char ch_name[20];
01818 
01819    if (p->channel < CHAN_PSEUDO) {
01820       /* No B channel */
01821       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
01822    } else if (p->channel == CHAN_PSEUDO) {
01823       /* Pseudo channel */
01824       strcpy(ch_name, "pseudo");
01825    } else {
01826       /* Real channel */
01827       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
01828    }
01829    publish_dahdichannel(chan, p->span, ch_name);
01830 }
01831 
01832 #ifdef HAVE_PRI
01833 /*!
01834  * \internal
01835  * \brief Post an AMI DAHDI channel association event.
01836  * \since 1.8
01837  *
01838  * \param pvt DAHDI private pointer
01839  * \param chan Channel associated with the private pointer
01840  *
01841  * \return Nothing
01842  */
01843 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
01844 {
01845    struct dahdi_pvt *p = pvt;
01846 
01847    dahdi_ami_channel_event(p, chan);
01848 }
01849 #endif
01850 
01851 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
01852 *  returns the last value of the linear setting
01853 */
01854 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
01855 {
01856    struct dahdi_pvt *p = pvt;
01857    int oldval;
01858    int idx = analogsub_to_dahdisub(sub);
01859 
01860    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
01861    oldval = p->subs[idx].linear;
01862    p->subs[idx].linear = linear_mode ? 1 : 0;
01863    return oldval;
01864 }
01865 
01866 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
01867 {
01868    struct dahdi_pvt *p = pvt;
01869    int idx = analogsub_to_dahdisub(sub);
01870 
01871    p->subs[idx].inthreeway = inthreeway;
01872 }
01873 
01874 static int get_alarms(struct dahdi_pvt *p);
01875 static void handle_alarms(struct dahdi_pvt *p, int alms);
01876 static void my_get_and_handle_alarms(void *pvt)
01877 {
01878    int res;
01879    struct dahdi_pvt *p = pvt;
01880 
01881    res = get_alarms(p);
01882    handle_alarms(p, res);
01883 }
01884 
01885 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
01886 {
01887    RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(chan), ast_channel_cleanup);
01888 
01889    if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
01890       struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
01891 
01892       if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
01893          return p->sig_pvt;
01894       }
01895    }
01896    return NULL;
01897 }
01898 
01899 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
01900 {
01901    struct dahdi_pvt *p = pvt;
01902    int dahdi_sub = analogsub_to_dahdisub(sub);
01903    return p->subs[dahdi_sub].dfd;
01904 }
01905 
01906 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
01907 {
01908    struct dahdi_pvt *p = pvt;
01909 
01910    /* Choose proper cadence */
01911    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01912       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01913          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
01914       *cid_rings = cidrings[p->distinctivering - 1];
01915    } else {
01916       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01917          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
01918       *cid_rings = p->sendcalleridafter;
01919    }
01920 }
01921 
01922 static void my_set_alarm(void *pvt, int in_alarm)
01923 {
01924    struct dahdi_pvt *p = pvt;
01925 
01926    p->inalarm = in_alarm;
01927 }
01928 
01929 static void my_set_dialing(void *pvt, int is_dialing)
01930 {
01931    struct dahdi_pvt *p = pvt;
01932 
01933    p->dialing = is_dialing;
01934 }
01935 
01936 static void my_set_outgoing(void *pvt, int is_outgoing)
01937 {
01938    struct dahdi_pvt *p = pvt;
01939 
01940    p->outgoing = is_outgoing;
01941 }
01942 
01943 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01944 static void my_set_digital(void *pvt, int is_digital)
01945 {
01946    struct dahdi_pvt *p = pvt;
01947 
01948    p->digital = is_digital;
01949 }
01950 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01951 
01952 #if defined(HAVE_SS7)
01953 static void my_set_inservice(void *pvt, int is_inservice)
01954 {
01955    struct dahdi_pvt *p = pvt;
01956 
01957    p->inservice = is_inservice;
01958 }
01959 #endif   /* defined(HAVE_SS7) */
01960 
01961 #if defined(HAVE_SS7)
01962 static void my_set_locallyblocked(void *pvt, int is_blocked)
01963 {
01964    struct dahdi_pvt *p = pvt;
01965 
01966    p->locallyblocked = is_blocked;
01967 }
01968 #endif   /* defined(HAVE_SS7) */
01969 
01970 #if defined(HAVE_SS7)
01971 static void my_set_remotelyblocked(void *pvt, int is_blocked)
01972 {
01973    struct dahdi_pvt *p = pvt;
01974 
01975    p->remotelyblocked = is_blocked;
01976 }
01977 #endif   /* defined(HAVE_SS7) */
01978 
01979 static void my_set_ringtimeout(void *pvt, int ringt)
01980 {
01981    struct dahdi_pvt *p = pvt;
01982    p->ringt = ringt;
01983 }
01984 
01985 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
01986 {
01987    struct dahdi_pvt *p = pvt;
01988 
01989    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
01990       ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
01991       gettimeofday(&p->waitingfordt, NULL);
01992       ast_setstate(ast, AST_STATE_OFFHOOK);
01993    }
01994 }
01995 
01996 static int my_check_waitingfordt(void *pvt)
01997 {
01998    struct dahdi_pvt *p = pvt;
01999 
02000    if (p->waitingfordt.tv_sec) {
02001       return 1;
02002    }
02003 
02004    return 0;
02005 }
02006 
02007 static void my_set_confirmanswer(void *pvt, int flag)
02008 {
02009    struct dahdi_pvt *p = pvt;
02010    p->confirmanswer = flag;
02011 }
02012 
02013 static int my_check_confirmanswer(void *pvt)
02014 {
02015    struct dahdi_pvt *p = pvt;
02016    if (p->confirmanswer) {
02017       return 1;
02018    }
02019 
02020    return 0;
02021 }
02022 
02023 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02024 {
02025    struct dahdi_pvt *p = pvt;
02026 
02027    p->callwaiting = callwaiting_enable;
02028 }
02029 
02030 static void my_cancel_cidspill(void *pvt)
02031 {
02032    struct dahdi_pvt *p = pvt;
02033 
02034    ast_free(p->cidspill);
02035    p->cidspill = NULL;
02036    restore_conference(p);
02037 }
02038 
02039 static int my_confmute(void *pvt, int mute)
02040 {
02041    struct dahdi_pvt *p = pvt;
02042    return dahdi_confmute(p, mute);
02043 }
02044 
02045 static void my_set_pulsedial(void *pvt, int flag)
02046 {
02047    struct dahdi_pvt *p = pvt;
02048    p->pulsedial = flag;
02049 }
02050 
02051 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02052 {
02053    struct dahdi_pvt *p = pvt;
02054 
02055    p->owner = new_owner;
02056 }
02057 
02058 static const char *my_get_orig_dialstring(void *pvt)
02059 {
02060    struct dahdi_pvt *p = pvt;
02061 
02062    return p->dialstring;
02063 }
02064 
02065 static void my_increase_ss_count(void)
02066 {
02067    ast_mutex_lock(&ss_thread_lock);
02068    ss_thread_count++;
02069    ast_mutex_unlock(&ss_thread_lock);
02070 }
02071 
02072 static void my_decrease_ss_count(void)
02073 {
02074    ast_mutex_lock(&ss_thread_lock);
02075    ss_thread_count--;
02076    ast_cond_signal(&ss_thread_complete);
02077    ast_mutex_unlock(&ss_thread_lock);
02078 }
02079 
02080 static void my_all_subchannels_hungup(void *pvt)
02081 {
02082    struct dahdi_pvt *p = pvt;
02083    int res, law;
02084 
02085    p->faxhandled = 0;
02086    p->didtdd = 0;
02087 
02088    if (p->dsp) {
02089       ast_dsp_free(p->dsp);
02090       p->dsp = NULL;
02091    }
02092 
02093    p->law = p->law_default;
02094    law = p->law_default;
02095    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02096    if (res < 0)
02097       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02098 
02099    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02100 
02101 #if 1
02102    {
02103    int i;
02104    p->owner = NULL;
02105    /* Cleanup owners here */
02106    for (i = 0; i < 3; i++) {
02107       p->subs[i].owner = NULL;
02108    }
02109    }
02110 #endif
02111 
02112    reset_conf(p);
02113    if (num_restart_pending == 0) {
02114       restart_monitor();
02115    }
02116 }
02117 
02118 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02119 
02120 static int my_conf_del(void *pvt, enum analog_sub sub)
02121 {
02122    struct dahdi_pvt *p = pvt;
02123    int x = analogsub_to_dahdisub(sub);
02124 
02125    return conf_del(p, &p->subs[x], x);
02126 }
02127 
02128 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02129 
02130 static int my_conf_add(void *pvt, enum analog_sub sub)
02131 {
02132    struct dahdi_pvt *p = pvt;
02133    int x = analogsub_to_dahdisub(sub);
02134 
02135    return conf_add(p, &p->subs[x], x, 0);
02136 }
02137 
02138 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02139 
02140 static int my_complete_conference_update(void *pvt, int needconference)
02141 {
02142    struct dahdi_pvt *p = pvt;
02143    int needconf = needconference;
02144    int x;
02145    int useslavenative;
02146    struct dahdi_pvt *slave = NULL;
02147 
02148    useslavenative = isslavenative(p, &slave);
02149 
02150    /* If we have a slave, add him to our conference now. or DAX
02151       if this is slave native */
02152    for (x = 0; x < MAX_SLAVES; x++) {
02153       if (p->slaves[x]) {
02154          if (useslavenative)
02155             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02156          else {
02157             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02158             needconf++;
02159          }
02160       }
02161    }
02162    /* If we're supposed to be in there, do so now */
02163    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02164       if (useslavenative)
02165          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02166       else {
02167          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02168          needconf++;
02169       }
02170    }
02171    /* If we have a master, add ourselves to his conference */
02172    if (p->master) {
02173       if (isslavenative(p->master, NULL)) {
02174          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02175       } else {
02176          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02177       }
02178    }
02179    if (!needconf) {
02180       /* Nobody is left (or should be left) in our conference.
02181          Kill it. */
02182       p->confno = -1;
02183    }
02184 
02185    return 0;
02186 }
02187 
02188 static int check_for_conference(struct dahdi_pvt *p);
02189 
02190 static int my_check_for_conference(void *pvt)
02191 {
02192    struct dahdi_pvt *p = pvt;
02193    return check_for_conference(p);
02194 }
02195 
02196 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)
02197 {
02198    struct dahdi_pvt *p = pvt;
02199    int da, db;
02200    int tchan;
02201    int tinthreeway;
02202 
02203    da = analogsub_to_dahdisub(a);
02204    db = analogsub_to_dahdisub(b);
02205 
02206    tchan = p->subs[da].chan;
02207    p->subs[da].chan = p->subs[db].chan;
02208    p->subs[db].chan = tchan;
02209 
02210    tinthreeway = p->subs[da].inthreeway;
02211    p->subs[da].inthreeway = p->subs[db].inthreeway;
02212    p->subs[db].inthreeway = tinthreeway;
02213 
02214    p->subs[da].owner = ast_a;
02215    p->subs[db].owner = ast_b;
02216 
02217    if (ast_a)
02218       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02219    if (ast_b)
02220       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02221 
02222    wakeup_sub(p, a);
02223    wakeup_sub(p, b);
02224 
02225    return;
02226 }
02227 
02228 /*!
02229  * \internal
02230  * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
02231  * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
02232  *
02233  * \param callid_created value returned from ast_callid_threadstorage_auto()
02234  */
02235 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created);
02236 
02237 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid);
02238 
02239 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02240 {
02241    ast_callid callid = 0;
02242    int callid_created = ast_callid_threadstorage_auto(&callid);
02243    struct dahdi_pvt *p = pvt;
02244    int dsub = analogsub_to_dahdisub(sub);
02245 
02246    return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
02247 }
02248 
02249 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02250 static int dahdi_setlaw(int dfd, int law)
02251 {
02252    int res;
02253    res = ioctl(dfd, DAHDI_SETLAW, &law);
02254    if (res)
02255       return res;
02256    return 0;
02257 }
02258 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02259 
02260 #if defined(HAVE_PRI)
02261 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
02262    enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
02263    const struct ast_channel *requestor)
02264 {
02265    struct dahdi_pvt *p = pvt;
02266    int audio;
02267    int newlaw = -1;
02268    ast_callid callid = 0;
02269    int callid_created = ast_callid_threadstorage_auto(&callid);
02270 
02271    switch (p->sig) {
02272    case SIG_PRI_LIB_HANDLE_CASES:
02273       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02274          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02275          break;
02276       }
02277       /* Fall through */
02278    default:
02279       /* Set to audio mode at this point */
02280       audio = 1;
02281       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02282          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02283             p->channel, audio, strerror(errno));
02284       }
02285       break;
02286    }
02287 
02288    if (law != SIG_PRI_DEFLAW) {
02289       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02290    }
02291 
02292    ast_copy_string(p->exten, exten, sizeof(p->exten));
02293 
02294    switch (law) {
02295       case SIG_PRI_DEFLAW:
02296          newlaw = 0;
02297          break;
02298       case SIG_PRI_ALAW:
02299          newlaw = DAHDI_LAW_ALAW;
02300          break;
02301       case SIG_PRI_ULAW:
02302          newlaw = DAHDI_LAW_MULAW;
02303          break;
02304    }
02305 
02306    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
02307 }
02308 #endif   /* defined(HAVE_PRI) */
02309 
02310 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02311 
02312 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02313 /*!
02314  * \internal
02315  * \brief Open the PRI/SS7 channel media path.
02316  * \since 1.8
02317  *
02318  * \param p Channel private control structure.
02319  *
02320  * \return Nothing
02321  */
02322 static void my_pri_ss7_open_media(void *p)
02323 {
02324    struct dahdi_pvt *pvt = p;
02325    int res;
02326    int dfd;
02327    int set_val;
02328 
02329    dfd = pvt->subs[SUB_REAL].dfd;
02330 
02331    /* Open the media path. */
02332    set_val = 1;
02333    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02334    if (res < 0) {
02335       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02336          pvt->channel, strerror(errno));
02337    }
02338 
02339    /* Set correct companding law for this call. */
02340    res = dahdi_setlaw(dfd, pvt->law);
02341    if (res < 0) {
02342       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02343    }
02344 
02345    /* Set correct gain for this call. */
02346    if (pvt->digital) {
02347       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02348    } else {
02349       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02350          pvt->law);
02351    }
02352    if (res < 0) {
02353       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02354    }
02355 
02356    if (pvt->dsp_features && pvt->dsp) {
02357       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02358       pvt->dsp_features = 0;
02359    }
02360 }
02361 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02362 
02363 #if defined(HAVE_PRI)
02364 /*!
02365  * \internal
02366  * \brief Ask DAHDI to dial the given dial string.
02367  * \since 1.8.11
02368  *
02369  * \param p Channel private control structure.
02370  * \param dial_string String to pass to DAHDI to dial.
02371  *
02372  * \note The channel private lock needs to be held when calling.
02373  *
02374  * \return Nothing
02375  */
02376 static void my_pri_dial_digits(void *p, const char *dial_string)
02377 {
02378    char dial_str[DAHDI_MAX_DTMF_BUF];
02379    struct dahdi_pvt *pvt = p;
02380    int res;
02381 
02382    snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
02383    res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
02384    if (!res) {
02385       pvt->dialing = 1;
02386    }
02387 }
02388 #endif   /* defined(HAVE_PRI) */
02389 
02390 static int unalloc_sub(struct dahdi_pvt *p, int x);
02391 
02392 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02393 {
02394    struct dahdi_pvt *p = pvt;
02395 
02396    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02397 }
02398 
02399 static int alloc_sub(struct dahdi_pvt *p, int x);
02400 
02401 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02402 {
02403    struct dahdi_pvt *p = pvt;
02404 
02405    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02406 }
02407 
02408 static int has_voicemail(struct dahdi_pvt *p);
02409 
02410 static int my_has_voicemail(void *pvt)
02411 {
02412    struct dahdi_pvt *p = pvt;
02413 
02414    return has_voicemail(p);
02415 }
02416 
02417 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02418 {
02419    struct dahdi_pvt *p = pvt;
02420    int index;
02421 
02422    index = analogsub_to_dahdisub(sub);
02423 
02424    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02425 }
02426 
02427 static enum analog_event dahdievent_to_analogevent(int event)
02428 {
02429    enum analog_event res;
02430 
02431    switch (event) {
02432    case DAHDI_EVENT_ONHOOK:
02433       res = ANALOG_EVENT_ONHOOK;
02434       break;
02435    case DAHDI_EVENT_RINGOFFHOOK:
02436       res = ANALOG_EVENT_RINGOFFHOOK;
02437       break;
02438    case DAHDI_EVENT_WINKFLASH:
02439       res = ANALOG_EVENT_WINKFLASH;
02440       break;
02441    case DAHDI_EVENT_ALARM:
02442       res = ANALOG_EVENT_ALARM;
02443       break;
02444    case DAHDI_EVENT_NOALARM:
02445       res = ANALOG_EVENT_NOALARM;
02446       break;
02447    case DAHDI_EVENT_DIALCOMPLETE:
02448       res = ANALOG_EVENT_DIALCOMPLETE;
02449       break;
02450    case DAHDI_EVENT_RINGERON:
02451       res = ANALOG_EVENT_RINGERON;
02452       break;
02453    case DAHDI_EVENT_RINGEROFF:
02454       res = ANALOG_EVENT_RINGEROFF;
02455       break;
02456    case DAHDI_EVENT_HOOKCOMPLETE:
02457       res = ANALOG_EVENT_HOOKCOMPLETE;
02458       break;
02459    case DAHDI_EVENT_PULSE_START:
02460       res = ANALOG_EVENT_PULSE_START;
02461       break;
02462    case DAHDI_EVENT_POLARITY:
02463       res = ANALOG_EVENT_POLARITY;
02464       break;
02465    case DAHDI_EVENT_RINGBEGIN:
02466       res = ANALOG_EVENT_RINGBEGIN;
02467       break;
02468    case DAHDI_EVENT_EC_DISABLED:
02469       res = ANALOG_EVENT_EC_DISABLED;
02470       break;
02471    case DAHDI_EVENT_REMOVED:
02472       res = ANALOG_EVENT_REMOVED;
02473       break;
02474    case DAHDI_EVENT_NEONMWI_ACTIVE:
02475       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02476       break;
02477    case DAHDI_EVENT_NEONMWI_INACTIVE:
02478       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02479       break;
02480 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02481    case DAHDI_EVENT_TX_CED_DETECTED:
02482       res = ANALOG_EVENT_TX_CED_DETECTED;
02483       break;
02484    case DAHDI_EVENT_RX_CED_DETECTED:
02485       res = ANALOG_EVENT_RX_CED_DETECTED;
02486       break;
02487    case DAHDI_EVENT_EC_NLP_DISABLED:
02488       res = ANALOG_EVENT_EC_NLP_DISABLED;
02489       break;
02490    case DAHDI_EVENT_EC_NLP_ENABLED:
02491       res = ANALOG_EVENT_EC_NLP_ENABLED;
02492       break;
02493 #endif
02494    case DAHDI_EVENT_PULSEDIGIT:
02495       res = ANALOG_EVENT_PULSEDIGIT;
02496       break;
02497    case DAHDI_EVENT_DTMFDOWN:
02498       res = ANALOG_EVENT_DTMFDOWN;
02499       break;
02500    case DAHDI_EVENT_DTMFUP:
02501       res = ANALOG_EVENT_DTMFUP;
02502       break;
02503    default:
02504       switch(event & 0xFFFF0000) {
02505       case DAHDI_EVENT_PULSEDIGIT:
02506       case DAHDI_EVENT_DTMFDOWN:
02507       case DAHDI_EVENT_DTMFUP:
02508          /* The event includes a digit number in the low word.
02509           * Converting it to a 'enum analog_event' would remove
02510           * that information. Thus it is returned as-is.
02511           */
02512          return event;
02513       }
02514 
02515       res = ANALOG_EVENT_ERROR;
02516       break;
02517    }
02518 
02519    return res;
02520 }
02521 
02522 static inline int dahdi_wait_event(int fd);
02523 
02524 static int my_wait_event(void *pvt)
02525 {
02526    struct dahdi_pvt *p = pvt;
02527 
02528    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02529 }
02530 
02531 static int my_get_event(void *pvt)
02532 {
02533    struct dahdi_pvt *p = pvt;
02534    int res;
02535 
02536    if (p->fake_event) {
02537       res = p->fake_event;
02538       p->fake_event = 0;
02539    } else
02540       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02541 
02542    return dahdievent_to_analogevent(res);
02543 }
02544 
02545 static int my_is_off_hook(void *pvt)
02546 {
02547    struct dahdi_pvt *p = pvt;
02548    int res;
02549    struct dahdi_params par;
02550 
02551    memset(&par, 0, sizeof(par));
02552 
02553    if (p->subs[SUB_REAL].dfd > -1)
02554       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02555    else {
02556       /* Assume not off hook on CVRS */
02557       res = 0;
02558       par.rxisoffhook = 0;
02559    }
02560    if (res) {
02561       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02562    }
02563 
02564    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02565       /* When "onhook" that means no battery on the line, and thus
02566       it is out of service..., if it's on a TDM card... If it's a channel
02567       bank, there is no telling... */
02568       return (par.rxbits > -1) || par.rxisoffhook;
02569    }
02570 
02571    return par.rxisoffhook;
02572 }
02573 
02574 static int my_set_echocanceller(void *pvt, int enable)
02575 {
02576    struct dahdi_pvt *p = pvt;
02577 
02578    if (enable)
02579       dahdi_ec_enable(p);
02580    else
02581       dahdi_ec_disable(p);
02582 
02583    return 0;
02584 }
02585 
02586 static int dahdi_ring_phone(struct dahdi_pvt *p);
02587 
02588 static int my_ring(void *pvt)
02589 {
02590    struct dahdi_pvt *p = pvt;
02591 
02592    return dahdi_ring_phone(p);
02593 }
02594 
02595 static int my_flash(void *pvt)
02596 {
02597    struct dahdi_pvt *p = pvt;
02598    int func = DAHDI_FLASH;
02599    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02600 }
02601 
02602 static inline int dahdi_set_hook(int fd, int hs);
02603 
02604 static int my_off_hook(void *pvt)
02605 {
02606    struct dahdi_pvt *p = pvt;
02607    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02608 }
02609 
02610 static void my_set_needringing(void *pvt, int value)
02611 {
02612    struct dahdi_pvt *p = pvt;
02613    p->subs[SUB_REAL].needringing = value;
02614 }
02615 
02616 static void my_set_polarity(void *pvt, int value)
02617 {
02618    struct dahdi_pvt *p = pvt;
02619 
02620    if (p->channel == CHAN_PSEUDO) {
02621       return;
02622    }
02623    p->polarity = value;
02624    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02625 }
02626 
02627 static void my_start_polarityswitch(void *pvt)
02628 {
02629    struct dahdi_pvt *p = pvt;
02630 
02631    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02632       my_set_polarity(pvt, 0);
02633    }
02634 }
02635 
02636 static void my_answer_polarityswitch(void *pvt)
02637 {
02638    struct dahdi_pvt *p = pvt;
02639 
02640    if (!p->answeronpolarityswitch) {
02641       return;
02642    }
02643 
02644    my_set_polarity(pvt, 1);
02645 }
02646 
02647 static void my_hangup_polarityswitch(void *pvt)
02648 {
02649    struct dahdi_pvt *p = pvt;
02650 
02651    if (!p->hanguponpolarityswitch) {
02652       return;
02653    }
02654 
02655    if (p->answeronpolarityswitch) {
02656       my_set_polarity(pvt, 0);
02657    } else {
02658       my_set_polarity(pvt, 1);
02659    }
02660 }
02661 
02662 static int my_start(void *pvt)
02663 {
02664    struct dahdi_pvt *p = pvt;
02665    int x = DAHDI_START;
02666 
02667    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02668 }
02669 
02670 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02671 {
02672    struct dahdi_pvt *p = pvt;
02673 
02674    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02675       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02676       return -1;
02677    }
02678 
02679    if (sub != ANALOG_SUB_REAL) {
02680       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
02681          dop->dialstr, p->channel, sub);
02682       return -1;
02683    }
02684 
02685    return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
02686 }
02687 
02688 static void dahdi_train_ec(struct dahdi_pvt *p);
02689 
02690 static int my_train_echocanceller(void *pvt)
02691 {
02692    struct dahdi_pvt *p = pvt;
02693 
02694    dahdi_train_ec(p);
02695 
02696    return 0;
02697 }
02698 
02699 static int my_is_dialing(void *pvt, enum analog_sub sub)
02700 {
02701    struct dahdi_pvt *p = pvt;
02702    int index;
02703    int x;
02704 
02705    index = analogsub_to_dahdisub(sub);
02706 
02707    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02708       ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
02709       return -1;
02710    }
02711 
02712    return x;
02713 }
02714 
02715 static int my_on_hook(void *pvt)
02716 {
02717    struct dahdi_pvt *p = pvt;
02718    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02719 }
02720 
02721 #if defined(HAVE_PRI)
02722 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02723 {
02724    struct dahdi_pvt *old_chan = chan_old;
02725    struct dahdi_pvt *new_chan = chan_new;
02726 
02727    new_chan->owner = old_chan->owner;
02728    old_chan->owner = NULL;
02729    if (new_chan->owner) {
02730       ast_channel_tech_pvt_set(new_chan->owner, new_chan);
02731       ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
02732       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02733       old_chan->subs[SUB_REAL].owner = NULL;
02734    }
02735    /* Copy any DSP that may be present */
02736    new_chan->dsp = old_chan->dsp;
02737    new_chan->dsp_features = old_chan->dsp_features;
02738    old_chan->dsp = NULL;
02739    old_chan->dsp_features = 0;
02740 
02741    /* Transfer flags from the old channel. */
02742    new_chan->dialing = old_chan->dialing;
02743    new_chan->digital = old_chan->digital;
02744    new_chan->outgoing = old_chan->outgoing;
02745    old_chan->dialing = 0;
02746    old_chan->digital = 0;
02747    old_chan->outgoing = 0;
02748 
02749    /* More stuff to transfer to the new channel. */
02750    new_chan->law = old_chan->law;
02751    strcpy(new_chan->dialstring, old_chan->dialstring);
02752 }
02753 #endif   /* defined(HAVE_PRI) */
02754 
02755 #if defined(HAVE_PRI)
02756 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
02757 {
02758    switch (tone) {
02759    case SIG_PRI_TONE_RINGTONE:
02760       return DAHDI_TONE_RINGTONE;
02761    case SIG_PRI_TONE_STUTTER:
02762       return DAHDI_TONE_STUTTER;
02763    case SIG_PRI_TONE_CONGESTION:
02764       return DAHDI_TONE_CONGESTION;
02765    case SIG_PRI_TONE_DIALTONE:
02766       return DAHDI_TONE_DIALTONE;
02767    case SIG_PRI_TONE_DIALRECALL:
02768       return DAHDI_TONE_DIALRECALL;
02769    case SIG_PRI_TONE_INFO:
02770       return DAHDI_TONE_INFO;
02771    case SIG_PRI_TONE_BUSY:
02772       return DAHDI_TONE_BUSY;
02773    default:
02774       return -1;
02775    }
02776 }
02777 #endif   /* defined(HAVE_PRI) */
02778 
02779 #if defined(HAVE_PRI)
02780 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
02781 {
02782    int x;
02783 
02784    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
02785    switch (x) {
02786    case DAHDI_EVENT_NONE:
02787       break;
02788    case DAHDI_EVENT_ALARM:
02789    case DAHDI_EVENT_NOALARM:
02790       if (sig_pri_is_alarm_ignored(pri)) {
02791          break;
02792       }
02793       /* Fall through */
02794    default:
02795       ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
02796          event2str(x), x, pri->span);
02797       break;
02798    }
02799    /* Keep track of alarm state */
02800    switch (x) {
02801    case DAHDI_EVENT_ALARM:
02802       pri_event_alarm(pri, index, 0);
02803       break;
02804    case DAHDI_EVENT_NOALARM:
02805       pri_event_noalarm(pri, index, 0);
02806       break;
02807    case DAHDI_EVENT_REMOVED:
02808       pri_queue_for_destruction(pri);
02809       break;
02810    default:
02811       break;
02812    }
02813 }
02814 #endif   /* defined(HAVE_PRI) */
02815 
02816 #if defined(HAVE_PRI)
02817 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
02818 {
02819    struct dahdi_pvt *p = pvt;
02820 
02821    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
02822 }
02823 #endif   /* defined(HAVE_PRI) */
02824 
02825 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02826 /*!
02827  * \internal
02828  * \brief Set the caller id information.
02829  * \since 1.8
02830  *
02831  * \param pvt DAHDI private structure
02832  * \param caller Caller-id information to set.
02833  *
02834  * \return Nothing
02835  */
02836 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
02837 {
02838    struct dahdi_pvt *p = pvt;
02839 
02840    ast_copy_string(p->cid_num,
02841       S_COR(caller->id.number.valid, caller->id.number.str, ""),
02842       sizeof(p->cid_num));
02843    ast_copy_string(p->cid_name,
02844       S_COR(caller->id.name.valid, caller->id.name.str, ""),
02845       sizeof(p->cid_name));
02846    ast_copy_string(p->cid_subaddr,
02847       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
02848       sizeof(p->cid_subaddr));
02849    p->cid_ton = caller->id.number.plan;
02850    p->callingpres = ast_party_id_presentation(&caller->id);
02851    if (caller->id.tag) {
02852       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
02853    }
02854    ast_copy_string(p->cid_ani,
02855       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
02856       sizeof(p->cid_ani));
02857    p->cid_ani2 = caller->ani2;
02858 }
02859 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02860 
02861 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02862 /*!
02863  * \internal
02864  * \brief Set the Dialed Number Identifier.
02865  * \since 1.8
02866  *
02867  * \param pvt DAHDI private structure
02868  * \param dnid Dialed Number Identifier string.
02869  *
02870  * \return Nothing
02871  */
02872 static void my_set_dnid(void *pvt, const char *dnid)
02873 {
02874    struct dahdi_pvt *p = pvt;
02875 
02876    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
02877 }
02878 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02879 
02880 #if defined(HAVE_PRI)
02881 /*!
02882  * \internal
02883  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
02884  * \since 1.8
02885  *
02886  * \param pvt DAHDI private structure
02887  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
02888  *
02889  * \return Nothing
02890  */
02891 static void my_set_rdnis(void *pvt, const char *rdnis)
02892 {
02893    struct dahdi_pvt *p = pvt;
02894 
02895    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
02896 }
02897 #endif   /* defined(HAVE_PRI) */
02898 
02899 #if defined(HAVE_PRI)
02900 /*!
02901  * \internal
02902  * \brief Make a dialstring for native ISDN CC to recall properly.
02903  * \since 1.8
02904  *
02905  * \param priv Channel private control structure.
02906  * \param buf Where to put the modified dialstring.
02907  * \param buf_size Size of modified dialstring buffer.
02908  *
02909  * \details
02910  * original dialstring:
02911  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
02912  *
02913  * The modified dialstring will have prefixed the channel-group section
02914  * with the ISDN channel restriction.
02915  *
02916  * buf:
02917  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
02918  *
02919  * The routine will check to see if the ISDN channel restriction is already
02920  * in the original dialstring.
02921  *
02922  * \return Nothing
02923  */
02924 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
02925 {
02926    char *dial;
02927    struct dahdi_pvt *pvt;
02928    AST_DECLARE_APP_ARGS(args,
02929       AST_APP_ARG(tech);   /* channel technology token */
02930       AST_APP_ARG(group);  /* channel/group token */
02931       //AST_APP_ARG(ext);  /* extension token */
02932       //AST_APP_ARG(opts); /* options token */
02933       //AST_APP_ARG(other);   /* Any remining unused arguments */
02934    );
02935 
02936    pvt = priv;
02937    dial = ast_strdupa(pvt->dialstring);
02938    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
02939    if (!args.tech) {
02940       ast_copy_string(buf, pvt->dialstring, buf_size);
02941       return;
02942    }
02943    if (!args.group) {
02944       /* Append the ISDN span channel restriction to the dialstring. */
02945       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
02946       return;
02947    }
02948    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
02949       /* The ISDN span channel restriction is not needed or already
02950        * in the dialstring. */
02951       ast_copy_string(buf, pvt->dialstring, buf_size);
02952       return;
02953    }
02954    /* Insert the ISDN span channel restriction into the dialstring. */
02955    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
02956 }
02957 #endif   /* defined(HAVE_PRI) */
02958 
02959 #if defined(HAVE_PRI)
02960 /*!
02961  * \internal
02962  * \brief Reevaluate the PRI span device state.
02963  * \since 1.8
02964  *
02965  * \param pri Asterisk D channel control structure.
02966  *
02967  * \return Nothing
02968  *
02969  * \note Assumes the pri->lock is already obtained.
02970  */
02971 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
02972 {
02973    unsigned idx;
02974    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
02975    unsigned in_use;     /* Number of B channels in use on the span. */
02976    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
02977    enum ast_device_state new_state;
02978 
02979    /* Count the number of B channels and the number of B channels in use. */
02980    num_b_chans = 0;
02981    in_use = 0;
02982    in_alarm = 1;
02983    for (idx = pri->numchans; idx--;) {
02984       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
02985          /* This is a B channel interface. */
02986          ++num_b_chans;
02987          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
02988             ++in_use;
02989          }
02990          if (!pri->pvts[idx]->inalarm) {
02991             /* There is a channel that is not in alarm. */
02992             in_alarm = 0;
02993          }
02994       }
02995    }
02996 
02997    /* Update the span congestion device state and report any change. */
02998    if (in_alarm) {
02999       new_state = AST_DEVICE_UNAVAILABLE;
03000    } else {
03001       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03002    }
03003    if (pri->congestion_devstate != new_state) {
03004       pri->congestion_devstate = new_state;
03005       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03006    }
03007 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03008    /* Update the span threshold device state and report any change. */
03009    if (in_alarm) {
03010       new_state = AST_DEVICE_UNAVAILABLE;
03011    } else if (!in_use) {
03012       new_state = AST_DEVICE_NOT_INUSE;
03013    } else if (!pri->user_busy_threshold) {
03014       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03015    } else {
03016       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03017          : AST_DEVICE_BUSY;
03018    }
03019    if (pri->threshold_devstate != new_state) {
03020       pri->threshold_devstate = new_state;
03021       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03022    }
03023 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03024 }
03025 #endif   /* defined(HAVE_PRI) */
03026 
03027 #if defined(HAVE_PRI)
03028 /*!
03029  * \internal
03030  * \brief Reference this module.
03031  * \since 1.8
03032  *
03033  * \return Nothing
03034  */
03035 static void my_module_ref(void)
03036 {
03037    ast_module_ref(ast_module_info->self);
03038 }
03039 #endif   /* defined(HAVE_PRI) */
03040 
03041 #if defined(HAVE_PRI)
03042 /*!
03043  * \internal
03044  * \brief Unreference this module.
03045  * \since 1.8
03046  *
03047  * \return Nothing
03048  */
03049 static void my_module_unref(void)
03050 {
03051    ast_module_unref(ast_module_info->self);
03052 }
03053 #endif   /* defined(HAVE_PRI) */
03054 
03055 #if defined(HAVE_PRI)
03056 #if defined(HAVE_PRI_CALL_WAITING)
03057 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03058 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03059 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03060 
03061 struct sig_pri_callback sig_pri_callbacks =
03062 {
03063    .handle_dchan_exception = my_handle_dchan_exception,
03064    .play_tone = my_pri_play_tone,
03065    .set_echocanceller = my_set_echocanceller,
03066    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03067    .lock_private = my_lock_private,
03068    .unlock_private = my_unlock_private,
03069    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03070    .new_ast_channel = my_new_pri_ast_channel,
03071    .fixup_chans = my_pri_fixup_chans,
03072    .set_alarm = my_set_alarm,
03073    .set_dialing = my_set_dialing,
03074    .set_outgoing = my_set_outgoing,
03075    .set_digital = my_set_digital,
03076    .set_callerid = my_set_callerid,
03077    .set_dnid = my_set_dnid,
03078    .set_rdnis = my_set_rdnis,
03079    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03080 #if defined(HAVE_PRI_CALL_WAITING)
03081    .init_config = my_pri_init_config,
03082 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03083    .get_orig_dialstring = my_get_orig_dialstring,
03084    .make_cc_dialstring = my_pri_make_cc_dialstring,
03085    .update_span_devstate = dahdi_pri_update_span_devstate,
03086    .module_ref = my_module_ref,
03087    .module_unref = my_module_unref,
03088    .dial_digits = my_pri_dial_digits,
03089    .open_media = my_pri_ss7_open_media,
03090    .ami_channel_event = my_ami_channel_event,
03091    .destroy_later = pri_queue_for_destruction,
03092 };
03093 #endif   /* defined(HAVE_PRI) */
03094 
03095 #if defined(HAVE_SS7)
03096 /*!
03097  * \internal
03098  * \brief Handle the SS7 link exception.
03099  * \since 1.8
03100  *
03101  * \param linkset Controlling linkset for the channel.
03102  * \param which Link index of the signaling channel.
03103  *
03104  * \return Nothing
03105  */
03106 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03107 {
03108    int event;
03109 
03110    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03111       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03112          linkset->span, which);
03113       return;
03114    }
03115    switch (event) {
03116    case DAHDI_EVENT_NONE:
03117       break;
03118    case DAHDI_EVENT_ALARM:
03119       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03120          event2str(event), event, linkset->span, which);
03121       sig_ss7_link_alarm(linkset, which);
03122       break;
03123    case DAHDI_EVENT_NOALARM:
03124       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03125          event2str(event), event, linkset->span, which);
03126       sig_ss7_link_noalarm(linkset, which);
03127       break;
03128    default:
03129       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03130          event2str(event), event, linkset->span, which);
03131       break;
03132    }
03133 }
03134 #endif   /* defined(HAVE_SS7) */
03135 
03136 #if defined(HAVE_SS7)
03137 static void my_ss7_set_loopback(void *pvt, int enable)
03138 {
03139    struct dahdi_pvt *p = pvt;
03140 
03141    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03142       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03143          strerror(errno));
03144    }
03145 }
03146 #endif   /* defined(HAVE_SS7) */
03147 
03148 #if defined(HAVE_SS7)
03149 /*!
03150  * \internal
03151  * \brief Find the linkset to which SS7 belongs.
03152  * \since 11.0
03153  *
03154  * \param ss7 structure to match on.
03155  *
03156  * \retval linkset if found.
03157  * \retval NULL if not found.
03158  */
03159 static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
03160 {
03161    int idx;
03162 
03163    if (!ss7) {
03164       return NULL;
03165    }
03166 
03167    for (idx = 0; idx < NUM_SPANS; ++idx) {
03168       if (linksets[idx].ss7.ss7 == ss7) {
03169          return &linksets[idx].ss7;
03170       }
03171    }
03172    return NULL;
03173 }
03174 #endif   /* defined(HAVE_SS7) */
03175 
03176 #if defined(HAVE_SS7)
03177 /*!
03178  * \internal
03179  * \brief Create a new asterisk channel structure for SS7.
03180  * \since 1.8
03181  *
03182  * \param pvt Private channel structure.
03183  * \param state Initial state of new channel.
03184  * \param law Combanding law to use.
03185  * \param exten Dialplan extension for incoming call.
03186  * \param requestor Channel requesting this new channel.
03187  *
03188  * \retval ast_channel on success.
03189  * \retval NULL on error.
03190  */
03191 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
03192 {
03193    struct dahdi_pvt *p = pvt;
03194    int audio;
03195    int newlaw;
03196    ast_callid callid = 0;
03197    int callid_created = ast_callid_threadstorage_auto(&callid);
03198 
03199    /* Set to audio mode at this point */
03200    audio = 1;
03201    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03202       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03203          p->channel, audio, strerror(errno));
03204 
03205    if (law != SIG_SS7_DEFLAW) {
03206       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03207          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03208    }
03209 
03210    ast_copy_string(p->exten, exten, sizeof(p->exten));
03211 
03212    newlaw = -1;
03213    switch (law) {
03214    case SIG_SS7_DEFLAW:
03215       newlaw = 0;
03216       break;
03217    case SIG_SS7_ALAW:
03218       newlaw = DAHDI_LAW_ALAW;
03219       break;
03220    case SIG_SS7_ULAW:
03221       newlaw = DAHDI_LAW_MULAW;
03222       break;
03223    }
03224    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
03225 }
03226 #endif   /* defined(HAVE_SS7) */
03227 
03228 #if defined(HAVE_SS7)
03229 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03230 {
03231    switch (tone) {
03232    case SIG_SS7_TONE_RINGTONE:
03233       return DAHDI_TONE_RINGTONE;
03234    case SIG_SS7_TONE_STUTTER:
03235       return DAHDI_TONE_STUTTER;
03236    case SIG_SS7_TONE_CONGESTION:
03237       return DAHDI_TONE_CONGESTION;
03238    case SIG_SS7_TONE_DIALTONE:
03239       return DAHDI_TONE_DIALTONE;
03240    case SIG_SS7_TONE_DIALRECALL:
03241       return DAHDI_TONE_DIALRECALL;
03242    case SIG_SS7_TONE_INFO:
03243       return DAHDI_TONE_INFO;
03244    case SIG_SS7_TONE_BUSY:
03245       return DAHDI_TONE_BUSY;
03246    default:
03247       return -1;
03248    }
03249 }
03250 #endif   /* defined(HAVE_SS7) */
03251 
03252 #if defined(HAVE_SS7)
03253 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03254 {
03255    struct dahdi_pvt *p = pvt;
03256 
03257    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03258 }
03259 #endif   /* defined(HAVE_SS7) */
03260 
03261 #if defined(HAVE_SS7)
03262 struct sig_ss7_callback sig_ss7_callbacks =
03263 {
03264    .lock_private = my_lock_private,
03265    .unlock_private = my_unlock_private,
03266    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03267 
03268    .set_echocanceller = my_set_echocanceller,
03269    .set_loopback = my_ss7_set_loopback,
03270 
03271    .new_ast_channel = my_new_ss7_ast_channel,
03272    .play_tone = my_ss7_play_tone,
03273 
03274    .handle_link_exception = my_handle_link_exception,
03275    .set_alarm = my_set_alarm,
03276    .set_dialing = my_set_dialing,
03277    .set_outgoing = my_set_outgoing,
03278    .set_digital = my_set_digital,
03279    .set_inservice = my_set_inservice,
03280    .set_locallyblocked = my_set_locallyblocked,
03281    .set_remotelyblocked = my_set_remotelyblocked,
03282    .set_callerid = my_set_callerid,
03283    .set_dnid = my_set_dnid,
03284    .open_media = my_pri_ss7_open_media,
03285    .find_linkset = my_ss7_find_linkset,
03286 };
03287 #endif   /* defined(HAVE_SS7) */
03288 
03289 /*!
03290  * \brief Send MWI state change
03291  *
03292  * \param mailbox This is the mailbox associated with the FXO line that the
03293  *      MWI state has changed on.
03294  * \param thereornot This argument should simply be set to 1 or 0, to indicate
03295  *      whether there are messages waiting or not.
03296  *
03297  *  \return nothing
03298  *
03299  * This function does two things:
03300  *
03301  * 1) It generates an internal Asterisk event notifying any other module that
03302  *    cares about MWI that the state of a mailbox has changed.
03303  *
03304  * 2) It runs the script specified by the mwimonitornotify option to allow
03305  *    some custom handling of the state change.
03306  */
03307 static void notify_message(char *mailbox, int thereornot)
03308 {
03309    char s[sizeof(mwimonitornotify) + 80];
03310 
03311    if (ast_strlen_zero(mailbox)) {
03312       return;
03313    }
03314 
03315    ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
03316    if (!ast_strlen_zero(mwimonitornotify)) {
03317       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03318       ast_safe_system(s);
03319    }
03320 }
03321 
03322 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03323 {
03324    struct dahdi_pvt *p = pvt;
03325 
03326    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03327       return;
03328 
03329    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03330       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03331       notify_message(p->mailbox, 1);
03332    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03333       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03334       notify_message(p->mailbox, 0);
03335    }
03336    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03337    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03338    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03339       ast_hangup(chan);
03340       return;
03341    }
03342 }
03343 
03344 static int my_have_progressdetect(void *pvt)
03345 {
03346    struct dahdi_pvt *p = pvt;
03347 
03348    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03349       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03350       return 1;
03351    } else {
03352       /* Don't have progress detection. */
03353       return 0;
03354    }
03355 }
03356 
03357 struct analog_callback analog_callbacks =
03358 {
03359    .play_tone = my_play_tone,
03360    .get_event = my_get_event,
03361    .wait_event = my_wait_event,
03362    .is_off_hook = my_is_off_hook,
03363    .set_echocanceller = my_set_echocanceller,
03364    .ring = my_ring,
03365    .flash = my_flash,
03366    .off_hook = my_off_hook,
03367    .dial_digits = my_dial_digits,
03368    .train_echocanceller = my_train_echocanceller,
03369    .on_hook = my_on_hook,
03370    .is_dialing = my_is_dialing,
03371    .allocate_sub = my_allocate_sub,
03372    .unallocate_sub = my_unallocate_sub,
03373    .swap_subs = my_swap_subchannels,
03374    .has_voicemail = my_has_voicemail,
03375    .check_for_conference = my_check_for_conference,
03376    .conf_add = my_conf_add,
03377    .conf_del = my_conf_del,
03378    .complete_conference_update = my_complete_conference_update,
03379    .start = my_start,
03380    .all_subchannels_hungup = my_all_subchannels_hungup,
03381    .lock_private = my_lock_private,
03382    .unlock_private = my_unlock_private,
03383    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03384    .handle_dtmf = my_handle_dtmf,
03385    .wink = my_wink,
03386    .new_ast_channel = my_new_analog_ast_channel,
03387    .dsp_set_digitmode = my_dsp_set_digitmode,
03388    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03389    .send_callerid = my_send_callerid,
03390    .callwait = my_callwait,
03391    .stop_callwait = my_stop_callwait,
03392    .get_callerid = my_get_callerid,
03393    .start_cid_detect = my_start_cid_detect,
03394    .stop_cid_detect = my_stop_cid_detect,
03395    .handle_notify_message = my_handle_notify_message,
03396    .increase_ss_count = my_increase_ss_count,
03397    .decrease_ss_count = my_decrease_ss_count,
03398    .distinctive_ring = my_distinctive_ring,
03399    .set_linear_mode = my_set_linear_mode,
03400    .set_inthreeway = my_set_inthreeway,
03401    .get_and_handle_alarms = my_get_and_handle_alarms,
03402    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03403    .get_sub_fd = my_get_sub_fd,
03404    .set_cadence = my_set_cadence,
03405    .set_alarm = my_set_alarm,
03406    .set_dialing = my_set_dialing,
03407    .set_outgoing = my_set_outgoing,
03408    .set_ringtimeout = my_set_ringtimeout,
03409    .set_waitingfordt = my_set_waitingfordt,
03410    .check_waitingfordt = my_check_waitingfordt,
03411    .set_confirmanswer = my_set_confirmanswer,
03412    .check_confirmanswer = my_check_confirmanswer,
03413    .set_callwaiting = my_set_callwaiting,
03414    .cancel_cidspill = my_cancel_cidspill,
03415    .confmute = my_confmute,
03416    .set_pulsedial = my_set_pulsedial,
03417    .set_new_owner = my_set_new_owner,
03418    .get_orig_dialstring = my_get_orig_dialstring,
03419    .set_needringing = my_set_needringing,
03420    .set_polarity = my_set_polarity,
03421    .start_polarityswitch = my_start_polarityswitch,
03422    .answer_polarityswitch = my_answer_polarityswitch,
03423    .hangup_polarityswitch = my_hangup_polarityswitch,
03424    .have_progressdetect = my_have_progressdetect,
03425 };
03426 
03427 /*! Round robin search locations. */
03428 static struct dahdi_pvt *round_robin[32];
03429 
03430 int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03431 {
03432    int res;
03433    if (p->subs[SUB_REAL].owner == ast)
03434       res = 0;
03435    else if (p->subs[SUB_CALLWAIT].owner == ast)
03436       res = 1;
03437    else if (p->subs[SUB_THREEWAY].owner == ast)
03438       res = 2;
03439    else {
03440       res = -1;
03441       if (!nullok)
03442          ast_log(LOG_WARNING,
03443             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03444             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03445    }
03446    return res;
03447 }
03448 
03449 /*!
03450  * \internal
03451  * \brief Obtain the specified subchannel owner lock if the owner exists.
03452  *
03453  * \param pvt Channel private struct.
03454  * \param sub_idx Subchannel owner to lock.
03455  *
03456  * \note Assumes the pvt->lock is already obtained.
03457  *
03458  * \note
03459  * Because deadlock avoidance may have been necessary, you need to confirm
03460  * the state of things before continuing.
03461  *
03462  * \return Nothing
03463  */
03464 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03465 {
03466    for (;;) {
03467       if (!pvt->subs[sub_idx].owner) {
03468          /* No subchannel owner pointer */
03469          break;
03470       }
03471       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03472          /* Got subchannel owner lock */
03473          break;
03474       }
03475       /* We must unlock the private to avoid the possibility of a deadlock */
03476       DEADLOCK_AVOIDANCE(&pvt->lock);
03477    }
03478 }
03479 
03480 static void wakeup_sub(struct dahdi_pvt *p, int a)
03481 {
03482    dahdi_lock_sub_owner(p, a);
03483    if (p->subs[a].owner) {
03484       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03485       ast_channel_unlock(p->subs[a].owner);
03486    }
03487 }
03488 
03489 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03490 {
03491    for (;;) {
03492       if (p->owner) {
03493          if (ast_channel_trylock(p->owner)) {
03494             DEADLOCK_AVOIDANCE(&p->lock);
03495          } else {
03496             ast_queue_frame(p->owner, f);
03497             ast_channel_unlock(p->owner);
03498             break;
03499          }
03500       } else
03501          break;
03502    }
03503 }
03504 
03505 static void publish_channel_alarm_clear(int channel)
03506 {
03507    RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
03508    RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
03509    if (!dahdi_chan) {
03510       return;
03511    }
03512 
03513    ast_str_set(&dahdi_chan, 0, "%d", channel);
03514    ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
03515    body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
03516    if (!body) {
03517       return;
03518    }
03519 
03520    ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
03521 }
03522 
03523 static void publish_span_alarm_clear(int span)
03524 {
03525    RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
03526 
03527    ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
03528    body = ast_json_pack("{s: i}", "Span", span);
03529    if (!body) {
03530       return;
03531    }
03532 
03533    ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
03534 }
03535 
03536 static void handle_clear_alarms(struct dahdi_pvt *p)
03537 {
03538 #if defined(HAVE_PRI)
03539    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03540       return;
03541    }
03542 #endif   /* defined(HAVE_PRI) */
03543 
03544    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03545       publish_channel_alarm_clear(p->channel);
03546    }
03547    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03548       publish_span_alarm_clear(p->span);
03549    }
03550 }
03551 
03552 #ifdef HAVE_OPENR2
03553 
03554 static int dahdi_r2_answer(struct dahdi_pvt *p)
03555 {
03556    int res = 0;
03557    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03558    * and does not has support for openr2_chan_answer_call_with_mode
03559    *  */
03560 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03561    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03562    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03563    if (!double_answer) {
03564       /* this still can result in double answer if the channel context
03565       * was configured that way */
03566       res = openr2_chan_answer_call(p->r2chan);
03567    } else if (wants_double_answer) {
03568       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03569    } else {
03570       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03571    }
03572 #else
03573    res = openr2_chan_answer_call(p->r2chan);
03574 #endif
03575    return res;
03576 }
03577 
03578 
03579 
03580 /* should be called with the ast_channel locked */
03581 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03582 {
03583    openr2_calling_party_category_t cat;
03584    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03585    struct dahdi_pvt *p = ast_channel_tech_pvt(c);
03586    if (ast_strlen_zero(catstr)) {
03587       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03588             ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03589       return p->mfcr2_category;
03590    }
03591    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03592       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03593             catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03594       return p->mfcr2_category;
03595    }
03596    ast_debug(1, "Using category %s\n", catstr);
03597    return cat;
03598 }
03599 
03600 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03601 {
03602    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03603    ast_mutex_lock(&p->lock);
03604    if (p->mfcr2call) {
03605       ast_mutex_unlock(&p->lock);
03606       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03607          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03608          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03609          the other end will see our seize as a forced release and drop the call, we will see an invalid
03610          pattern that will be seen and treated as protocol error. */
03611       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03612       return;
03613    }
03614    p->mfcr2call = 1;
03615    /* better safe than sorry ... */
03616    p->cid_name[0] = '\0';
03617    p->cid_num[0] = '\0';
03618    p->cid_subaddr[0] = '\0';
03619    p->rdnis[0] = '\0';
03620    p->exten[0] = '\0';
03621    p->mfcr2_ani_index = '\0';
03622    p->mfcr2_dnis_index = '\0';
03623    p->mfcr2_dnis_matched = 0;
03624    p->mfcr2_answer_pending = 0;
03625    p->mfcr2_call_accepted = 0;
03626    ast_mutex_unlock(&p->lock);
03627    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03628 }
03629 
03630 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03631 {
03632    int res;
03633    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03634    ast_mutex_lock(&p->lock);
03635    p->inalarm = alarm ? 1 : 0;
03636    if (p->inalarm) {
03637       res = get_alarms(p);
03638       handle_alarms(p, res);
03639    } else {
03640       handle_clear_alarms(p);
03641    }
03642    ast_mutex_unlock(&p->lock);
03643 }
03644 
03645 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03646 {
03647    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03648 }
03649 
03650 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03651 {
03652    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03653    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03654    if (p->owner) {
03655       ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
03656       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
03657    }
03658    ast_mutex_lock(&p->lock);
03659    p->mfcr2call = 0;
03660    ast_mutex_unlock(&p->lock);
03661 }
03662 
03663 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03664 {
03665    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03666       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03667          p->channel, openr2_proto_get_disconnect_string(cause));
03668       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03669       openr2_chan_set_idle(p->r2chan);
03670       ast_mutex_lock(&p->lock);
03671       p->mfcr2call = 0;
03672       ast_mutex_unlock(&p->lock);
03673    }
03674 }
03675 
03676 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03677 {
03678    struct dahdi_pvt *p;
03679    struct ast_channel *c;
03680    ast_callid callid = 0;
03681    int callid_created = ast_callid_threadstorage_auto(&callid);
03682    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03683          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03684          openr2_proto_get_category_string(category));
03685    p = openr2_chan_get_client_data(r2chan);
03686    /* if collect calls are not allowed and this is a collect call, reject it! */
03687    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03688       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03689       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03690       goto dahdi_r2_on_call_offered_cleanup;
03691    }
03692    ast_mutex_lock(&p->lock);
03693    p->mfcr2_recvd_category = category;
03694    /* if we're not supposed to use CID, clear whatever we have */
03695    if (!p->use_callerid) {
03696       ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
03697       p->cid_num[0] = 0;
03698       p->cid_name[0] = 0;
03699    }
03700    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03701    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03702       ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
03703       p->exten[0] = 's';
03704       p->exten[1] = 0;
03705    }
03706    ast_mutex_unlock(&p->lock);
03707    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03708       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03709             p->channel, p->exten, p->context);
03710       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03711       goto dahdi_r2_on_call_offered_cleanup;
03712    }
03713    if (!p->mfcr2_accept_on_offer) {
03714       /* The user wants us to start the PBX thread right away without accepting the call first */
03715       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
03716       if (c) {
03717          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03718             the call or reject it and detect the tone off condition of the other end, all of this
03719             will be done in the PBX thread now */
03720          goto dahdi_r2_on_call_offered_cleanup;
03721       }
03722       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03723       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03724    } else if (p->mfcr2_charge_calls) {
03725       ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03726       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03727    } else {
03728       ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03729       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03730    }
03731 
03732 dahdi_r2_on_call_offered_cleanup:
03733    ast_callid_threadstorage_auto_clean(callid, callid_created);
03734 }
03735 
03736 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03737 {
03738    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03739    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03740    ast_mutex_lock(&p->lock);
03741    p->mfcr2call = 0;
03742    ast_mutex_unlock(&p->lock);
03743 }
03744 
03745 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03746 {
03747    struct dahdi_pvt *p = NULL;
03748    struct ast_channel *c = NULL;
03749    ast_callid callid = 0;
03750    int callid_created = ast_callid_threadstorage_auto(&callid);
03751    p = openr2_chan_get_client_data(r2chan);
03752    dahdi_ec_enable(p);
03753    p->mfcr2_call_accepted = 1;
03754    /* if it's an incoming call ... */
03755    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03756       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03757       /* If accept on offer is not set, it means at this point the PBX thread is already
03758          launched (was launched in the 'on call offered' handler) and therefore this callback
03759          is being executed already in the PBX thread rather than the monitor thread, don't launch
03760          any other thread, just disable the openr2 reading and answer the call if needed */
03761       if (!p->mfcr2_accept_on_offer) {
03762          openr2_chan_disable_read(r2chan);
03763          if (p->mfcr2_answer_pending) {
03764             ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03765             dahdi_r2_answer(p);
03766          }
03767          goto dahdi_r2_on_call_accepted_cleanup;
03768       }
03769       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
03770       if (c) {
03771          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03772             library to forget about it */
03773          openr2_chan_disable_read(r2chan);
03774          goto dahdi_r2_on_call_accepted_cleanup;
03775       }
03776       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03777       /* failed to create the channel, bail out and report it as an out of order line */
03778       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03779       goto dahdi_r2_on_call_accepted_cleanup;
03780    }
03781    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03782    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03783    p->subs[SUB_REAL].needringing = 1;
03784    p->dialing = 0;
03785    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
03786    openr2_chan_disable_read(r2chan);
03787 
03788 dahdi_r2_on_call_accepted_cleanup:
03789    ast_callid_threadstorage_auto_clean(callid, callid_created);
03790 }
03791 
03792 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03793 {
03794    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03795    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03796    p->subs[SUB_REAL].needanswer = 1;
03797 }
03798 
03799 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03800 {
03801    /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
03802 }
03803 
03804 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03805 {
03806    switch (cause) {
03807    case OR2_CAUSE_BUSY_NUMBER:
03808       return AST_CAUSE_BUSY;
03809    case OR2_CAUSE_NETWORK_CONGESTION:
03810       return AST_CAUSE_CONGESTION;
03811    case OR2_CAUSE_OUT_OF_ORDER:
03812       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03813    case OR2_CAUSE_UNALLOCATED_NUMBER:
03814       return AST_CAUSE_UNREGISTERED;
03815    case OR2_CAUSE_NO_ANSWER:
03816       return AST_CAUSE_NO_ANSWER;
03817    case OR2_CAUSE_NORMAL_CLEARING:
03818       return AST_CAUSE_NORMAL_CLEARING;
03819    case OR2_CAUSE_UNSPECIFIED:
03820    default:
03821       return AST_CAUSE_NOTDEFINED;
03822    }
03823 }
03824 
03825 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
03826 {
03827    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03828    char cause_str[50];
03829    struct ast_control_pvt_cause_code *cause_code;
03830    int datalen = sizeof(*cause_code);
03831 
03832    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03833    ast_mutex_lock(&p->lock);
03834    if (!p->owner) {
03835       ast_mutex_unlock(&p->lock);
03836       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
03837       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03838       return;
03839    }
03840 
03841    snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
03842    datalen += strlen(cause_str);
03843    cause_code = ast_alloca(datalen);
03844    memset(cause_code, 0, datalen);
03845    cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
03846    ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
03847    ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
03848    ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
03849    ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
03850 
03851    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
03852       be done in dahdi_hangup */
03853    if (ast_channel_state(p->owner) == AST_STATE_UP) {
03854       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
03855       ast_mutex_unlock(&p->lock);
03856    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03857       /* being the forward side we must report what happened to the call to whoever requested it */
03858       switch (cause) {
03859       case OR2_CAUSE_BUSY_NUMBER:
03860          p->subs[SUB_REAL].needbusy = 1;
03861          break;
03862       case OR2_CAUSE_NETWORK_CONGESTION:
03863       case OR2_CAUSE_OUT_OF_ORDER:
03864       case OR2_CAUSE_UNALLOCATED_NUMBER:
03865       case OR2_CAUSE_NO_ANSWER:
03866       case OR2_CAUSE_UNSPECIFIED:
03867       case OR2_CAUSE_NORMAL_CLEARING:
03868          p->subs[SUB_REAL].needcongestion = 1;
03869          break;
03870       default:
03871          ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
03872       }
03873       ast_mutex_unlock(&p->lock);
03874    } else {
03875       ast_mutex_unlock(&p->lock);
03876       /* being the backward side and not UP yet, we only need to request hangup */
03877       /* TODO: what about doing this same thing when were AST_STATE_UP? */
03878       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03879    }
03880 }
03881 
03882 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
03883 {
03884    switch (level) {
03885    case OR2_LOG_NOTICE:
03886       ast_verbose("%s", logmessage);
03887       break;
03888    case OR2_LOG_WARNING:
03889       ast_log(LOG_WARNING, "%s", logmessage);
03890       break;
03891    case OR2_LOG_ERROR:
03892       ast_log(LOG_ERROR, "%s", logmessage);
03893       break;
03894    case OR2_LOG_STACK_TRACE:
03895    case OR2_LOG_MF_TRACE:
03896    case OR2_LOG_CAS_TRACE:
03897    case OR2_LOG_DEBUG:
03898    case OR2_LOG_EX_DEBUG:
03899       ast_debug(1, "%s", logmessage);
03900       break;
03901    default:
03902       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
03903       ast_debug(1, "%s", logmessage);
03904       break;
03905    }
03906 }
03907 
03908 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
03909 {
03910    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03911    ast_mutex_lock(&p->lock);
03912    p->remotelyblocked = 1;
03913    ast_mutex_unlock(&p->lock);
03914    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
03915 }
03916 
03917 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
03918 {
03919    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03920    ast_mutex_lock(&p->lock);
03921    p->remotelyblocked = 0;
03922    ast_mutex_unlock(&p->lock);
03923    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
03924 }
03925 
03926 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
03927    __attribute__((format (printf, 3, 0)));
03928 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
03929 {
03930 #define CONTEXT_TAG "Context - "
03931    char logmsg[256];
03932    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
03933    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
03934    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
03935    dahdi_r2_write_log(level, completemsg);
03936 #undef CONTEXT_TAG
03937 }
03938 
03939 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
03940    __attribute__((format (printf, 3, 0)));
03941 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
03942 {
03943 #define CHAN_TAG "Chan "
03944    char logmsg[256];
03945    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
03946    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
03947    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
03948    dahdi_r2_write_log(level, completemsg);
03949 }
03950 
03951 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
03952 {
03953    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03954    /* if 'immediate' is set, let's stop requesting DNIS */
03955    if (p->immediate) {
03956       return 0;
03957    }
03958    p->exten[p->mfcr2_dnis_index] = digit;
03959    p->rdnis[p->mfcr2_dnis_index] = digit;
03960    p->mfcr2_dnis_index++;
03961    p->exten[p->mfcr2_dnis_index] = 0;
03962    p->rdnis[p->mfcr2_dnis_index] = 0;
03963    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
03964    if ((p->mfcr2_dnis_matched ||
03965        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
03966        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03967       return 0;
03968    }
03969    /* otherwise keep going */
03970    return 1;
03971 }
03972 
03973 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
03974 {
03975    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03976    p->cid_num[p->mfcr2_ani_index] = digit;
03977    p->cid_name[p->mfcr2_ani_index] = digit;
03978    p->mfcr2_ani_index++;
03979    p->cid_num[p->mfcr2_ani_index] = 0;
03980    p->cid_name[p->mfcr2_ani_index] = 0;
03981 }
03982 
03983 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
03984 {
03985    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
03986 }
03987 
03988 static openr2_event_interface_t dahdi_r2_event_iface = {
03989    .on_call_init = dahdi_r2_on_call_init,
03990    .on_call_offered = dahdi_r2_on_call_offered,
03991    .on_call_accepted = dahdi_r2_on_call_accepted,
03992    .on_call_answered = dahdi_r2_on_call_answered,
03993    .on_call_disconnect = dahdi_r2_on_call_disconnect,
03994    .on_call_end = dahdi_r2_on_call_end,
03995    .on_call_read = dahdi_r2_on_call_read,
03996    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
03997    .on_os_error = dahdi_r2_on_os_error,
03998    .on_protocol_error = dahdi_r2_on_protocol_error,
03999    .on_line_blocked = dahdi_r2_on_line_blocked,
04000    .on_line_idle = dahdi_r2_on_line_idle,
04001    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04002    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04003    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04004    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04005    /* so far we do nothing with billing pulses */
04006    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04007 };
04008 
04009 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04010 {
04011    return AST_ALAW(sample);
04012 }
04013 
04014 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04015 {
04016    return AST_LIN2A(sample);
04017 }
04018 
04019 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04020    dahdi_r2_alaw_to_linear,
04021    dahdi_r2_linear_to_alaw
04022 };
04023 
04024 #endif /* HAVE_OPENR2 */
04025 
04026 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04027 {
04028    int tchan;
04029    int tinthreeway;
04030    struct ast_channel *towner;
04031 
04032    ast_debug(1, "Swapping %d and %d\n", a, b);
04033 
04034    tchan = p->subs[a].chan;
04035    towner = p->subs[a].owner;
04036    tinthreeway = p->subs[a].inthreeway;
04037 
04038    p->subs[a].chan = p->subs[b].chan;
04039    p->subs[a].owner = p->subs[b].owner;
04040    p->subs[a].inthreeway = p->subs[b].inthreeway;
04041 
04042    p->subs[b].chan = tchan;
04043    p->subs[b].owner = towner;
04044    p->subs[b].inthreeway = tinthreeway;
04045 
04046    if (p->subs[a].owner)
04047       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04048    if (p->subs[b].owner)
04049       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04050    wakeup_sub(p, a);
04051    wakeup_sub(p, b);
04052 }
04053 
04054 static int dahdi_open(char *fn)
04055 {
04056    int fd;
04057    int isnum;
04058    int chan = 0;
04059    int bs;
04060    int x;
04061    isnum = 1;
04062    for (x = 0; x < strlen(fn); x++) {
04063       if (!isdigit(fn[x])) {
04064          isnum = 0;
04065          break;
04066       }
04067    }
04068    if (isnum) {
04069       chan = atoi(fn);
04070       if (chan < 1) {
04071          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04072          return -1;
04073       }
04074       fn = "/dev/dahdi/channel";
04075    }
04076    fd = open(fn, O_RDWR | O_NONBLOCK);
04077    if (fd < 0) {
04078       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04079       return -1;
04080    }
04081    if (chan) {
04082       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04083          x = errno;
04084          close(fd);
04085          errno = x;
04086          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04087          return -1;
04088       }
04089    }
04090    bs = READ_SIZE;
04091    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04092       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04093       x = errno;
04094       close(fd);
04095       errno = x;
04096       return -1;
04097    }
04098    return fd;
04099 }
04100 
04101 static void dahdi_close(int fd)
04102 {
04103    if (fd > 0)
04104       close(fd);
04105 }
04106 
04107 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04108 {
04109    dahdi_close(chan_pvt->subs[sub_num].dfd);
04110    chan_pvt->subs[sub_num].dfd = -1;
04111 }
04112 
04113 #if defined(HAVE_PRI)
04114 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04115 {
04116    dahdi_close(pri->pri.fds[fd_num]);
04117    pri->pri.fds[fd_num] = -1;
04118 }
04119 #endif   /* defined(HAVE_PRI) */
04120 
04121 #if defined(HAVE_SS7)
04122 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04123 {
04124    dahdi_close(ss7->ss7.fds[fd_num]);
04125    ss7->ss7.fds[fd_num] = -1;
04126 }
04127 #endif   /* defined(HAVE_SS7) */
04128 
04129 static int dahdi_setlinear(int dfd, int linear)
04130 {
04131    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04132 }
04133 
04134 
04135 static int alloc_sub(struct dahdi_pvt *p, int x)
04136 {
04137    struct dahdi_bufferinfo bi;
04138    int res;
04139    if (p->subs[x].dfd >= 0) {
04140       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04141       return -1;
04142    }
04143 
04144    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04145    if (p->subs[x].dfd <= -1) {
04146       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04147       return -1;
04148    }
04149 
04150    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04151    if (!res) {
04152       bi.txbufpolicy = p->buf_policy;
04153       bi.rxbufpolicy = p->buf_policy;
04154       bi.numbufs = p->buf_no;
04155       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04156       if (res < 0) {
04157          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04158       }
04159    } else
04160       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04161 
04162    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04163       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04164       dahdi_close_sub(p, x);
04165       p->subs[x].dfd = -1;
04166       return -1;
04167    }
04168    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04169    return 0;
04170 }
04171 
04172 static int unalloc_sub(struct dahdi_pvt *p, int x)
04173 {
04174    if (!x) {
04175       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04176       return -1;
04177    }
04178    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04179    dahdi_close_sub(p, x);
04180    p->subs[x].linear = 0;
04181    p->subs[x].chan = 0;
04182    p->subs[x].owner = NULL;
04183    p->subs[x].inthreeway = 0;
04184    p->polarity = POLARITY_IDLE;
04185    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04186    return 0;
04187 }
04188 
04189 static int digit_to_dtmfindex(char digit)
04190 {
04191    if (isdigit(digit))
04192       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04193    else if (digit >= 'A' && digit <= 'D')
04194       return DAHDI_TONE_DTMF_A + (digit - 'A');
04195    else if (digit >= 'a' && digit <= 'd')
04196       return DAHDI_TONE_DTMF_A + (digit - 'a');
04197    else if (digit == '*')
04198       return DAHDI_TONE_DTMF_s;
04199    else if (digit == '#')
04200       return DAHDI_TONE_DTMF_p;
04201    else
04202       return -1;
04203 }
04204 
04205 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04206 {
04207    struct dahdi_pvt *pvt;
04208    int idx;
04209    int dtmf = -1;
04210    int res;
04211 
04212    pvt = ast_channel_tech_pvt(chan);
04213 
04214    ast_mutex_lock(&pvt->lock);
04215 
04216    idx = dahdi_get_index(chan, pvt, 0);
04217 
04218    if ((idx != SUB_REAL) || !pvt->owner)
04219       goto out;
04220 
04221 #ifdef HAVE_PRI
04222    switch (pvt->sig) {
04223    case SIG_PRI_LIB_HANDLE_CASES:
04224       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04225       if (!res)
04226          goto out;
04227       break;
04228    default:
04229       break;
04230    }
04231 #endif
04232    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04233       goto out;
04234 
04235    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04236       char dial_str[] = { 'T', digit, '\0' };
04237 
04238       res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
04239       if (!res) {
04240          pvt->dialing = 1;
04241       }
04242    } else {
04243       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04244          ast_channel_name(chan), digit);
04245       pvt->dialing = 1;
04246       pvt->begindigit = digit;
04247    }
04248 
04249 out:
04250    ast_mutex_unlock(&pvt->lock);
04251 
04252    return 0;
04253 }
04254 
04255 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04256 {
04257    struct dahdi_pvt *pvt;
04258    int res = 0;
04259    int idx;
04260    int x;
04261 
04262    pvt = ast_channel_tech_pvt(chan);
04263 
04264    ast_mutex_lock(&pvt->lock);
04265 
04266    idx = dahdi_get_index(chan, pvt, 0);
04267 
04268    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04269       goto out;
04270 
04271 #ifdef HAVE_PRI
04272    /* This means that the digit was already sent via PRI signalling */
04273    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04274       goto out;
04275    }
04276 #endif
04277 
04278    if (pvt->begindigit) {
04279       x = -1;
04280       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04281          ast_channel_name(chan), digit);
04282       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04283       pvt->dialing = 0;
04284       pvt->begindigit = 0;
04285    }
04286 
04287 out:
04288    ast_mutex_unlock(&pvt->lock);
04289 
04290    return res;
04291 }
04292 
04293 static const char * const events[] = {
04294    "No event",
04295    "On hook",
04296    "Ring/Answered",
04297    "Wink/Flash",
04298    "Alarm",
04299    "No more alarm",
04300    "HDLC Abort",
04301    "HDLC Overrun",
04302    "HDLC Bad FCS",
04303    "Dial Complete",
04304    "Ringer On",
04305    "Ringer Off",
04306    "Hook Transition Complete",
04307    "Bits Changed",
04308    "Pulse Start",
04309    "Timer Expired",
04310    "Timer Ping",
04311    "Polarity Reversal",
04312    "Ring Begin",
04313 };
04314 
04315 static struct {
04316    int alarm;
04317    char *name;
04318 } alarms[] = {
04319    { DAHDI_ALARM_RED, "Red Alarm" },
04320    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04321    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04322    { DAHDI_ALARM_RECOVER, "Recovering" },
04323    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04324    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04325    { DAHDI_ALARM_NONE, "None" },
04326 };
04327 
04328 static char *alarm2str(int alm)
04329 {
04330    int x;
04331    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04332       if (alarms[x].alarm & alm)
04333          return alarms[x].name;
04334    }
04335    return alm ? "Unknown Alarm" : "No Alarm";
04336 }
04337 
04338 static const char *event2str(int event)
04339 {
04340    static char buf[256];
04341    if ((event < (ARRAY_LEN(events))) && (event > -1))
04342       return events[event];
04343    sprintf(buf, "Event %d", event); /* safe */
04344    return buf;
04345 }
04346 
04347 static char *dahdi_sig2str(int sig)
04348 {
04349    static char buf[256];
04350    switch (sig) {
04351    case SIG_EM:
04352       return "E & M Immediate";
04353    case SIG_EMWINK:
04354       return "E & M Wink";
04355    case SIG_EM_E1:
04356       return "E & M E1";
04357    case SIG_FEATD:
04358       return "Feature Group D (DTMF)";
04359    case SIG_FEATDMF:
04360       return "Feature Group D (MF)";
04361    case SIG_FEATDMF_TA:
04362       return "Feature Groud D (MF) Tandem Access";
04363    case SIG_FEATB:
04364       return "Feature Group B (MF)";
04365    case SIG_E911:
04366       return "E911 (MF)";
04367    case SIG_FGC_CAMA:
04368       return "FGC/CAMA (Dialpulse)";
04369    case SIG_FGC_CAMAMF:
04370       return "FGC/CAMA (MF)";
04371    case SIG_FXSLS:
04372       return "FXS Loopstart";
04373    case SIG_FXSGS:
04374       return "FXS Groundstart";
04375    case SIG_FXSKS:
04376       return "FXS Kewlstart";
04377    case SIG_FXOLS:
04378       return "FXO Loopstart";
04379    case SIG_FXOGS:
04380       return "FXO Groundstart";
04381    case SIG_FXOKS:
04382       return "FXO Kewlstart";
04383    case SIG_PRI:
04384       return "ISDN PRI";
04385    case SIG_BRI:
04386       return "ISDN BRI Point to Point";
04387    case SIG_BRI_PTMP:
04388       return "ISDN BRI Point to MultiPoint";
04389    case SIG_SS7:
04390       return "SS7";
04391    case SIG_MFCR2:
04392       return "MFC/R2";
04393    case SIG_SF:
04394       return "SF (Tone) Immediate";
04395    case SIG_SFWINK:
04396       return "SF (Tone) Wink";
04397    case SIG_SF_FEATD:
04398       return "SF (Tone) with Feature Group D (DTMF)";
04399    case SIG_SF_FEATDMF:
04400       return "SF (Tone) with Feature Group D (MF)";
04401    case SIG_SF_FEATB:
04402       return "SF (Tone) with Feature Group B (MF)";
04403    case 0:
04404       return "Pseudo";
04405    default:
04406       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04407       return buf;
04408    }
04409 }
04410 
04411 #define sig2str dahdi_sig2str
04412 
04413 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04414 {
04415    /* If the conference already exists, and we're already in it
04416       don't bother doing anything */
04417    struct dahdi_confinfo zi;
04418 
04419    memset(&zi, 0, sizeof(zi));
04420    zi.chan = 0;
04421 
04422    if (slavechannel > 0) {
04423       /* If we have only one slave, do a digital mon */
04424       zi.confmode = DAHDI_CONF_DIGITALMON;
04425       zi.confno = slavechannel;
04426    } else {
04427       if (!idx) {
04428          /* Real-side and pseudo-side both participate in conference */
04429          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04430             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04431       } else
04432          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04433       zi.confno = p->confno;
04434    }
04435    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04436       return 0;
04437    if (c->dfd < 0)
04438       return 0;
04439    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04440       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04441       return -1;
04442    }
04443    if (slavechannel < 1) {
04444       p->confno = zi.confno;
04445    }
04446    c->curconf = zi;
04447    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04448    return 0;
04449 }
04450 
04451 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04452 {
04453    /* If they're listening to our channel, they're ours */
04454    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04455       return 1;
04456    /* If they're a talker on our (allocated) conference, they're ours */
04457    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04458       return 1;
04459    return 0;
04460 }
04461 
04462 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04463 {
04464    struct dahdi_confinfo zi;
04465    if (/* Can't delete if there's no dfd */
04466       (c->dfd < 0) ||
04467       /* Don't delete from the conference if it's not our conference */
04468       !isourconf(p, c)
04469       /* Don't delete if we don't think it's conferenced at all (implied) */
04470       ) return 0;
04471    memset(&zi, 0, sizeof(zi));
04472    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04473       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04474       return -1;
04475    }
04476    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04477    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04478    return 0;
04479 }
04480 
04481 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04482 {
04483    int x;
04484    int useslavenative;
04485    struct dahdi_pvt *slave = NULL;
04486    /* Start out optimistic */
04487    useslavenative = 1;
04488    /* Update conference state in a stateless fashion */
04489    for (x = 0; x < 3; x++) {
04490       /* Any three-way calling makes slave native mode *definitely* out
04491          of the question */
04492       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04493          useslavenative = 0;
04494    }
04495    /* If we don't have any 3-way calls, check to see if we have
04496       precisely one slave */
04497    if (useslavenative) {
04498       for (x = 0; x < MAX_SLAVES; x++) {
04499          if (p->slaves[x]) {
04500             if (slave) {
04501                /* Whoops already have a slave!  No
04502                   slave native and stop right away */
04503                slave = NULL;
04504                useslavenative = 0;
04505                break;
04506             } else {
04507                /* We have one slave so far */
04508                slave = p->slaves[x];
04509             }
04510          }
04511       }
04512    }
04513    /* If no slave, slave native definitely out */
04514    if (!slave)
04515       useslavenative = 0;
04516    else if (slave->law != p->law) {
04517       useslavenative = 0;
04518       slave = NULL;
04519    }
04520    if (out)
04521       *out = slave;
04522    return useslavenative;
04523 }
04524 
04525 static int reset_conf(struct dahdi_pvt *p)
04526 {
04527    p->confno = -1;
04528    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04529    if (p->subs[SUB_REAL].dfd > -1) {
04530       struct dahdi_confinfo zi;
04531 
04532       memset(&zi, 0, sizeof(zi));
04533       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04534          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04535    }
04536    return 0;
04537 }
04538 
04539 void dahdi_conf_update(struct dahdi_pvt *p)
04540 {
04541    int needconf = 0;
04542    int x;
04543    int useslavenative;
04544    struct dahdi_pvt *slave = NULL;
04545 
04546    useslavenative = isslavenative(p, &slave);
04547    /* Start with the obvious, general stuff */
04548    for (x = 0; x < 3; x++) {
04549       /* Look for three way calls */
04550       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04551          conf_add(p, &p->subs[x], x, 0);
04552          needconf++;
04553       } else {
04554          conf_del(p, &p->subs[x], x);
04555       }
04556    }
04557    /* If we have a slave, add him to our conference now. or DAX
04558       if this is slave native */
04559    for (x = 0; x < MAX_SLAVES; x++) {
04560       if (p->slaves[x]) {
04561          if (useslavenative)
04562             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04563          else {
04564             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04565             needconf++;
04566          }
04567       }
04568    }
04569    /* If we're supposed to be in there, do so now */
04570    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04571       if (useslavenative)
04572          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04573       else {
04574          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04575          needconf++;
04576       }
04577    }
04578    /* If we have a master, add ourselves to his conference */
04579    if (p->master) {
04580       if (isslavenative(p->master, NULL)) {
04581          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04582       } else {
04583          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04584       }
04585    }
04586    if (!needconf) {
04587       /* Nobody is left (or should be left) in our conference.
04588          Kill it. */
04589       p->confno = -1;
04590    }
04591    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04592 }
04593 
04594 void dahdi_ec_enable(struct dahdi_pvt *p)
04595 {
04596    int res;
04597    if (!p)
04598       return;
04599    if (p->echocanon) {
04600       ast_debug(1, "Echo cancellation already on\n");
04601       return;
04602    }
04603    if (p->digital) {
04604       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04605       return;
04606    }
04607    if (p->echocancel.head.tap_length) {
04608 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04609       switch (p->sig) {
04610 #if defined(HAVE_PRI)
04611       case SIG_PRI_LIB_HANDLE_CASES:
04612          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04613             /*
04614              * PRI nobch pseudo channel.  Does not need ec anyway.
04615              * Does not handle ioctl(DAHDI_AUDIOMODE)
04616              */
04617             return;
04618          }
04619          /* Fall through */
04620 #endif   /* defined(HAVE_PRI) */
04621 #if defined(HAVE_SS7)
04622       case SIG_SS7:
04623 #endif   /* defined(HAVE_SS7) */
04624          {
04625             int x = 1;
04626 
04627             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04628             if (res)
04629                ast_log(LOG_WARNING,
04630                   "Unable to enable audio mode on channel %d (%s)\n",
04631                   p->channel, strerror(errno));
04632          }
04633          break;
04634       default:
04635          break;
04636       }
04637 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04638       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04639       if (res) {
04640          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04641       } else {
04642          p->echocanon = 1;
04643          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04644       }
04645    } else
04646       ast_debug(1, "No echo cancellation requested\n");
04647 }
04648 
04649 static void dahdi_train_ec(struct dahdi_pvt *p)
04650 {
04651    int x;
04652    int res;
04653 
04654    if (p && p->echocanon && p->echotraining) {
04655       x = p->echotraining;
04656       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04657       if (res)
04658          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04659       else
04660          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04661    } else {
04662       ast_debug(1, "No echo training requested\n");
04663    }
04664 }
04665 
04666 void dahdi_ec_disable(struct dahdi_pvt *p)
04667 {
04668    int res;
04669 
04670    if (p->echocanon) {
04671       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04672 
04673       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04674 
04675       if (res)
04676          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04677       else
04678          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04679    }
04680 
04681    p->echocanon = 0;
04682 }
04683 
04684 static int set_hwgain(int fd, float gain, int tx_direction)
04685 {
04686    struct dahdi_hwgain hwgain;
04687 
04688    hwgain.newgain = gain * 10.0;
04689    hwgain.tx = tx_direction;
04690    return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
04691 }
04692 
04693 /* perform a dynamic range compression transform on the given sample */
04694 static int drc_sample(int sample, float drc)
04695 {
04696    float neg;
04697    float shallow, steep;
04698    float max = SHRT_MAX;
04699 
04700    neg = (sample < 0 ? -1 : 1);
04701    steep = drc*sample;
04702    shallow = neg*(max-max/drc)+(float)sample/drc;
04703    if (abs(steep) < abs(shallow)) {
04704       sample = steep;
04705    }
04706    else {
04707       sample = shallow;
04708    }
04709 
04710    return sample;
04711 }
04712 
04713 
04714 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04715 {
04716    int j;
04717    int k;
04718 
04719    float linear_gain = pow(10.0, gain / 20.0);
04720 
04721    switch (law) {
04722    case DAHDI_LAW_ALAW:
04723       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04724          if (gain || drc) {
04725             k = AST_ALAW(j);
04726             if (drc) {
04727                k = drc_sample(k, drc);
04728             }
04729             k = (float)k * linear_gain;
04730             if (k > 32767) {
04731                k = 32767;
04732             } else if (k < -32768) {
04733                k = -32768;
04734             }
04735             g->txgain[j] = AST_LIN2A(k);
04736          } else {
04737             g->txgain[j] = j;
04738          }
04739       }
04740       break;
04741    case DAHDI_LAW_MULAW:
04742       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04743          if (gain || drc) {
04744             k = AST_MULAW(j);
04745             if (drc) {
04746                k = drc_sample(k, drc);
04747             }
04748             k = (float)k * linear_gain;
04749             if (k > 32767) {
04750                k = 32767;
04751             } else if (k < -32768) {
04752                k = -32768;
04753             }
04754             g->txgain[j] = AST_LIN2MU(k);
04755 
04756          } else {
04757             g->txgain[j] = j;
04758          }
04759       }
04760       break;
04761    }
04762 }
04763 
04764 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04765 {
04766    int j;
04767    int k;
04768    float linear_gain = pow(10.0, gain / 20.0);
04769 
04770    switch (law) {
04771    case DAHDI_LAW_ALAW:
04772       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04773          if (gain || drc) {
04774             k = AST_ALAW(j);
04775             if (drc) {
04776                k = drc_sample(k, drc);
04777             }
04778             k = (float)k * linear_gain;
04779             if (k > 32767) {
04780                k = 32767;
04781             } else if (k < -32768) {
04782                k = -32768;
04783             }
04784             g->rxgain[j] = AST_LIN2A(k);
04785          } else {
04786             g->rxgain[j] = j;
04787          }
04788       }
04789       break;
04790    case DAHDI_LAW_MULAW:
04791       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04792          if (gain || drc) {
04793             k = AST_MULAW(j);
04794             if (drc) {
04795                k = drc_sample(k, drc);
04796             }
04797             k = (float)k * linear_gain;
04798             if (k > 32767) {
04799                k = 32767;
04800             } else if (k < -32768) {
04801                k = -32768;
04802             }
04803             g->rxgain[j] = AST_LIN2MU(k);
04804          } else {
04805             g->rxgain[j] = j;
04806          }
04807       }
04808       break;
04809    }
04810 }
04811 
04812 static int set_actual_txgain(int fd, float gain, float drc, int law)
04813 {
04814    struct dahdi_gains g;
04815    int res;
04816 
04817    memset(&g, 0, sizeof(g));
04818    res = ioctl(fd, DAHDI_GETGAINS, &g);
04819    if (res) {
04820       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04821       return res;
04822    }
04823 
04824    fill_txgain(&g, gain, drc, law);
04825 
04826    return ioctl(fd, DAHDI_SETGAINS, &g);
04827 }
04828 
04829 static int set_actual_rxgain(int fd, float gain, float drc, int law)
04830 {
04831    struct dahdi_gains g;
04832    int res;
04833 
04834    memset(&g, 0, sizeof(g));
04835    res = ioctl(fd, DAHDI_GETGAINS, &g);
04836    if (res) {
04837       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04838       return res;
04839    }
04840 
04841    fill_rxgain(&g, gain, drc, law);
04842 
04843    return ioctl(fd, DAHDI_SETGAINS, &g);
04844 }
04845 
04846 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
04847 {
04848    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04849 }
04850 
04851 static int bump_gains(struct dahdi_pvt *p)
04852 {
04853    int res;
04854 
04855    /* Bump receive gain by value stored in cid_rxgain */
04856    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04857    if (res) {
04858       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04859       return -1;
04860    }
04861 
04862    return 0;
04863 }
04864 
04865 static int restore_gains(struct dahdi_pvt *p)
04866 {
04867    int res;
04868 
04869    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04870    if (res) {
04871       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
04872       return -1;
04873    }
04874 
04875    return 0;
04876 }
04877 
04878 static inline int dahdi_set_hook(int fd, int hs)
04879 {
04880    int x, res;
04881 
04882    x = hs;
04883    res = ioctl(fd, DAHDI_HOOK, &x);
04884 
04885    if (res < 0) {
04886       if (errno == EINPROGRESS)
04887          return 0;
04888       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
04889       /* will expectedly fail if phone is off hook during operation, such as during a restart */
04890    }
04891 
04892    return res;
04893 }
04894 
04895 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
04896 {
04897    int x, res;
04898 
04899    x = muted;
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          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
04906          break;
04907       }
04908       /* Fall through */
04909 #endif   /* defined(HAVE_PRI) */
04910 #if defined(HAVE_SS7)
04911    case SIG_SS7:
04912 #endif   /* defined(HAVE_SS7) */
04913       {
04914          int y = 1;
04915 
04916          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
04917          if (res)
04918             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
04919                p->channel, strerror(errno));
04920       }
04921       break;
04922    default:
04923       break;
04924    }
04925 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04926    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
04927    if (res < 0)
04928       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
04929    return res;
04930 }
04931 
04932 static int save_conference(struct dahdi_pvt *p)
04933 {
04934    struct dahdi_confinfo c;
04935    int res;
04936    if (p->saveconf.confmode) {
04937       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
04938       return -1;
04939    }
04940    p->saveconf.chan = 0;
04941    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
04942    if (res) {
04943       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
04944       p->saveconf.confmode = 0;
04945       return -1;
04946    }
04947    memset(&c, 0, sizeof(c));
04948    c.confmode = DAHDI_CONF_NORMAL;
04949    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
04950    if (res) {
04951       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
04952       return -1;
04953    }
04954    ast_debug(1, "Disabled conferencing\n");
04955    return 0;
04956 }
04957 
04958 static int restore_conference(struct dahdi_pvt *p)
04959 {
04960    int res;
04961    if (p->saveconf.confmode) {
04962       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
04963       p->saveconf.confmode = 0;
04964       if (res) {
04965          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
04966          return -1;
04967       }
04968       ast_debug(1, "Restored conferencing\n");
04969    }
04970    return 0;
04971 }
04972 
04973 static int send_cwcidspill(struct dahdi_pvt *p)
04974 {
04975    p->callwaitcas = 0;
04976    p->cidcwexpire = 0;
04977    p->cid_suppress_expire = 0;
04978    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
04979       return -1;
04980    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
04981    /* Make sure we account for the end */
04982    p->cidlen += READ_SIZE * 4;
04983    p->cidpos = 0;
04984    send_callerid(p);
04985    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
04986    return 0;
04987 }
04988 
04989 static int has_voicemail(struct dahdi_pvt *p)
04990 {
04991    int new_msgs;
04992    RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
04993 
04994    mwi_message = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), p->mailbox);
04995    if (mwi_message) {
04996       struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
04997       new_msgs = mwi_state->new_msgs;
04998    } else {
04999       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05000    }
05001 
05002    return new_msgs;
05003 }
05004 
05005 
05006 
05007 static int send_callerid(struct dahdi_pvt *p)
05008 {
05009    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05010    int res;
05011    /* Take out of linear mode if necessary */
05012    if (p->subs[SUB_REAL].linear) {
05013       p->subs[SUB_REAL].linear = 0;
05014       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05015    }
05016    while (p->cidpos < p->cidlen) {
05017       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05018       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05019       if (res < 0) {
05020          if (errno == EAGAIN)
05021             return 0;
05022          else {
05023             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05024             return -1;
05025          }
05026       }
05027       if (!res)
05028          return 0;
05029       p->cidpos += res;
05030    }
05031    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05032    ast_free(p->cidspill);
05033    p->cidspill = NULL;
05034    if (p->callwaitcas) {
05035       /* Wait for CID/CW to expire */
05036       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05037       p->cid_suppress_expire = p->cidcwexpire;
05038    } else
05039       restore_conference(p);
05040    return 0;
05041 }
05042 
05043 static int dahdi_callwait(struct ast_channel *ast)
05044 {
05045    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05046 
05047    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05048    if (p->cidspill) {
05049       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05050       ast_free(p->cidspill);
05051    }
05052 
05053    /*
05054     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05055     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05056     */
05057    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05058       return -1;
05059    save_conference(p);
05060    /* Silence */
05061    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05062    if (!p->callwaitrings && p->callwaitingcallerid) {
05063       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05064       p->callwaitcas = 1;
05065       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05066    } else {
05067       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05068       p->callwaitcas = 0;
05069       p->cidlen = 2400 + READ_SIZE * 4;
05070    }
05071    p->cidpos = 0;
05072    send_callerid(p);
05073 
05074    return 0;
05075 }
05076 
05077 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05078 {
05079    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05080    int x, res, mysig;
05081    char *dest;
05082    AST_DECLARE_APP_ARGS(args,
05083       AST_APP_ARG(group);  /* channel/group token */
05084       AST_APP_ARG(ext); /* extension token */
05085       //AST_APP_ARG(opts); /* options token */
05086       AST_APP_ARG(other);  /* Any remining unused arguments */
05087    );
05088 
05089    ast_mutex_lock(&p->lock);
05090    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05091 
05092    /* Split the dialstring */
05093    dest = ast_strdupa(rdest);
05094    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05095    if (!args.ext) {
05096       args.ext = "";
05097    }
05098 
05099 #if defined(HAVE_PRI)
05100    if (dahdi_sig_pri_lib_handles(p->sig)) {
05101       char *subaddr;
05102 
05103       sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05104 
05105       /* Remove any subaddress for uniformity with incoming calls. */
05106       subaddr = strchr(p->exten, ':');
05107       if (subaddr) {
05108          *subaddr = '\0';
05109       }
05110    } else
05111 #endif   /* defined(HAVE_PRI) */
05112    {
05113       ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05114    }
05115 
05116    if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05117       p->subs[SUB_REAL].needbusy = 1;
05118       ast_mutex_unlock(&p->lock);
05119       return 0;
05120    }
05121    if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05122       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05123       ast_mutex_unlock(&p->lock);
05124       return -1;
05125    }
05126    p->waitingfordt.tv_sec = 0;
05127    p->dialednone = 0;
05128    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05129    {
05130       /* Special pseudo -- automatically up */
05131       ast_setstate(ast, AST_STATE_UP);
05132       ast_mutex_unlock(&p->lock);
05133       return 0;
05134    }
05135    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05136    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05137    if (res)
05138       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05139    p->outgoing = 1;
05140 
05141    if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05142       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05143    } else {
05144       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05145    }
05146 
05147 #ifdef HAVE_PRI
05148    if (dahdi_sig_pri_lib_handles(p->sig)) {
05149       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05150          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05151       ast_mutex_unlock(&p->lock);
05152       return res;
05153    }
05154 #endif
05155 
05156 #if defined(HAVE_SS7)
05157    if (p->sig == SIG_SS7) {
05158       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05159       ast_mutex_unlock(&p->lock);
05160       return res;
05161    }
05162 #endif   /* defined(HAVE_SS7) */
05163 
05164    /* If this is analog signalling we can exit here */
05165    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05166       p->callwaitrings = 0;
05167       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05168       ast_mutex_unlock(&p->lock);
05169       return res;
05170    }
05171 
05172    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05173    switch (mysig) {
05174    case 0:
05175       /* Special pseudo -- automatically up*/
05176       ast_setstate(ast, AST_STATE_UP);
05177       break;
05178    case SIG_MFCR2:
05179       break;
05180    default:
05181       ast_debug(1, "not yet implemented\n");
05182       ast_mutex_unlock(&p->lock);
05183       return -1;
05184    }
05185 
05186 #ifdef HAVE_OPENR2
05187    if (p->mfcr2) {
05188       openr2_calling_party_category_t chancat;
05189       int callres = 0;
05190       char *c, *l;
05191 
05192       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05193       p->dialdest[0] = '\0';
05194 
05195       c = args.ext;
05196       if (!p->hidecallerid) {
05197          l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05198       } else {
05199          l = NULL;
05200       }
05201       if (strlen(c) < p->stripmsd) {
05202          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05203          ast_mutex_unlock(&p->lock);
05204          return -1;
05205       }
05206       p->dialing = 1;
05207       chancat = dahdi_r2_get_channel_category(ast);
05208       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05209       if (-1 == callres) {
05210          ast_mutex_unlock(&p->lock);
05211          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05212          return -1;
05213       }
05214       p->mfcr2_call_accepted = 0;
05215       p->mfcr2_progress_sent = 0;
05216       ast_setstate(ast, AST_STATE_DIALING);
05217    }
05218 #endif /* HAVE_OPENR2 */
05219    ast_mutex_unlock(&p->lock);
05220    return 0;
05221 }
05222 
05223 /*!
05224  * \internal
05225  * \brief Insert the given chan_dahdi interface structure into the interface list.
05226  * \since 1.8
05227  *
05228  * \param pvt chan_dahdi private interface structure to insert.
05229  *
05230  * \details
05231  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05232  * Any duplicates are inserted after the existing entries.
05233  *
05234  * \note The new interface must not already be in the list.
05235  *
05236  * \return Nothing
05237  */
05238 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05239 {
05240    struct dahdi_pvt *cur;
05241 
05242    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05243 
05244    /* Find place in middle of list for the new interface. */
05245    for (cur = iflist; cur; cur = cur->next) {
05246       if (pvt->channel < cur->channel) {
05247          /* New interface goes before the current interface. */
05248          pvt->prev = cur->prev;
05249          pvt->next = cur;
05250          if (cur->prev) {
05251             /* Insert into the middle of the list. */
05252             cur->prev->next = pvt;
05253          } else {
05254             /* Insert at head of list. */
05255             iflist = pvt;
05256          }
05257          cur->prev = pvt;
05258          return;
05259       }
05260    }
05261 
05262    /* New interface goes onto the end of the list */
05263    pvt->prev = ifend;
05264    pvt->next = NULL;
05265    if (ifend) {
05266       ifend->next = pvt;
05267    }
05268    ifend = pvt;
05269    if (!iflist) {
05270       /* List was empty */
05271       iflist = pvt;
05272    }
05273 }
05274 
05275 /*!
05276  * \internal
05277  * \brief Extract the given chan_dahdi interface structure from the interface list.
05278  * \since 1.8
05279  *
05280  * \param pvt chan_dahdi private interface structure to extract.
05281  *
05282  * \note
05283  * The given interface structure can be either in the interface list or a stand alone
05284  * structure that has not been put in the list if the next and prev pointers are NULL.
05285  *
05286  * \return Nothing
05287  */
05288 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05289 {
05290    /* Extract from the forward chain. */
05291    if (pvt->prev) {
05292       pvt->prev->next = pvt->next;
05293    } else if (iflist == pvt) {
05294       /* Node is at the head of the list. */
05295       iflist = pvt->next;
05296    }
05297 
05298    /* Extract from the reverse chain. */
05299    if (pvt->next) {
05300       pvt->next->prev = pvt->prev;
05301    } else if (ifend == pvt) {
05302       /* Node is at the end of the list. */
05303       ifend = pvt->prev;
05304    }
05305 
05306    /* Node is no longer in the list. */
05307    pvt->which_iflist = DAHDI_IFLIST_NONE;
05308    pvt->prev = NULL;
05309    pvt->next = NULL;
05310 }
05311 
05312 #if defined(HAVE_PRI)
05313 /*!
05314  * \internal
05315  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05316  * \since 1.8
05317  *
05318  * \param pri sig_pri span control structure holding no B channel list.
05319  * \param pvt chan_dahdi private interface structure to insert.
05320  *
05321  * \details
05322  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05323  * Any duplicates are inserted after the existing entries.
05324  *
05325  * \note The new interface must not already be in the list.
05326  *
05327  * \return Nothing
05328  */
05329 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05330 {
05331    struct dahdi_pvt *cur;
05332 
05333    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05334 
05335    /* Find place in middle of list for the new interface. */
05336    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05337       if (pvt->channel < cur->channel) {
05338          /* New interface goes before the current interface. */
05339          pvt->prev = cur->prev;
05340          pvt->next = cur;
05341          if (cur->prev) {
05342             /* Insert into the middle of the list. */
05343             cur->prev->next = pvt;
05344          } else {
05345             /* Insert at head of list. */
05346             pri->no_b_chan_iflist = pvt;
05347          }
05348          cur->prev = pvt;
05349          return;
05350       }
05351    }
05352 
05353    /* New interface goes onto the end of the list */
05354    pvt->prev = pri->no_b_chan_end;
05355    pvt->next = NULL;
05356    if (pri->no_b_chan_end) {
05357       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05358    }
05359    pri->no_b_chan_end = pvt;
05360    if (!pri->no_b_chan_iflist) {
05361       /* List was empty */
05362       pri->no_b_chan_iflist = pvt;
05363    }
05364 }
05365 #endif   /* defined(HAVE_PRI) */
05366 
05367 #if defined(HAVE_PRI)
05368 /*!
05369  * \internal
05370  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05371  * \since 1.8
05372  *
05373  * \param pri sig_pri span control structure holding no B channel list.
05374  * \param pvt chan_dahdi private interface structure to extract.
05375  *
05376  * \note
05377  * The given interface structure can be either in the interface list or a stand alone
05378  * structure that has not been put in the list if the next and prev pointers are NULL.
05379  *
05380  * \return Nothing
05381  */
05382 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05383 {
05384    /* Extract from the forward chain. */
05385    if (pvt->prev) {
05386       pvt->prev->next = pvt->next;
05387    } else if (pri->no_b_chan_iflist == pvt) {
05388       /* Node is at the head of the list. */
05389       pri->no_b_chan_iflist = pvt->next;
05390    }
05391 
05392    /* Extract from the reverse chain. */
05393    if (pvt->next) {
05394       pvt->next->prev = pvt->prev;
05395    } else if (pri->no_b_chan_end == pvt) {
05396       /* Node is at the end of the list. */
05397       pri->no_b_chan_end = pvt->prev;
05398    }
05399 
05400    /* Node is no longer in the list. */
05401    pvt->which_iflist = DAHDI_IFLIST_NONE;
05402    pvt->prev = NULL;
05403    pvt->next = NULL;
05404 }
05405 #endif   /* defined(HAVE_PRI) */
05406 
05407 #if defined(HAVE_PRI)
05408 /*!
05409  * \internal
05410  * \brief Unlink the channel interface from the PRI private pointer array.
05411  * \since 1.8
05412  *
05413  * \param pvt chan_dahdi private interface structure to unlink.
05414  *
05415  * \return Nothing
05416  */
05417 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05418 {
05419    unsigned idx;
05420    struct sig_pri_span *pri;
05421 
05422    pri = pvt->pri;
05423    if (!pri) {
05424       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05425       return;
05426    }
05427    ast_mutex_lock(&pri->lock);
05428    for (idx = 0; idx < pri->numchans; ++idx) {
05429       if (pri->pvts[idx] == pvt->sig_pvt) {
05430          pri->pvts[idx] = NULL;
05431          ast_mutex_unlock(&pri->lock);
05432          return;
05433       }
05434    }
05435    ast_mutex_unlock(&pri->lock);
05436 }
05437 #endif   /* defined(HAVE_PRI) */
05438 
05439 #if defined(HAVE_SS7)
05440 /*!
05441  * \internal
05442  * \brief Unlink the channel interface from the SS7 private pointer array.
05443  * \since 1.8
05444  *
05445  * \param pvt chan_dahdi private interface structure to unlink.
05446  *
05447  * \return Nothing
05448  */
05449 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05450 {
05451    unsigned idx;
05452    struct sig_ss7_linkset *ss7;
05453 
05454    ss7 = pvt->ss7;
05455    if (!ss7) {
05456       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05457       return;
05458    }
05459    ast_mutex_lock(&ss7->lock);
05460    for (idx = 0; idx < ss7->numchans; ++idx) {
05461       if (ss7->pvts[idx] == pvt->sig_pvt) {
05462          ss7->pvts[idx] = NULL;
05463          ast_mutex_unlock(&ss7->lock);
05464          return;
05465       }
05466    }
05467    ast_mutex_unlock(&ss7->lock);
05468 }
05469 #endif   /* defined(HAVE_SS7) */
05470 
05471 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05472 {
05473    if (cur->next && cur->next->span == cur->span) {
05474       return cur->next;
05475    } else if (cur->prev && cur->prev->span == cur->span) {
05476       return cur->prev;
05477    }
05478 
05479    return NULL;
05480 }
05481 
05482 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05483 {
05484    struct dahdi_pvt *p = pvt;
05485 
05486    if (p->manages_span_alarms) {
05487       struct dahdi_pvt *next = find_next_iface_in_span(p);
05488       if (next) {
05489          next->manages_span_alarms = 1;
05490       }
05491    }
05492 
05493    /* Remove channel from the list */
05494 #if defined(HAVE_PRI)
05495    dahdi_unlink_pri_pvt(p);
05496 #endif   /* defined(HAVE_PRI) */
05497 #if defined(HAVE_SS7)
05498    dahdi_unlink_ss7_pvt(p);
05499 #endif   /* defined(HAVE_SS7) */
05500    switch (pvt->which_iflist) {
05501    case DAHDI_IFLIST_NONE:
05502       break;
05503    case DAHDI_IFLIST_MAIN:
05504       dahdi_iflist_extract(p);
05505       break;
05506 #if defined(HAVE_PRI)
05507    case DAHDI_IFLIST_NO_B_CHAN:
05508       if (p->pri) {
05509          dahdi_nobch_extract(p->pri, p);
05510       }
05511       break;
05512 #endif   /* defined(HAVE_PRI) */
05513    }
05514 
05515    if (p->sig_pvt) {
05516       if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
05517          analog_delete(p->sig_pvt);
05518       }
05519       switch (p->sig) {
05520 #if defined(HAVE_PRI)
05521       case SIG_PRI_LIB_HANDLE_CASES:
05522          sig_pri_chan_delete(p->sig_pvt);
05523          break;
05524 #endif   /* defined(HAVE_PRI) */
05525 #if defined(HAVE_SS7)
05526       case SIG_SS7:
05527          sig_ss7_chan_delete(p->sig_pvt);
05528          break;
05529 #endif   /* defined(HAVE_SS7) */
05530       default:
05531          break;
05532       }
05533    }
05534    ast_free(p->cidspill);
05535    if (p->use_smdi) {
05536       ao2_cleanup(p->smdi_iface);
05537    }
05538    if (p->mwi_event_sub) {
05539       p->mwi_event_sub = stasis_unsubscribe(p->mwi_event_sub);
05540    }
05541    if (p->vars) {
05542       ast_variables_destroy(p->vars);
05543    }
05544    if (p->cc_params) {
05545       ast_cc_config_params_destroy(p->cc_params);
05546    }
05547 
05548    p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05549    p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05550 
05551    ast_mutex_destroy(&p->lock);
05552    dahdi_close_sub(p, SUB_REAL);
05553    if (p->owner) {
05554       ast_channel_tech_pvt_set(p->owner, NULL);
05555    }
05556    ast_free(p);
05557 }
05558 
05559 static void destroy_channel(struct dahdi_pvt *cur, int now)
05560 {
05561    int i;
05562 
05563    if (!now) {
05564       /* Do not destroy the channel now if it is owned by someone. */
05565       if (cur->owner) {
05566          return;
05567       }
05568       for (i = 0; i < 3; i++) {
05569          if (cur->subs[i].owner) {
05570             return;
05571          }
05572       }
05573    }
05574    destroy_dahdi_pvt(cur);
05575 }
05576 
05577 static void destroy_all_channels(void)
05578 {
05579    int chan;
05580 #if defined(HAVE_PRI)
05581    unsigned span;
05582    struct sig_pri_span *pri;
05583 #endif   /* defined(HAVE_PRI) */
05584    struct dahdi_pvt *p;
05585 
05586    while (num_restart_pending) {
05587       usleep(1);
05588    }
05589 
05590    ast_mutex_lock(&iflock);
05591    /* Destroy all the interfaces and free their memory */
05592    while (iflist) {
05593       p = iflist;
05594 
05595       chan = p->channel;
05596 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05597       {
05598          char db_chan_name[20];
05599          char db_answer[5];
05600          char state;
05601          int why = -1;
05602 
05603          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05604          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05605             sscanf(db_answer, "%1c:%30d", &state, &why);
05606          }
05607          if (!why) {
05608             /* SRVST persistence is not required */
05609             ast_db_del(db_chan_name, SRVST_DBKEY);
05610          }
05611       }
05612 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05613       /* Free associated memory */
05614       destroy_dahdi_pvt(p);
05615       ast_verb(3, "Unregistered channel %d\n", chan);
05616    }
05617    ifcount = 0;
05618    ast_mutex_unlock(&iflock);
05619 
05620 #if defined(HAVE_PRI)
05621    /* Destroy all of the no B channel interface lists */
05622    for (span = 0; span < NUM_SPANS; ++span) {
05623       if (!pris[span].dchannels[0]) {
05624          break;
05625       }
05626       pri = &pris[span].pri;
05627       ast_mutex_lock(&pri->lock);
05628       while (pri->no_b_chan_iflist) {
05629          p = pri->no_b_chan_iflist;
05630 
05631          /* Free associated memory */
05632          destroy_dahdi_pvt(p);
05633       }
05634       ast_mutex_unlock(&pri->lock);
05635    }
05636 #endif   /* defined(HAVE_PRI) */
05637 }
05638 
05639 #if defined(HAVE_PRI)
05640 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05641 
05642 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05643 {
05644    /* Data will be our digit string */
05645    struct dahdi_pvt *p;
05646 
05647    if (ast_strlen_zero(digits)) {
05648       ast_debug(1, "No digit string sent to application!\n");
05649       return -1;
05650    }
05651 
05652    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
05653 
05654    if (!p) {
05655       ast_debug(1, "Unable to find technology private\n");
05656       return -1;
05657    }
05658 
05659    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05660 
05661    return 0;
05662 }
05663 #endif   /* defined(HAVE_PRI) */
05664 
05665 #if defined(HAVE_PRI)
05666 #if defined(HAVE_PRI_PROG_W_CAUSE)
05667 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05668 
05669 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05670 {
05671    /* Data will be our digit string */
05672    struct dahdi_pvt *pvt;
05673    char *parse;
05674    int res;
05675    AST_DECLARE_APP_ARGS(args,
05676       AST_APP_ARG(destination);
05677       AST_APP_ARG(original);
05678       AST_APP_ARG(reason);
05679    );
05680 
05681    if (ast_strlen_zero(data)) {
05682       ast_debug(1, "No data sent to application!\n");
05683       return -1;
05684    }
05685    if (ast_channel_tech(chan) != &dahdi_tech) {
05686       ast_debug(1, "Only DAHDI technology accepted!\n");
05687       return -1;
05688    }
05689    pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
05690    if (!pvt) {
05691       ast_debug(1, "Unable to find technology private\n");
05692       return -1;
05693    }
05694    switch (pvt->sig) {
05695    case SIG_PRI_LIB_HANDLE_CASES:
05696       break;
05697    default:
05698       ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
05699          ast_channel_name(chan));
05700       return -1;
05701    }
05702 
05703    parse = ast_strdupa(data);
05704    AST_STANDARD_APP_ARGS(args, parse);
05705 
05706    if (ast_strlen_zero(args.destination)) {
05707       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05708       return -1;
05709    }
05710 
05711    if (ast_strlen_zero(args.original)) {
05712       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05713       args.original = NULL;
05714    }
05715 
05716    if (ast_strlen_zero(args.reason)) {
05717       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05718       args.reason = NULL;
05719    }
05720 
05721    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
05722       args.destination, args.original, args.reason);
05723    if (!res) {
05724       /*
05725        * Wait up to 5 seconds for a reply before hanging up this call
05726        * leg if the peer does not disconnect first.
05727        */
05728       ast_safe_sleep(chan, 5000);
05729    }
05730 
05731    return -1;
05732 }
05733 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05734 #endif   /* defined(HAVE_PRI) */
05735 
05736 #if defined(HAVE_OPENR2)
05737 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05738 
05739 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05740 {
05741    /* data is whether to accept with charge or no charge */
05742    openr2_call_mode_t accept_mode;
05743    int res, timeout, maxloops;
05744    struct ast_frame *f;
05745    struct dahdi_pvt *p;
05746    char *parse;
05747    AST_DECLARE_APP_ARGS(args,
05748          AST_APP_ARG(charge);
05749    );
05750 
05751    if (ast_strlen_zero(data)) {
05752       ast_debug(1, "No data sent to application!\n");
05753       return -1;
05754    }
05755 
05756    if (ast_channel_tech(chan) != &dahdi_tech) {
05757       ast_debug(1, "Only DAHDI technology accepted!\n");
05758       return -1;
05759    }
05760 
05761    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
05762    if (!p) {
05763       ast_debug(1, "Unable to find technology private!\n");
05764       return -1;
05765    }
05766 
05767    parse = ast_strdupa(data);
05768    AST_STANDARD_APP_ARGS(args, parse);
05769 
05770    if (ast_strlen_zero(args.charge)) {
05771       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05772       return -1;
05773    }
05774 
05775    ast_mutex_lock(&p->lock);
05776    if (!p->mfcr2 || !p->mfcr2call) {
05777       ast_mutex_unlock(&p->lock);
05778       ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
05779       return -1;
05780    }
05781 
05782    if (p->mfcr2_call_accepted) {
05783       ast_mutex_unlock(&p->lock);
05784       ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
05785       return 0;
05786    }
05787    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05788    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05789       ast_mutex_unlock(&p->lock);
05790       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05791       return -1;
05792    }
05793    ast_mutex_unlock(&p->lock);
05794 
05795    res = 0;
05796    timeout = 100;
05797    maxloops = 50; /* wait up to 5 seconds */
05798    /* we need to read() until the call is accepted */
05799    while (maxloops > 0) {
05800       maxloops--;
05801       if (ast_check_hangup(chan)) {
05802          break;
05803       }
05804       res = ast_waitfor(chan, timeout);
05805       if (res < 0) {
05806          ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
05807          res = -1;
05808          break;
05809       }
05810       if (res == 0) {
05811          continue;
05812       }
05813       res = 0;
05814       f = ast_read(chan);
05815       if (!f) {
05816          ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
05817          res = -1;
05818          break;
05819       }
05820       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05821          ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
05822          ast_frfree(f);
05823          res = -1;
05824          break;
05825       }
05826       ast_frfree(f);
05827       ast_mutex_lock(&p->lock);
05828       if (p->mfcr2_call_accepted) {
05829          ast_mutex_unlock(&p->lock);
05830          ast_debug(1, "Accepted MFC/R2 call!\n");
05831          break;
05832       }
05833       ast_mutex_unlock(&p->lock);
05834    }
05835    if (res == -1) {
05836       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05837    }
05838    return res;
05839 }
05840 
05841 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05842 {
05843    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05844    switch (cause) {
05845    case AST_CAUSE_USER_BUSY:
05846    case AST_CAUSE_CALL_REJECTED:
05847    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
05848       r2cause = OR2_CAUSE_BUSY_NUMBER;
05849       break;
05850 
05851    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05852    case AST_CAUSE_SWITCH_CONGESTION:
05853       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05854       break;
05855 
05856    case AST_CAUSE_UNALLOCATED:
05857       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05858       break;
05859 
05860    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05861    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05862       r2cause = OR2_CAUSE_OUT_OF_ORDER;
05863       break;
05864 
05865    case AST_CAUSE_NO_ANSWER:
05866    case AST_CAUSE_NO_USER_RESPONSE:
05867       r2cause = OR2_CAUSE_NO_ANSWER;
05868       break;
05869 
05870    default:
05871       r2cause = OR2_CAUSE_NORMAL_CLEARING;
05872       break;
05873    }
05874    ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
05875          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05876    return r2cause;
05877 }
05878 #endif
05879 
05880 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
05881 {
05882    if (p->bufferoverrideinuse) {
05883       /* faxbuffers are in use, revert them */
05884       struct dahdi_bufferinfo bi = {
05885          .txbufpolicy = p->buf_policy,
05886          .rxbufpolicy = p->buf_policy,
05887          .bufsize = p->bufsize,
05888          .numbufs = p->buf_no
05889       };
05890       int bpres;
05891 
05892       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05893          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
05894       }
05895       p->bufferoverrideinuse = 0;
05896       return bpres;
05897    }
05898 
05899    return -1;
05900 }
05901 
05902 static int dahdi_hangup(struct ast_channel *ast)
05903 {
05904    int res = 0;
05905    int idx,x;
05906    int law;
05907    /*static int restore_gains(struct dahdi_pvt *p);*/
05908    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05909    struct dahdi_params par;
05910 
05911    ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
05912    if (!ast_channel_tech_pvt(ast)) {
05913       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
05914       return 0;
05915    }
05916 
05917    ast_mutex_lock(&p->lock);
05918    p->exten[0] = '\0';
05919    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05920       dahdi_confmute(p, 0);
05921       restore_gains(p);
05922       p->ignoredtmf = 0;
05923       p->waitingfordt.tv_sec = 0;
05924 
05925       res = analog_hangup(p->sig_pvt, ast);
05926       revert_fax_buffers(p, ast);
05927 
05928       goto hangup_out;
05929    } else {
05930       p->cid_num[0] = '\0';
05931       p->cid_name[0] = '\0';
05932       p->cid_subaddr[0] = '\0';
05933    }
05934 
05935 #if defined(HAVE_PRI)
05936    if (dahdi_sig_pri_lib_handles(p->sig)) {
05937       x = 1;
05938       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
05939 
05940       dahdi_confmute(p, 0);
05941       p->muting = 0;
05942       restore_gains(p);
05943       if (p->dsp) {
05944          ast_dsp_free(p->dsp);
05945          p->dsp = NULL;
05946       }
05947       p->ignoredtmf = 0;
05948 
05949       /* Real channel, do some fixup */
05950       p->subs[SUB_REAL].owner = NULL;
05951       p->subs[SUB_REAL].needbusy = 0;
05952       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05953 
05954       p->owner = NULL;
05955       p->cid_tag[0] = '\0';
05956       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
05957       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
05958       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
05959       p->outgoing = 0;
05960       p->digital = 0;
05961       p->faxhandled = 0;
05962       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
05963 
05964       revert_fax_buffers(p, ast);
05965 
05966       p->law = p->law_default;
05967       law = p->law_default;
05968       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
05969       if (res < 0) {
05970          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
05971             p->channel, strerror(errno));
05972       }
05973 
05974       sig_pri_hangup(p->sig_pvt, ast);
05975 
05976       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05977       dahdi_ec_disable(p);
05978 
05979       x = 0;
05980       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
05981       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
05982 
05983       p->rdnis[0] = '\0';
05984       dahdi_conf_update(p);
05985       reset_conf(p);
05986 
05987       /* Restore data mode */
05988       x = 0;
05989       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
05990 
05991       if (num_restart_pending == 0) {
05992          restart_monitor();
05993       }
05994       goto hangup_out;
05995    }
05996 #endif   /* defined(HAVE_PRI) */
05997 
05998 #if defined(HAVE_SS7)
05999    if (p->sig == SIG_SS7) {
06000       x = 1;
06001       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06002 
06003       dahdi_confmute(p, 0);
06004       p->muting = 0;
06005       restore_gains(p);
06006       if (p->dsp) {
06007          ast_dsp_free(p->dsp);
06008          p->dsp = NULL;
06009       }
06010       p->ignoredtmf = 0;
06011 
06012       /* Real channel, do some fixup */
06013       p->subs[SUB_REAL].owner = NULL;
06014       p->subs[SUB_REAL].needbusy = 0;
06015       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06016 
06017       p->owner = NULL;
06018       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06019       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06020       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06021       p->outgoing = 0;
06022       p->digital = 0;
06023       p->faxhandled = 0;
06024       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06025 
06026       revert_fax_buffers(p, ast);
06027 
06028       p->law = p->law_default;
06029       law = p->law_default;
06030       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06031       if (res < 0) {
06032          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06033             p->channel, strerror(errno));
06034       }
06035 
06036       sig_ss7_hangup(p->sig_pvt, ast);
06037 
06038       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06039       dahdi_ec_disable(p);
06040 
06041       x = 0;
06042       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06043       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06044 
06045       dahdi_conf_update(p);
06046       reset_conf(p);
06047 
06048       /* Restore data mode */
06049       x = 0;
06050       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06051 
06052       if (num_restart_pending == 0) {
06053          restart_monitor();
06054       }
06055       goto hangup_out;
06056    }
06057 #endif   /* defined(HAVE_SS7) */
06058 
06059    idx = dahdi_get_index(ast, p, 1);
06060 
06061    dahdi_confmute(p, 0);
06062    p->muting = 0;
06063    restore_gains(p);
06064    if (p->origcid_num) {
06065       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06066       ast_free(p->origcid_num);
06067       p->origcid_num = NULL;
06068    }
06069    if (p->origcid_name) {
06070       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06071       ast_free(p->origcid_name);
06072       p->origcid_name = NULL;
06073    }
06074    if (p->dsp)
06075       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06076 
06077    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06078       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06079    p->ignoredtmf = 0;
06080 
06081    if (idx > -1) {
06082       /* Real channel, do some fixup */
06083       p->subs[idx].owner = NULL;
06084       p->subs[idx].needanswer = 0;
06085       p->subs[idx].needflash = 0;
06086       p->subs[idx].needringing = 0;
06087       p->subs[idx].needbusy = 0;
06088       p->subs[idx].needcongestion = 0;
06089       p->subs[idx].linear = 0;
06090       p->polarity = POLARITY_IDLE;
06091       dahdi_setlinear(p->subs[idx].dfd, 0);
06092       if (idx == SUB_REAL) {
06093          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06094             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06095             if (p->subs[SUB_CALLWAIT].inthreeway) {
06096                /* We had flipped over to answer a callwait and now it's gone */
06097                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06098                /* Move to the call-wait, but un-own us until they flip back. */
06099                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06100                unalloc_sub(p, SUB_CALLWAIT);
06101                p->owner = NULL;
06102             } else {
06103                /* The three way hung up, but we still have a call wait */
06104                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06105                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06106                unalloc_sub(p, SUB_THREEWAY);
06107                if (p->subs[SUB_REAL].inthreeway) {
06108                   /* This was part of a three way call.  Immediately make way for
06109                      another call */
06110                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06111                   p->owner = p->subs[SUB_REAL].owner;
06112                } else {
06113                   /* This call hasn't been completed yet...  Set owner to NULL */
06114                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06115                   p->owner = NULL;
06116                }
06117                p->subs[SUB_REAL].inthreeway = 0;
06118             }
06119          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06120             /* Move to the call-wait and switch back to them. */
06121             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06122             unalloc_sub(p, SUB_CALLWAIT);
06123             p->owner = p->subs[SUB_REAL].owner;
06124             if (ast_channel_state(p->owner) != AST_STATE_UP)
06125                p->subs[SUB_REAL].needanswer = 1;
06126             ast_queue_unhold(p->subs[SUB_REAL].owner);
06127          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06128             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06129             unalloc_sub(p, SUB_THREEWAY);
06130             if (p->subs[SUB_REAL].inthreeway) {
06131                /* This was part of a three way call.  Immediately make way for
06132                   another call */
06133                ast_debug(1, "Call was complete, setting owner to former third call\n");
06134                p->owner = p->subs[SUB_REAL].owner;
06135             } else {
06136                /* This call hasn't been completed yet...  Set owner to NULL */
06137                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06138                p->owner = NULL;
06139             }
06140             p->subs[SUB_REAL].inthreeway = 0;
06141          }
06142       } else if (idx == SUB_CALLWAIT) {
06143          /* Ditch the holding callwait call, and immediately make it availabe */
06144          if (p->subs[SUB_CALLWAIT].inthreeway) {
06145             /* This is actually part of a three way, placed on hold.  Place the third part
06146                on music on hold now */
06147             if (p->subs[SUB_THREEWAY].owner) {
06148                ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest);
06149             }
06150             p->subs[SUB_THREEWAY].inthreeway = 0;
06151             /* Make it the call wait now */
06152             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06153             unalloc_sub(p, SUB_THREEWAY);
06154          } else
06155             unalloc_sub(p, SUB_CALLWAIT);
06156       } else if (idx == SUB_THREEWAY) {
06157          if (p->subs[SUB_CALLWAIT].inthreeway) {
06158             /* The other party of the three way call is currently in a call-wait state.
06159                Start music on hold for them, and take the main guy out of the third call */
06160             if (p->subs[SUB_CALLWAIT].owner) {
06161                ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest);
06162             }
06163             p->subs[SUB_CALLWAIT].inthreeway = 0;
06164          }
06165          p->subs[SUB_REAL].inthreeway = 0;
06166          /* If this was part of a three way call index, let us make
06167             another three way call */
06168          unalloc_sub(p, SUB_THREEWAY);
06169       } else {
06170          /* This wasn't any sort of call, but how are we an index? */
06171          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06172       }
06173    }
06174 
06175    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06176       p->owner = NULL;
06177       p->ringt = 0;
06178       p->distinctivering = 0;
06179       p->confirmanswer = 0;
06180       p->outgoing = 0;
06181       p->digital = 0;
06182       p->faxhandled = 0;
06183       p->pulsedial = 0;
06184       if (p->dsp) {
06185          ast_dsp_free(p->dsp);
06186          p->dsp = NULL;
06187       }
06188 
06189       revert_fax_buffers(p, ast);
06190 
06191       p->law = p->law_default;
06192       law = p->law_default;
06193       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06194       if (res < 0)
06195          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06196       /* Perform low level hangup if no owner left */
06197 #ifdef HAVE_OPENR2
06198       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06199          ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06200          /* If it's an incoming call, check the mfcr2_forced_release setting */
06201          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06202             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06203          } else {
06204             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06205             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06206             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06207                                                              : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06208             dahdi_r2_disconnect_call(p, r2cause);
06209          }
06210       } else if (p->mfcr2call) {
06211          ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06212          /* since ast_request() was called but not ast_call() we have not yet dialed
06213          and the openr2 stack will not call on_call_end callback, we need to unset
06214          the mfcr2call flag and bump the monitor count so the monitor thread can take
06215          care of this channel events from now on */
06216          p->mfcr2call = 0;
06217       }
06218 #endif
06219       switch (p->sig) {
06220       case SIG_SS7:
06221       case SIG_MFCR2:
06222       case SIG_PRI_LIB_HANDLE_CASES:
06223       case 0:
06224          break;
06225       default:
06226          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06227          break;
06228       }
06229       if (res < 0) {
06230          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06231       }
06232       switch (p->sig) {
06233       case SIG_FXOGS:
06234       case SIG_FXOLS:
06235       case SIG_FXOKS:
06236          memset(&par, 0, sizeof(par));
06237          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06238          if (!res) {
06239             struct analog_pvt *analog_p = p->sig_pvt;
06240 #if 0
06241             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06242 #endif
06243             /* If they're off hook, try playing congestion */
06244             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06245                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06246             else
06247                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06248             analog_p->fxsoffhookstate = par.rxisoffhook;
06249          }
06250          break;
06251       case SIG_FXSGS:
06252       case SIG_FXSLS:
06253       case SIG_FXSKS:
06254          /* Make sure we're not made available for at least two seconds assuming
06255          we were actually used for an inbound or outbound call. */
06256          if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06257             time(&p->guardtime);
06258             p->guardtime += 2;
06259          }
06260          break;
06261       default:
06262          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06263          break;
06264       }
06265       if (p->sig)
06266          dahdi_ec_disable(p);
06267       x = 0;
06268       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06269       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06270       p->didtdd = 0;
06271       p->callwaitcas = 0;
06272       p->callwaiting = p->permcallwaiting;
06273       p->hidecallerid = p->permhidecallerid;
06274       p->waitingfordt.tv_sec = 0;
06275       p->dialing = 0;
06276       p->rdnis[0] = '\0';
06277       dahdi_conf_update(p);
06278       reset_conf(p);
06279       /* Restore data mode */
06280       switch (p->sig) {
06281       case SIG_PRI_LIB_HANDLE_CASES:
06282       case SIG_SS7:
06283          x = 0;
06284          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06285          break;
06286       default:
06287          break;
06288       }
06289       if (num_restart_pending == 0)
06290          restart_monitor();
06291    }
06292 
06293    p->callwaitingrepeat = 0;
06294    p->cidcwexpire = 0;
06295    p->cid_suppress_expire = 0;
06296    p->oprmode = 0;
06297 hangup_out:
06298    ast_channel_tech_pvt_set(ast, NULL);
06299    ast_free(p->cidspill);
06300    p->cidspill = NULL;
06301 
06302    ast_mutex_unlock(&p->lock);
06303    ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06304 
06305    ast_mutex_lock(&iflock);
06306    if (p->restartpending) {
06307       num_restart_pending--;
06308    }
06309 
06310    if (p->destroy) {
06311       destroy_channel(p, 0);
06312    }
06313    ast_mutex_unlock(&iflock);
06314 
06315    ast_module_unref(ast_module_info->self);
06316    return 0;
06317 }
06318 
06319 static int dahdi_answer(struct ast_channel *ast)
06320 {
06321    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06322    int res = 0;
06323    int idx;
06324    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06325    ast_mutex_lock(&p->lock);
06326    idx = dahdi_get_index(ast, p, 0);
06327    if (idx < 0)
06328       idx = SUB_REAL;
06329    /* nothing to do if a radio channel */
06330    if ((p->radio || (p->oprmode < 0))) {
06331       ast_mutex_unlock(&p->lock);
06332       return 0;
06333    }
06334 
06335    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06336       res = analog_answer(p->sig_pvt, ast);
06337       ast_mutex_unlock(&p->lock);
06338       return res;
06339    }
06340 
06341    switch (p->sig) {
06342 #if defined(HAVE_PRI)
06343    case SIG_PRI_LIB_HANDLE_CASES:
06344       res = sig_pri_answer(p->sig_pvt, ast);
06345       break;
06346 #endif   /* defined(HAVE_PRI) */
06347 #if defined(HAVE_SS7)
06348    case SIG_SS7:
06349       res = sig_ss7_answer(p->sig_pvt, ast);
06350       break;
06351 #endif   /* defined(HAVE_SS7) */
06352 #ifdef HAVE_OPENR2
06353    case SIG_MFCR2:
06354       if (!p->mfcr2_call_accepted) {
06355          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06356             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06357          p->mfcr2_answer_pending = 1;
06358          if (p->mfcr2_charge_calls) {
06359             ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06360             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06361          } else {
06362             ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06363             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06364          }
06365       } else {
06366          ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06367          dahdi_r2_answer(p);
06368       }
06369       break;
06370 #endif
06371    case 0:
06372       ast_mutex_unlock(&p->lock);
06373       return 0;
06374    default:
06375       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06376       res = -1;
06377       break;
06378    }
06379    ast_mutex_unlock(&p->lock);
06380    return res;
06381 }
06382 
06383 void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
06384 {
06385    int val = 0;
06386 
06387    p->ignoredtmf = 1;
06388 
06389    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06390 
06391    if (!p->hardwaredtmf && p->dsp) {
06392       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06393       ast_dsp_set_features(p->dsp, p->dsp_features);
06394    }
06395 }
06396 
06397 void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
06398 {
06399    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06400 
06401    if (p->channel == CHAN_PSEUDO)
06402       return;
06403 
06404    p->ignoredtmf = 0;
06405 
06406    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06407 
06408    if (!p->hardwaredtmf && p->dsp) {
06409       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06410       ast_dsp_set_features(p->dsp, p->dsp_features);
06411    }
06412 }
06413 
06414 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06415 {
06416    char *cp;
06417    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06418 
06419    /* all supported options require data */
06420    if (!p || !data || (*datalen < 1)) {
06421       errno = EINVAL;
06422       return -1;
06423    }
06424 
06425    switch (option) {
06426    case AST_OPTION_DIGIT_DETECT:
06427       cp = (char *) data;
06428       *cp = p->ignoredtmf ? 0 : 1;
06429       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06430       break;
06431    case AST_OPTION_FAX_DETECT:
06432       cp = (char *) data;
06433       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06434       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06435       break;
06436    case AST_OPTION_CC_AGENT_TYPE:
06437 #if defined(HAVE_PRI)
06438 #if defined(HAVE_PRI_CCSS)
06439       if (dahdi_sig_pri_lib_handles(p->sig)) {
06440          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06441          break;
06442       }
06443 #endif   /* defined(HAVE_PRI_CCSS) */
06444 #endif   /* defined(HAVE_PRI) */
06445       return -1;
06446    default:
06447       return -1;
06448    }
06449 
06450    errno = 0;
06451 
06452    return 0;
06453 }
06454 
06455 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06456 {
06457    char *cp;
06458    signed char *scp;
06459    int x;
06460    int idx;
06461    struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06462    struct oprmode *oprmode;
06463 
06464 
06465    /* all supported options require data */
06466    if (!p || !data || (datalen < 1)) {
06467       errno = EINVAL;
06468       return -1;
06469    }
06470 
06471    switch (option) {
06472    case AST_OPTION_TXGAIN:
06473       scp = (signed char *) data;
06474       idx = dahdi_get_index(chan, p, 0);
06475       if (idx < 0) {
06476          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06477          return -1;
06478       }
06479       ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06480       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06481    case AST_OPTION_RXGAIN:
06482       scp = (signed char *) data;
06483       idx = dahdi_get_index(chan, p, 0);
06484       if (idx < 0) {
06485          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06486          return -1;
06487       }
06488       ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06489       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06490    case AST_OPTION_TONE_VERIFY:
06491       if (!p->dsp)
06492          break;
06493       cp = (char *) data;
06494       switch (*cp) {
06495       case 1:
06496          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06497          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06498          break;
06499       case 2:
06500          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06501          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06502          break;
06503       default:
06504          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06505          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06506          break;
06507       }
06508       break;
06509    case AST_OPTION_TDD:
06510       /* turn on or off TDD */
06511       cp = (char *) data;
06512       p->mate = 0;
06513       if (!*cp) { /* turn it off */
06514          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06515          if (p->tdd)
06516             tdd_free(p->tdd);
06517          p->tdd = 0;
06518          break;
06519       }
06520       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06521          (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06522       dahdi_ec_disable(p);
06523       /* otherwise, turn it on */
06524       if (!p->didtdd) { /* if havent done it yet */
06525          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06526          unsigned char *buf;
06527          int size, res, fd, len;
06528          struct pollfd fds[1];
06529 
06530          buf = mybuf;
06531          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06532          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06533          len = 40000;
06534          idx = dahdi_get_index(chan, p, 0);
06535          if (idx < 0) {
06536             ast_log(LOG_WARNING, "No index in TDD?\n");
06537             return -1;
06538          }
06539          fd = p->subs[idx].dfd;
06540          while (len) {
06541             if (ast_check_hangup(chan))
06542                return -1;
06543             size = len;
06544             if (size > READ_SIZE)
06545                size = READ_SIZE;
06546             fds[0].fd = fd;
06547             fds[0].events = POLLPRI | POLLOUT;
06548             fds[0].revents = 0;
06549             res = poll(fds, 1, -1);
06550             if (!res) {
06551                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06552                continue;
06553             }
06554             /* if got exception */
06555             if (fds[0].revents & POLLPRI)
06556                return -1;
06557             if (!(fds[0].revents & POLLOUT)) {
06558                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06559                continue;
06560             }
06561             res = write(fd, buf, size);
06562             if (res != size) {
06563                if (res == -1) return -1;
06564                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06565                break;
06566             }
06567             len -= size;
06568             buf += size;
06569          }
06570          p->didtdd = 1; /* set to have done it now */
06571       }
06572       if (*cp == 2) { /* Mate mode */
06573          if (p->tdd)
06574             tdd_free(p->tdd);
06575          p->tdd = 0;
06576          p->mate = 1;
06577          break;
06578       }
06579       if (!p->tdd) { /* if we don't have one yet */
06580          p->tdd = tdd_new(); /* allocate one */
06581       }
06582       break;
06583    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06584       if (!p->dsp)
06585          break;
06586       cp = (char *) data;
06587       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06588          *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
06589       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06590       break;
06591    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06592 #if defined(HAVE_PRI)
06593       if (dahdi_sig_pri_lib_handles(p->sig)
06594          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06595          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06596          break;
06597       }
06598 #endif   /* defined(HAVE_PRI) */
06599 
06600       cp = (char *) data;
06601       if (!*cp) {
06602          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
06603          x = 0;
06604          dahdi_ec_disable(p);
06605       } else {
06606          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
06607          x = 1;
06608       }
06609       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06610          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06611       break;
06612    case AST_OPTION_OPRMODE:  /* Operator services mode */
06613       oprmode = (struct oprmode *) data;
06614       /* We don't support operator mode across technologies */
06615       if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
06616          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06617                ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
06618          errno = EINVAL;
06619          return -1;
06620       }
06621       pp = ast_channel_tech_pvt(oprmode->peer);
06622       p->oprmode = pp->oprmode = 0;
06623       /* setup peers */
06624       p->oprpeer = pp;
06625       pp->oprpeer = p;
06626       /* setup modes, if any */
06627       if (oprmode->mode)
06628       {
06629          pp->oprmode = oprmode->mode;
06630          p->oprmode = -oprmode->mode;
06631       }
06632       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06633          oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
06634       break;
06635    case AST_OPTION_ECHOCAN:
06636       cp = (char *) data;
06637       if (*cp) {
06638          ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
06639          dahdi_ec_enable(p);
06640       } else {
06641          ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
06642          dahdi_ec_disable(p);
06643       }
06644       break;
06645    case AST_OPTION_DIGIT_DETECT:
06646       cp = (char *) data;
06647       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06648       if (*cp) {
06649          dahdi_dtmf_detect_enable(p);
06650       } else {
06651          dahdi_dtmf_detect_disable(p);
06652       }
06653       break;
06654    case AST_OPTION_FAX_DETECT:
06655       cp = (char *) data;
06656       if (p->dsp) {
06657          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06658          if (*cp) {
06659             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06660          } else {
06661             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06662          }
06663          ast_dsp_set_features(p->dsp, p->dsp_features);
06664       }
06665       break;
06666    default:
06667       return -1;
06668    }
06669    errno = 0;
06670 
06671    return 0;
06672 }
06673 
06674 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06675 {
06676    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06677    int res = 0;
06678 
06679    if (!p) {
06680       /* No private structure! */
06681       *buf = '\0';
06682       return -1;
06683    }
06684 
06685    if (!strcasecmp(data, "rxgain")) {
06686       ast_mutex_lock(&p->lock);
06687       snprintf(buf, len, "%f", p->rxgain);
06688       ast_mutex_unlock(&p->lock);
06689    } else if (!strcasecmp(data, "txgain")) {
06690       ast_mutex_lock(&p->lock);
06691       snprintf(buf, len, "%f", p->txgain);
06692       ast_mutex_unlock(&p->lock);
06693    } else if (!strcasecmp(data, "dahdi_channel")) {
06694       ast_mutex_lock(&p->lock);
06695       snprintf(buf, len, "%d", p->channel);
06696       ast_mutex_unlock(&p->lock);
06697    } else if (!strcasecmp(data, "dahdi_span")) {
06698       ast_mutex_lock(&p->lock);
06699       snprintf(buf, len, "%d", p->span);
06700       ast_mutex_unlock(&p->lock);
06701    } else if (!strcasecmp(data, "dahdi_type")) {
06702       ast_mutex_lock(&p->lock);
06703       switch (p->sig) {
06704 #if defined(HAVE_OPENR2)
06705       case SIG_MFCR2:
06706          ast_copy_string(buf, "mfc/r2", len);
06707          break;
06708 #endif   /* defined(HAVE_OPENR2) */
06709 #if defined(HAVE_PRI)
06710       case SIG_PRI_LIB_HANDLE_CASES:
06711          ast_copy_string(buf, "pri", len);
06712          break;
06713 #endif   /* defined(HAVE_PRI) */
06714       case 0:
06715          ast_copy_string(buf, "pseudo", len);
06716          break;
06717 #if defined(HAVE_SS7)
06718       case SIG_SS7:
06719          ast_copy_string(buf, "ss7", len);
06720          break;
06721 #endif   /* defined(HAVE_SS7) */
06722       default:
06723          /* The only thing left is analog ports. */
06724          ast_copy_string(buf, "analog", len);
06725          break;
06726       }
06727       ast_mutex_unlock(&p->lock);
06728 #if defined(HAVE_PRI)
06729 #if defined(HAVE_PRI_REVERSE_CHARGE)
06730    } else if (!strcasecmp(data, "reversecharge")) {
06731       ast_mutex_lock(&p->lock);
06732       switch (p->sig) {
06733       case SIG_PRI_LIB_HANDLE_CASES:
06734          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06735          break;
06736       default:
06737          *buf = '\0';
06738          res = -1;
06739          break;
06740       }
06741       ast_mutex_unlock(&p->lock);
06742 #endif
06743 #if defined(HAVE_PRI_SETUP_KEYPAD)
06744    } else if (!strcasecmp(data, "keypad_digits")) {
06745       ast_mutex_lock(&p->lock);
06746       switch (p->sig) {
06747       case SIG_PRI_LIB_HANDLE_CASES:
06748          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06749             len);
06750          break;
06751       default:
06752          *buf = '\0';
06753          res = -1;
06754          break;
06755       }
06756       ast_mutex_unlock(&p->lock);
06757 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06758    } else if (!strcasecmp(data, "no_media_path")) {
06759       ast_mutex_lock(&p->lock);
06760       switch (p->sig) {
06761       case SIG_PRI_LIB_HANDLE_CASES:
06762          /*
06763           * TRUE if the call is on hold or is call waiting because
06764           * there is no media path available.
06765           */
06766          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06767          break;
06768       default:
06769          *buf = '\0';
06770          res = -1;
06771          break;
06772       }
06773       ast_mutex_unlock(&p->lock);
06774 #endif   /* defined(HAVE_PRI) */
06775    } else {
06776       *buf = '\0';
06777       res = -1;
06778    }
06779 
06780    return res;
06781 }
06782 
06783 
06784 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06785 {
06786    int res;
06787    char policy_str[21] = "";
06788 
06789    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06790       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06791       return 1;
06792    }
06793    if (*num_buffers < 0) {
06794       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06795       return -1;
06796    }
06797    if (!strcasecmp(policy_str, "full")) {
06798       *policy = DAHDI_POLICY_WHEN_FULL;
06799    } else if (!strcasecmp(policy_str, "immediate")) {
06800       *policy = DAHDI_POLICY_IMMEDIATE;
06801 #if defined(HAVE_DAHDI_HALF_FULL)
06802    } else if (!strcasecmp(policy_str, "half")) {
06803       *policy = DAHDI_POLICY_HALF_FULL;
06804 #endif
06805    } else {
06806       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06807       return -1;
06808    }
06809 
06810    return 0;
06811 }
06812 
06813 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06814 {
06815    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06816    int res = 0;
06817 
06818    if (!p) {
06819       /* No private structure! */
06820       return -1;
06821    }
06822 
06823    if (!strcasecmp(data, "buffers")) {
06824       int num_bufs, policy;
06825 
06826       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06827          struct dahdi_bufferinfo bi = {
06828             .txbufpolicy = policy,
06829             .rxbufpolicy = policy,
06830             .bufsize = p->bufsize,
06831             .numbufs = num_bufs,
06832          };
06833          int bpres;
06834 
06835          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06836             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06837          } else {
06838             p->bufferoverrideinuse = 1;
06839          }
06840       } else {
06841          res = -1;
06842       }
06843    } else if (!strcasecmp(data, "echocan_mode")) {
06844       if (!strcasecmp(value, "on")) {
06845          ast_mutex_lock(&p->lock);
06846          dahdi_ec_enable(p);
06847          ast_mutex_unlock(&p->lock);
06848       } else if (!strcasecmp(value, "off")) {
06849          ast_mutex_lock(&p->lock);
06850          dahdi_ec_disable(p);
06851          ast_mutex_unlock(&p->lock);
06852 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06853       } else if (!strcasecmp(value, "fax")) {
06854          int blah = 1;
06855 
06856          ast_mutex_lock(&p->lock);
06857          if (!p->echocanon) {
06858             dahdi_ec_enable(p);
06859          }
06860          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06861             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06862          }
06863          ast_mutex_unlock(&p->lock);
06864       } else if (!strcasecmp(value, "voice")) {
06865          int blah = 0;
06866 
06867          ast_mutex_lock(&p->lock);
06868          if (!p->echocanon) {
06869             dahdi_ec_enable(p);
06870          }
06871          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06872             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06873          }
06874          ast_mutex_unlock(&p->lock);
06875 #endif
06876       } else {
06877          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06878          res = -1;
06879       }
06880    } else {
06881       res = -1;
06882    }
06883 
06884    return res;
06885 }
06886 
06887 void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
06888 {
06889    /* Unlink a specific slave or all slaves/masters from a given master */
06890    int x;
06891    int hasslaves;
06892    if (!master)
06893       return;
06894    if (needlock) {
06895       ast_mutex_lock(&master->lock);
06896       if (slave) {
06897          while (ast_mutex_trylock(&slave->lock)) {
06898             DEADLOCK_AVOIDANCE(&master->lock);
06899          }
06900       }
06901    }
06902    hasslaves = 0;
06903    for (x = 0; x < MAX_SLAVES; x++) {
06904       if (master->slaves[x]) {
06905          if (!slave || (master->slaves[x] == slave)) {
06906             /* Take slave out of the conference */
06907             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06908             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06909             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06910             master->slaves[x]->master = NULL;
06911             master->slaves[x] = NULL;
06912          } else
06913             hasslaves = 1;
06914       }
06915       if (!hasslaves)
06916          master->inconference = 0;
06917    }
06918    if (!slave) {
06919       if (master->master) {
06920          /* Take master out of the conference */
06921          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06922          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06923          hasslaves = 0;
06924          for (x = 0; x < MAX_SLAVES; x++) {
06925             if (master->master->slaves[x] == master)
06926                master->master->slaves[x] = NULL;
06927             else if (master->master->slaves[x])
06928                hasslaves = 1;
06929          }
06930          if (!hasslaves)
06931             master->master->inconference = 0;
06932       }
06933       master->master = NULL;
06934    }
06935    dahdi_conf_update(master);
06936    if (needlock) {
06937       if (slave)
06938          ast_mutex_unlock(&slave->lock);
06939       ast_mutex_unlock(&master->lock);
06940    }
06941 }
06942 
06943 void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
06944 {
06945    int x;
06946    if (!slave || !master) {
06947       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06948       return;
06949    }
06950    for (x = 0; x < MAX_SLAVES; x++) {
06951       if (!master->slaves[x]) {
06952          master->slaves[x] = slave;
06953          break;
06954       }
06955    }
06956    if (x >= MAX_SLAVES) {
06957       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06958       master->slaves[MAX_SLAVES - 1] = slave;
06959    }
06960    if (slave->master)
06961       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06962    slave->master = master;
06963 
06964    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06965 }
06966 
06967 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
06968 {
06969    struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
06970    int x;
06971 
06972    ast_mutex_lock(&p->lock);
06973 
06974    ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
06975    if (p->owner == oldchan) {
06976       p->owner = newchan;
06977    }
06978    for (x = 0; x < 3; x++) {
06979       if (p->subs[x].owner == oldchan) {
06980          if (!x) {
06981             dahdi_master_slave_unlink(NULL, p, 0);
06982          }
06983          p->subs[x].owner = newchan;
06984       }
06985    }
06986    if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06987       analog_fixup(oldchan, newchan, p->sig_pvt);
06988 #if defined(HAVE_PRI)
06989    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
06990       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
06991 #endif   /* defined(HAVE_PRI) */
06992 #if defined(HAVE_SS7)
06993    } else if (p->sig == SIG_SS7) {
06994       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
06995 #endif   /* defined(HAVE_SS7) */
06996    }
06997    dahdi_conf_update(p);
06998 
06999    ast_mutex_unlock(&p->lock);
07000 
07001    if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07002       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07003    }
07004    return 0;
07005 }
07006 
07007 static int dahdi_ring_phone(struct dahdi_pvt *p)
07008 {
07009    int x;
07010    int res;
07011    /* Make sure our transmit state is on hook */
07012    x = 0;
07013    x = DAHDI_ONHOOK;
07014    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07015    do {
07016       x = DAHDI_RING;
07017       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07018       if (res) {
07019          switch (errno) {
07020          case EBUSY:
07021          case EINTR:
07022             /* Wait just in case */
07023             usleep(10000);
07024             continue;
07025          case EINPROGRESS:
07026             res = 0;
07027             break;
07028          default:
07029             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07030             res = 0;
07031          }
07032       }
07033    } while (res);
07034    return res;
07035 }
07036 
07037 static void *analog_ss_thread(void *data);
07038 
07039 /*!
07040  * \internal
07041  * \brief Attempt to transfer 3-way call.
07042  *
07043  * \param p DAHDI private structure.
07044  *
07045  * \note On entry these locks are held: real-call, private, 3-way call.
07046  * \note On exit these locks are held: real-call, private.
07047  *
07048  * \retval 0 on success.
07049  * \retval -1 on error.
07050  */
07051 static int attempt_transfer(struct dahdi_pvt *p)
07052 {
07053    struct ast_channel *owner_real;
07054    struct ast_channel *owner_3way;
07055    enum ast_transfer_result xfer_res;
07056    int res = 0;
07057 
07058    owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
07059    owner_3way = ast_channel_ref(p->su