Thu Oct 11 06:33:37 2012

Asterisk developer's documentation


chan_dahdi.c

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