Sun Oct 16 2011 08:41:32

Asterisk developer's documentation


chan_dahdi.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2008, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI for Pseudo TDM
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * Connects to the DAHDI telephony library as well as
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <use>res_smdi</use>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use>pri</use>
00045    <use>ss7</use>
00046    <use>openr2</use>
00047    <support_level>core</support_level>
00048  ***/
00049 
00050 #include "asterisk.h"
00051 
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 336635 $")
00053 
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064 
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068 /* Analog signaling is currently still present in chan_dahdi for use with
00069  * radio. Sig_analog does not currently handle any radio operations. If
00070  * radio only uses analog signaling, then the radio handling logic could
00071  * be placed in sig_analog and the duplicated code could be removed.
00072  */
00073 
00074 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077 
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif   /* defined(HAVE_SS7) */
00081 
00082 #ifdef HAVE_OPENR2
00083 /* put this here until sig_mfcr2 comes along */
00084 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00085 #include <openr2.h>
00086 #endif
00087 
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122 
00123 /*** DOCUMENTATION
00124    <application name="DAHDISendKeypadFacility" language="en_US">
00125       <synopsis>
00126          Send digits out of band over a PRI.
00127       </synopsis>
00128       <syntax>
00129          <parameter name="digits" required="true" />
00130       </syntax>
00131       <description>
00132          <para>This application will send the given string of digits in a Keypad
00133          Facility IE over the current channel.</para>
00134       </description>
00135    </application>
00136    <application name="DAHDISendCallreroutingFacility" language="en_US">
00137       <synopsis>
00138          Send an ISDN call rerouting/deflection facility message.
00139       </synopsis>
00140       <syntax argsep=",">
00141          <parameter name="destination" required="true">
00142             <para>Destination number.</para>
00143          </parameter>
00144          <parameter name="original">
00145             <para>Original called number.</para>
00146          </parameter>
00147          <parameter name="reason">
00148             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00149          </parameter>
00150       </syntax>
00151       <description>
00152          <para>This application will send an ISDN switch specific call
00153          rerouting/deflection facility message over the current channel.
00154          Supported switches depend upon the version of libpri in use.</para>
00155       </description>
00156    </application>
00157    <application name="DAHDIAcceptR2Call" language="en_US">
00158       <synopsis>
00159          Accept an R2 call if its not already accepted (you still need to answer it)
00160       </synopsis>
00161       <syntax>
00162          <parameter name="charge" required="true">
00163             <para>Yes or No.</para>
00164             <para>Whether you want to accept the call with charge or without charge.</para>
00165          </parameter>
00166       </syntax>
00167       <description>
00168          <para>This application will Accept the R2 call either with charge or no charge.</para>
00169       </description>
00170    </application>
00171    <manager name="DAHDITransfer" language="en_US">
00172       <synopsis>
00173          Transfer DAHDI Channel.
00174       </synopsis>
00175       <syntax>
00176          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00177          <parameter name="DAHDIChannel" required="true">
00178             <para>DAHDI channel number to transfer.</para>
00179          </parameter>
00180       </syntax>
00181       <description>
00182          <para>Simulate a flash hook event by the user connected to the channel.</para>
00183          <note><para>Valid only for analog channels.</para></note>
00184       </description>
00185    </manager>
00186    <manager name="DAHDIHangup" language="en_US">
00187       <synopsis>
00188          Hangup DAHDI Channel.
00189       </synopsis>
00190       <syntax>
00191          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00192          <parameter name="DAHDIChannel" required="true">
00193             <para>DAHDI channel number to hangup.</para>
00194          </parameter>
00195       </syntax>
00196       <description>
00197          <para>Simulate an on-hook event by the user connected to the channel.</para>
00198          <note><para>Valid only for analog channels.</para></note>
00199       </description>
00200    </manager>
00201    <manager name="DAHDIDialOffhook" language="en_US">
00202       <synopsis>
00203          Dial over DAHDI channel while offhook.
00204       </synopsis>
00205       <syntax>
00206          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00207          <parameter name="DAHDIChannel" required="true">
00208             <para>DAHDI channel number to dial digits.</para>
00209          </parameter>
00210          <parameter name="Number" required="true">
00211             <para>Digits to dial.</para>
00212          </parameter>
00213       </syntax>
00214       <description>
00215          <para>Generate DTMF control frames to the bridged peer.</para>
00216       </description>
00217    </manager>
00218    <manager name="DAHDIDNDon" language="en_US">
00219       <synopsis>
00220          Toggle DAHDI channel Do Not Disturb status ON.
00221       </synopsis>
00222       <syntax>
00223          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00224          <parameter name="DAHDIChannel" required="true">
00225             <para>DAHDI channel number to set DND on.</para>
00226          </parameter>
00227       </syntax>
00228       <description>
00229          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00230          <note><para>Feature only supported by analog channels.</para></note>
00231       </description>
00232    </manager>
00233    <manager name="DAHDIDNDoff" language="en_US">
00234       <synopsis>
00235          Toggle DAHDI channel Do Not Disturb status OFF.
00236       </synopsis>
00237       <syntax>
00238          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00239          <parameter name="DAHDIChannel" required="true">
00240             <para>DAHDI channel number to set DND off.</para>
00241          </parameter>
00242       </syntax>
00243       <description>
00244          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00245          <note><para>Feature only supported by analog channels.</para></note>
00246       </description>
00247    </manager>
00248    <manager name="DAHDIShowChannels" language="en_US">
00249       <synopsis>
00250          Show status of DAHDI channels.
00251       </synopsis>
00252       <syntax>
00253          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00254          <parameter name="DAHDIChannel">
00255             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00256          </parameter>
00257       </syntax>
00258       <description>
00259          <para>Similar to the CLI command "dahdi show channels".</para>
00260       </description>
00261    </manager>
00262    <manager name="DAHDIRestart" language="en_US">
00263       <synopsis>
00264          Fully Restart DAHDI channels (terminates calls).
00265       </synopsis>
00266       <syntax>
00267          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00268       </syntax>
00269       <description>
00270          <para>Equivalent to the CLI command "dahdi restart".</para>
00271       </description>
00272    </manager>
00273  ***/
00274 
00275 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00276 
00277 static const char * const lbostr[] = {
00278 "0 db (CSU)/0-133 feet (DSX-1)",
00279 "133-266 feet (DSX-1)",
00280 "266-399 feet (DSX-1)",
00281 "399-533 feet (DSX-1)",
00282 "533-655 feet (DSX-1)",
00283 "-7.5db (CSU)",
00284 "-15db (CSU)",
00285 "-22.5db (CSU)"
00286 };
00287 
00288 /*! Global jitterbuffer configuration - by default, jb is disabled
00289  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00290 static struct ast_jb_conf default_jbconf =
00291 {
00292    .flags = 0,
00293    .max_size = 200,
00294    .resync_threshold = 1000,
00295    .impl = "fixed",
00296    .target_extra = 40,
00297 };
00298 static struct ast_jb_conf global_jbconf;
00299 
00300 /*!
00301  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00302  * the user hangs up to reset the state machine so ring works properly.
00303  * This is used to be able to support kewlstart by putting the zhone in
00304  * groundstart mode since their forward disconnect supervision is entirely
00305  * broken even though their documentation says it isn't and their support
00306  * is entirely unwilling to provide any assistance with their channel banks
00307  * even though their web site says they support their products for life.
00308  */
00309 /* #define ZHONE_HACK */
00310 
00311 /*! \brief Typically, how many rings before we should send Caller*ID */
00312 #define DEFAULT_CIDRINGS 1
00313 
00314 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00315 
00316 
00317 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00318 #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))
00319 
00320 static const char tdesc[] = "DAHDI Telephony Driver"
00321 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00322    " w/"
00323    #if defined(HAVE_PRI)
00324       "PRI"
00325    #endif   /* defined(HAVE_PRI) */
00326    #if defined(HAVE_SS7)
00327       #if defined(HAVE_PRI)
00328       " & "
00329       #endif   /* defined(HAVE_PRI) */
00330       "SS7"
00331    #endif   /* defined(HAVE_SS7) */
00332    #if defined(HAVE_OPENR2)
00333       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00336       "MFC/R2"
00337    #endif   /* defined(HAVE_OPENR2) */
00338 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00339 ;
00340 
00341 static const char config[] = "chan_dahdi.conf";
00342 
00343 #define SIG_EM    DAHDI_SIG_EM
00344 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00345 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00346 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00347 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00348 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00349 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00350 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00351 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00352 #define SIG_FXSLS DAHDI_SIG_FXSLS
00353 #define SIG_FXSGS DAHDI_SIG_FXSGS
00354 #define SIG_FXSKS DAHDI_SIG_FXSKS
00355 #define SIG_FXOLS DAHDI_SIG_FXOLS
00356 #define SIG_FXOGS DAHDI_SIG_FXOGS
00357 #define SIG_FXOKS DAHDI_SIG_FXOKS
00358 #define SIG_PRI      DAHDI_SIG_CLEAR
00359 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00360 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00361 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00362 #define SIG_MFCR2    DAHDI_SIG_CAS
00363 #define  SIG_SF      DAHDI_SIG_SF
00364 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00365 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00366 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00367 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00368 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00369 
00370 #ifdef LOTS_OF_SPANS
00371 #define NUM_SPANS DAHDI_MAX_SPANS
00372 #else
00373 #define NUM_SPANS       32
00374 #endif
00375 
00376 #define CHAN_PSEUDO  -2
00377 
00378 #define CALLPROGRESS_PROGRESS    1
00379 #define CALLPROGRESS_FAX_OUTGOING   2
00380 #define CALLPROGRESS_FAX_INCOMING   4
00381 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00382 
00383 #define NUM_CADENCE_MAX 25
00384 static int num_cadence = 4;
00385 static int user_has_defined_cadences = 0;
00386 
00387 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00388    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00389    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00390    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00391    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00392 };
00393 
00394 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00395  * is 1, the second pause is 2 and so on.
00396  */
00397 
00398 static int cidrings[NUM_CADENCE_MAX] = {
00399    2,                            /*!< Right after first long ring */
00400    4,                            /*!< Right after long part */
00401    3,                            /*!< After third chirp */
00402    2,                            /*!< Second spell */
00403 };
00404 
00405 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00406 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00407 
00408 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00409          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00410 
00411 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00412 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00413 
00414 static char defaultcic[64] = "";
00415 static char defaultozz[64] = "";
00416 
00417 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00418 static char mwimonitornotify[PATH_MAX] = "";
00419 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00420 static int  mwisend_rpas = 0;
00421 #endif
00422 
00423 static char progzone[10] = "";
00424 
00425 static int usedistinctiveringdetection = 0;
00426 static int distinctiveringaftercid = 0;
00427 
00428 static int numbufs = 4;
00429 
00430 static int mwilevel = 512;
00431 static int dtmfcid_level = 256;
00432 
00433 #define REPORT_CHANNEL_ALARMS 1
00434 #define REPORT_SPAN_ALARMS    2 
00435 static int report_alarms = REPORT_CHANNEL_ALARMS;
00436 
00437 #ifdef HAVE_PRI
00438 static int pridebugfd = -1;
00439 static char pridebugfilename[1024] = "";
00440 #endif
00441 
00442 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00443 static int firstdigittimeout = 16000;
00444 
00445 /*! \brief How long to wait for following digits (FXO logic) */
00446 static int gendigittimeout = 8000;
00447 
00448 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00449 static int matchdigittimeout = 3000;
00450 
00451 /*! \brief Protect the interface list (of dahdi_pvt's) */
00452 AST_MUTEX_DEFINE_STATIC(iflock);
00453 
00454 
00455 static int ifcount = 0;
00456 
00457 #ifdef HAVE_PRI
00458 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00459 #endif
00460 
00461 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00462    when it's doing something critical. */
00463 AST_MUTEX_DEFINE_STATIC(monlock);
00464 
00465 /*! \brief This is the thread for the monitor which checks for input on the channels
00466    which are not currently in use. */
00467 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00468 static ast_cond_t ss_thread_complete;
00469 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00470 AST_MUTEX_DEFINE_STATIC(restart_lock);
00471 static int ss_thread_count = 0;
00472 static int num_restart_pending = 0;
00473 
00474 static int restart_monitor(void);
00475 
00476 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);
00477 
00478 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00479 
00480 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00481 {
00482    /* This module does not handle MWI in an event-based manner.  However, it
00483     * subscribes to MWI for each mailbox that is configured so that the core
00484     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00485     * event cache instead of checking the mailbox directly. */
00486 }
00487 
00488 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00489 static inline int dahdi_get_event(int fd)
00490 {
00491    int j;
00492    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493       return -1;
00494    return j;
00495 }
00496 
00497 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00498 static inline int dahdi_wait_event(int fd)
00499 {
00500    int i, j = 0;
00501    i = DAHDI_IOMUX_SIGEVENT;
00502    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503       return -1;
00504    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505       return -1;
00506    return j;
00507 }
00508 
00509 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00510 #define READ_SIZE 160
00511 
00512 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00513 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00514 
00515 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00516 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00517 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00518 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00519 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00520 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00521 
00522 struct dahdi_pvt;
00523 
00524 /*!
00525  * \brief Configured ring timeout base.
00526  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00527  */
00528 static int ringt_base = DEFAULT_RINGT;
00529 
00530 #if defined(HAVE_SS7)
00531 
00532 struct dahdi_ss7 {
00533    struct sig_ss7_linkset ss7;
00534 };
00535 
00536 static struct dahdi_ss7 linksets[NUM_SPANS];
00537 
00538 static int cur_ss7type = -1;
00539 static int cur_linkset = -1;
00540 static int cur_pointcode = -1;
00541 static int cur_cicbeginswith = -1;
00542 static int cur_adjpointcode = -1;
00543 static int cur_networkindicator = -1;
00544 static int cur_defaultdpc = -1;
00545 #endif   /* defined(HAVE_SS7) */
00546 
00547 #ifdef HAVE_OPENR2
00548 struct dahdi_mfcr2 {
00549    pthread_t r2master;            /*!< Thread of master */
00550    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00551    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00552    int numchans;                          /*!< Number of channels in this R2 block */
00553    int monitored_count;                   /*!< Number of channels being monitored */
00554 };
00555 
00556 struct dahdi_mfcr2_conf {
00557    openr2_variant_t variant;
00558    int mfback_timeout;
00559    int metering_pulse_timeout;
00560    int max_ani;
00561    int max_dnis;
00562    signed int get_ani_first:2;
00563 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00564    signed int skip_category_request:2;
00565 #endif
00566    unsigned int call_files:1;
00567    unsigned int allow_collect_calls:1;
00568    unsigned int charge_calls:1;
00569    unsigned int accept_on_offer:1;
00570    unsigned int forced_release:1;
00571    unsigned int double_answer:1;
00572    signed int immediate_accept:2;
00573    char logdir[OR2_MAX_PATH];
00574    char r2proto_file[OR2_MAX_PATH];
00575    openr2_log_level_t loglevel;
00576    openr2_calling_party_category_t category;
00577 };
00578 
00579 /* malloc'd array of malloc'd r2links */
00580 static struct dahdi_mfcr2 **r2links;
00581 /* how many r2links have been malloc'd */
00582 static int r2links_count = 0;
00583 
00584 #endif /* HAVE_OPENR2 */
00585 
00586 #ifdef HAVE_PRI
00587 
00588 struct dahdi_pri {
00589    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00590    int mastertrunkgroup;               /*!< What trunk group is our master */
00591    int prilogicalspan;                 /*!< Logical span number within trunk group */
00592    struct sig_pri_span pri;
00593 };
00594 
00595 static struct dahdi_pri pris[NUM_SPANS];
00596 
00597 #if defined(HAVE_PRI_CCSS)
00598 /*! DAHDI PRI CCSS agent and monitor type name. */
00599 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00600 #endif   /* defined(HAVE_PRI_CCSS) */
00601 
00602 #else
00603 /*! Shut up the compiler */
00604 struct dahdi_pri;
00605 #endif
00606 
00607 #define SUB_REAL  0        /*!< Active call */
00608 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00609 #define SUB_THREEWAY 2        /*!< Three-way call */
00610 
00611 /* Polarity states */
00612 #define POLARITY_IDLE   0
00613 #define POLARITY_REV    1
00614 
00615 
00616 struct distRingData {
00617    int ring[3];
00618    int range;
00619 };
00620 struct ringContextData {
00621    char contextData[AST_MAX_CONTEXT];
00622 };
00623 struct dahdi_distRings {
00624    struct distRingData ringnum[3];
00625    struct ringContextData ringContext[3];
00626 };
00627 
00628 static const char * const subnames[] = {
00629    "Real",
00630    "Callwait",
00631    "Threeway"
00632 };
00633 
00634 struct dahdi_subchannel {
00635    int dfd;
00636    struct ast_channel *owner;
00637    int chan;
00638    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00639    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00640    unsigned int needringing:1;
00641    unsigned int needbusy:1;
00642    unsigned int needcongestion:1;
00643    unsigned int needanswer:1;
00644    unsigned int needflash:1;
00645    unsigned int needhold:1;
00646    unsigned int needunhold:1;
00647    unsigned int linear:1;
00648    unsigned int inthreeway:1;
00649    struct dahdi_confinfo curconf;
00650 };
00651 
00652 #define CONF_USER_REAL     (1 << 0)
00653 #define CONF_USER_THIRDCALL   (1 << 1)
00654 
00655 #define MAX_SLAVES   4
00656 
00657 /* States for sending MWI message
00658  * First three states are required for send Ring Pulse Alert Signal
00659  */
00660 typedef enum {
00661    MWI_SEND_NULL = 0,
00662    MWI_SEND_SA,
00663    MWI_SEND_SA_WAIT,
00664    MWI_SEND_PAUSE,
00665    MWI_SEND_SPILL,
00666    MWI_SEND_CLEANUP,
00667    MWI_SEND_DONE,
00668 } mwisend_states;
00669 
00670 struct mwisend_info {
00671    struct   timeval  pause;
00672    mwisend_states    mwisend_current;
00673 };
00674 
00675 /*! Specify the lists dahdi_pvt can be put in. */
00676 enum DAHDI_IFLIST {
00677    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00678    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00679 #if defined(HAVE_PRI)
00680    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00681 #endif   /* defined(HAVE_PRI) */
00682 };
00683 
00684 struct dahdi_pvt {
00685    ast_mutex_t lock;             /*!< Channel private lock. */
00686    struct callerid_state *cs;
00687    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00688                      /*!< Up to three channels can be associated with this call */
00689 
00690    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00691    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00692    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00693 
00694    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00695    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00696    int inconference;          /*!< If our real should be in the conference */
00697 
00698    int bufsize;                /*!< Size of the buffers */
00699    int buf_no;             /*!< Number of buffers */
00700    int buf_policy;            /*!< Buffer policy */
00701    int faxbuf_no;              /*!< Number of Fax buffers */
00702    int faxbuf_policy;          /*!< Fax buffer policy */
00703    int sig;             /*!< Signalling style */
00704    /*!
00705     * \brief Nonzero if the signaling type is sent over a radio.
00706     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00707     */
00708    int radio;
00709    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00710    int oprmode;               /*!< "Operator Services" mode */
00711    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00712    /*! \brief Amount of gain to increase during caller id */
00713    float cid_rxgain;
00714    /*! \brief Rx gain set by chan_dahdi.conf */
00715    float rxgain;
00716    /*! \brief Tx gain set by chan_dahdi.conf */
00717    float txgain;
00718 
00719    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00720    float rxdrc;
00721    
00722    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00723    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00724    struct dahdi_pvt *next;          /*!< Next channel in list */
00725    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00726 
00727    /* flags */
00728 
00729    /*!
00730     * \brief TRUE if ADSI (Analog Display Services Interface) available
00731     * \note Set from the "adsi" value read in from chan_dahdi.conf
00732     */
00733    unsigned int adsi:1;
00734    /*!
00735     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00736     * call is answered by the remote party.
00737     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00738     */
00739    unsigned int answeronpolarityswitch:1;
00740    /*!
00741     * \brief TRUE if busy detection is enabled.
00742     * (Listens for the beep-beep busy pattern.)
00743     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00744     */
00745    unsigned int busydetect:1;
00746    /*!
00747     * \brief TRUE if call return is enabled.
00748     * (*69, if your dialplan doesn't catch this first)
00749     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00750     */
00751    unsigned int callreturn:1;
00752    /*!
00753     * \brief TRUE if busy extensions will hear the call-waiting tone
00754     * and can use hook-flash to switch between callers.
00755     * \note Can be disabled by dialing *70.
00756     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00757     */
00758    unsigned int callwaiting:1;
00759    /*!
00760     * \brief TRUE if send caller ID for Call Waiting
00761     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00762     */
00763    unsigned int callwaitingcallerid:1;
00764    /*!
00765     * \brief TRUE if support for call forwarding enabled.
00766     * Dial *72 to enable call forwarding.
00767     * Dial *73 to disable call forwarding.
00768     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00769     */
00770    unsigned int cancallforward:1;
00771    /*!
00772     * \brief TRUE if support for call parking is enabled.
00773     * \note Set from the "canpark" value read in from chan_dahdi.conf
00774     */
00775    unsigned int canpark:1;
00776    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00777    unsigned int confirmanswer:1;
00778    /*!
00779     * \brief TRUE if the channel is to be destroyed on hangup.
00780     * (Used by pseudo channels.)
00781     */
00782    unsigned int destroy:1;
00783    unsigned int didtdd:1;           /*!< flag to say its done it once */
00784    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00785    unsigned int dialednone:1;
00786    /*!
00787     * \brief TRUE if in the process of dialing digits or sending something.
00788     * \note This is used as a receive squelch for ISDN until connected.
00789     */
00790    unsigned int dialing:1;
00791    /*! \brief TRUE if the transfer capability of the call is digital. */
00792    unsigned int digital:1;
00793    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00794    unsigned int dnd:1;
00795    /*! \brief XXX BOOLEAN Purpose??? */
00796    unsigned int echobreak:1;
00797    /*!
00798     * \brief TRUE if echo cancellation enabled when bridged.
00799     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00800     * \note Disabled if the echo canceller is not setup.
00801     */
00802    unsigned int echocanbridged:1;
00803    /*! \brief TRUE if echo cancellation is turned on. */
00804    unsigned int echocanon:1;
00805    /*! \brief TRUE if a fax tone has already been handled. */
00806    unsigned int faxhandled:1;
00807    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00808    unsigned int usefaxbuffers:1;
00809    /*! TRUE while buffer configuration override is in use */
00810    unsigned int bufferoverrideinuse:1;
00811    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00812    unsigned int firstradio:1;
00813    /*!
00814     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00815     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00816     */
00817    unsigned int hanguponpolarityswitch:1;
00818    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00819    unsigned int hardwaredtmf:1;
00820    /*!
00821     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00822     * \note Caller ID can be disabled by dialing *67.
00823     * \note Caller ID can be enabled by dialing *82.
00824     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00825     */
00826    unsigned int hidecallerid:1;
00827    /*!
00828     * \brief TRUE if hide just the name not the number for legacy PBX use.
00829     * \note Only applies to PRI channels.
00830     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00831     */
00832    unsigned int hidecalleridname:1;
00833    /*! \brief TRUE if DTMF detection is disabled. */
00834    unsigned int ignoredtmf:1;
00835    /*!
00836     * \brief TRUE if the channel should be answered immediately
00837     * without attempting to gather any digits.
00838     * \note Set from the "immediate" value read in from chan_dahdi.conf
00839     */
00840    unsigned int immediate:1;
00841    /*! \brief TRUE if in an alarm condition. */
00842    unsigned int inalarm:1;
00843    /*! \brief TRUE if TDD in MATE mode */
00844    unsigned int mate:1;
00845    /*! \brief TRUE if we originated the call leg. */
00846    unsigned int outgoing:1;
00847    /* unsigned int overlapdial:1;         unused and potentially confusing */
00848    /*!
00849     * \brief TRUE if busy extensions will hear the call-waiting tone
00850     * and can use hook-flash to switch between callers.
00851     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00852     */
00853    unsigned int permcallwaiting:1;
00854    /*!
00855     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00856     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00857     */
00858    unsigned int permhidecallerid:1;
00859    /*!
00860     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00861     * \note Set from the "priindication" value read in from chan_dahdi.conf
00862     */
00863    unsigned int priindication_oob:1;
00864    /*!
00865     * \brief TRUE if PRI B channels are always exclusively selected.
00866     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00867     */
00868    unsigned int priexclusive:1;
00869    /*!
00870     * \brief TRUE if we will pulse dial.
00871     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00872     */
00873    unsigned int pulse:1;
00874    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00875    unsigned int pulsedial:1;
00876    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00877    /*!
00878     * \brief TRUE if caller ID is restricted.
00879     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00880     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00881     */
00882    unsigned int restrictcid:1;
00883    /*!
00884     * \brief TRUE if three way calling is enabled
00885     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00886     */
00887    unsigned int threewaycalling:1;
00888    /*!
00889     * \brief TRUE if call transfer is enabled
00890     * \note For FXS ports (either direct analog or over T1/E1):
00891     *   Support flash-hook call transfer
00892     * \note For digital ports using ISDN PRI protocols:
00893     *   Support switch-side transfer (called 2BCT, RLT or other names)
00894     * \note Set from the "transfer" value read in from chan_dahdi.conf
00895     */
00896    unsigned int transfer:1;
00897    /*!
00898     * \brief TRUE if caller ID is used on this channel.
00899     * \note PRI and SS7 spans will save caller ID from the networking peer.
00900     * \note FXS ports will generate the caller ID spill.
00901     * \note FXO ports will listen for the caller ID spill.
00902     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00903     */
00904    unsigned int use_callerid:1;
00905    /*!
00906     * \brief TRUE if we will use the calling presentation setting
00907     * from the Asterisk channel for outgoing calls.
00908     * \note Only applies to PRI and SS7 channels.
00909     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00910     */
00911    unsigned int use_callingpres:1;
00912    /*!
00913     * \brief TRUE if distinctive rings are to be detected.
00914     * \note For FXO lines
00915     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00916     */
00917    unsigned int usedistinctiveringdetection:1;
00918    /*!
00919     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00920     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00921     */
00922    unsigned int dahditrcallerid:1;
00923    /*!
00924     * \brief TRUE if allowed to flash-transfer to busy channels.
00925     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00926     */
00927    unsigned int transfertobusy:1;
00928    /*!
00929     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00930     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00931     */
00932    unsigned int mwimonitor_neon:1;
00933    /*!
00934     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00935     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00936     */
00937    unsigned int mwimonitor_fsk:1;
00938    /*!
00939     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00940     * \note RPAS - Ring Pulse Alert Signal
00941     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00942     */
00943    unsigned int mwimonitor_rpas:1;
00944    /*! \brief TRUE if an MWI monitor thread is currently active */
00945    unsigned int mwimonitoractive:1;
00946    /*! \brief TRUE if a MWI message sending thread is active */
00947    unsigned int mwisendactive:1;
00948    /*!
00949     * \brief TRUE if channel is out of reset and ready
00950     * \note Set but not used.
00951     */
00952    unsigned int inservice:1;
00953    /*!
00954     * \brief TRUE if the channel is locally blocked.
00955     * \note Applies to SS7 and MFCR2 channels.
00956     */
00957    unsigned int locallyblocked:1;
00958    /*!
00959     * \brief TRUE if the channel is remotely blocked.
00960     * \note Applies to SS7 and MFCR2 channels.
00961     */
00962    unsigned int remotelyblocked:1;
00963    /*!
00964     * \brief TRUE if the channel alarms will be managed also as Span ones
00965     * \note Applies to all channels
00966     */
00967    unsigned int manages_span_alarms:1;
00968 
00969 #if defined(HAVE_PRI)
00970    struct sig_pri_span *pri;
00971    int logicalspan;
00972 #endif
00973    /*!
00974     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00975     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00976     */
00977    unsigned int use_smdi:1;
00978    struct mwisend_info mwisend_data;
00979    /*! \brief The SMDI interface to get SMDI messages from. */
00980    struct ast_smdi_interface *smdi_iface;
00981 
00982    /*! \brief Distinctive Ring data */
00983    struct dahdi_distRings drings;
00984 
00985    /*!
00986     * \brief The configured context for incoming calls.
00987     * \note The "context" string read in from chan_dahdi.conf
00988     */
00989    char context[AST_MAX_CONTEXT];
00990    /*!
00991     * \brief Saved context string.
00992     */
00993    char defcontext[AST_MAX_CONTEXT];
00994    /*! \brief Extension to use in the dialplan. */
00995    char exten[AST_MAX_EXTENSION];
00996    /*!
00997     * \brief Language configured for calls.
00998     * \note The "language" string read in from chan_dahdi.conf
00999     */
01000    char language[MAX_LANGUAGE];
01001    /*!
01002     * \brief The configured music-on-hold class to use for calls.
01003     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01004     */
01005    char mohinterpret[MAX_MUSICCLASS];
01006    /*!
01007     * \brief Suggested music-on-hold class for peer channel to use for calls.
01008     * \note The "mohsuggest" string read in from chan_dahdi.conf
01009     */
01010    char mohsuggest[MAX_MUSICCLASS];
01011    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01012 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01013    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01014    char cid_ani[AST_MAX_EXTENSION];
01015 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01016    /*! \brief Automatic Number Identification code from PRI */
01017    int cid_ani2;
01018    /*! \brief Caller ID number from an incoming call. */
01019    char cid_num[AST_MAX_EXTENSION];
01020    /*!
01021     * \brief Caller ID tag from incoming call
01022     * \note the "cid_tag" string read in from chan_dahdi.conf
01023     */
01024    char cid_tag[AST_MAX_EXTENSION];
01025    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01026    int cid_ton;
01027    /*! \brief Caller ID name from an incoming call. */
01028    char cid_name[AST_MAX_EXTENSION];
01029    /*! \brief Caller ID subaddress from an incoming call. */
01030    char cid_subaddr[AST_MAX_EXTENSION];
01031    char *origcid_num;            /*!< malloced original callerid */
01032    char *origcid_name;           /*!< malloced original callerid */
01033    /*! \brief Call waiting number. */
01034    char callwait_num[AST_MAX_EXTENSION];
01035    /*! \brief Call waiting name. */
01036    char callwait_name[AST_MAX_EXTENSION];
01037    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01038    char rdnis[AST_MAX_EXTENSION];
01039    /*! \brief Dialed Number Identifier */
01040    char dnid[AST_MAX_EXTENSION];
01041    /*!
01042     * \brief Bitmapped groups this belongs to.
01043     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01044     */
01045    ast_group_t group;
01046    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01047    int law_default;
01048    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01049    int law;
01050    int confno;             /*!< Our conference */
01051    int confusers;             /*!< Who is using our conference */
01052    int propconfno;               /*!< Propagated conference number */
01053    /*!
01054     * \brief Bitmapped call groups this belongs to.
01055     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01056     */
01057    ast_group_t callgroup;
01058    /*!
01059     * \brief Bitmapped pickup groups this belongs to.
01060     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01061     */
01062    ast_group_t pickupgroup;
01063    /*!
01064     * \brief Channel variable list with associated values to set when a channel is created.
01065     * \note The "setvar" strings read in from chan_dahdi.conf
01066     */
01067    struct ast_variable *vars;
01068    int channel;               /*!< Channel Number */
01069    int span;               /*!< Span number */
01070    time_t guardtime;          /*!< Must wait this much time before using for new call */
01071    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01072    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01073    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01074    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01075    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01076    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01077    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01078    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01079    /*! \brief Analog caller ID waveform sample buffer */
01080    unsigned char *cidspill;
01081    /*! \brief Position in the cidspill buffer to send out next. */
01082    int cidpos;
01083    /*! \brief Length of the cidspill buffer containing samples. */
01084    int cidlen;
01085    /*! \brief Ring timeout timer?? */
01086    int ringt;
01087    /*!
01088     * \brief Ring timeout base.
01089     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01090     */
01091    int ringt_base;
01092    /*!
01093     * \brief Number of most significant digits/characters to strip from the dialed number.
01094     * \note Feature is deprecated.  Use dialplan logic.
01095     * \note The characters are stripped before the PRI TON/NPI prefix
01096     * characters are processed.
01097     */
01098    int stripmsd;
01099    /*!
01100     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01101     * \note
01102     * After CAS is sent, the call waiting caller id will be sent if the phone
01103     * gives a positive reply.
01104     */
01105    int callwaitcas;
01106    /*! \brief Number of call waiting rings. */
01107    int callwaitrings;
01108    /*! \brief Echo cancel parameters. */
01109    struct {
01110       struct dahdi_echocanparams head;
01111       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01112    } echocancel;
01113    /*!
01114     * \brief Echo training time. 0 = disabled
01115     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01116     */
01117    int echotraining;
01118    /*! \brief Filled with 'w'.  XXX Purpose?? */
01119    char echorest[20];
01120    /*!
01121     * \brief Number of times to see "busy" tone before hanging up.
01122     * \note Set from the "busycount" value read in from chan_dahdi.conf
01123     */
01124    int busycount;
01125    /*!
01126     * \brief Length of "busy" tone on time.
01127     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01128     */
01129    int busy_tonelength;
01130    /*!
01131     * \brief Length of "busy" tone off time.
01132     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01133     */
01134    int busy_quietlength;
01135    /*!
01136     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01137     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01138     */
01139    int callprogress;
01140    /*!
01141     * \brief Number of milliseconds to wait for dialtone.
01142     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01143     */
01144    int waitfordialtone;
01145    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01146    struct timeval flashtime;        /*!< Last flash-hook time */
01147    /*! \brief Opaque DSP configuration structure. */
01148    struct ast_dsp *dsp;
01149    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01150    struct dahdi_dialoperation dop;
01151    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01152    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01153    char finaldial[64];
01154    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01155    int amaflags;              /*!< AMA Flags */
01156    struct tdd_state *tdd;           /*!< TDD flag */
01157    /*! \brief Accumulated call forwarding number. */
01158    char call_forward[AST_MAX_EXTENSION];
01159    /*!
01160     * \brief Voice mailbox location.
01161     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01162     */
01163    char mailbox[AST_MAX_EXTENSION];
01164    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01165    struct ast_event_sub *mwi_event_sub;
01166    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01167    char dialdest[256];
01168 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01169    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01170    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01171    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01172 #endif
01173    int distinctivering;          /*!< Which distinctivering to use */
01174    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01175    /*! \brief Holding place for event injected from outside normal operation. */
01176    int fake_event;
01177    /*!
01178     * \brief Minimal time period (ms) between the answer polarity
01179     * switch and hangup polarity switch.
01180     */
01181    int polarityonanswerdelay;
01182    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01183    struct timeval polaritydelaytv;
01184    /*!
01185     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01186     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01187     */
01188    int sendcalleridafter;
01189    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01190    int polarity;
01191    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01192    int dsp_features;
01193 #if defined(HAVE_SS7)
01194    /*! \brief SS7 control parameters */
01195    struct sig_ss7_linkset *ss7;
01196 #endif   /* defined(HAVE_SS7) */
01197 #ifdef HAVE_OPENR2
01198    struct dahdi_mfcr2 *mfcr2;
01199    openr2_chan_t *r2chan;
01200    openr2_calling_party_category_t mfcr2_recvd_category;
01201    openr2_calling_party_category_t mfcr2_category;
01202    int mfcr2_dnis_index;
01203    int mfcr2_ani_index;
01204    int mfcr2call:1;
01205    int mfcr2_answer_pending:1;
01206    int mfcr2_charge_calls:1;
01207    int mfcr2_allow_collect_calls:1;
01208    int mfcr2_forced_release:1;
01209    int mfcr2_dnis_matched:1;
01210    int mfcr2_call_accepted:1;
01211    int mfcr2_progress:1;
01212    int mfcr2_accept_on_offer:1;
01213 #endif
01214    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01215    char begindigit;
01216    /*! \brief TRUE if confrence is muted. */
01217    int muting;
01218    void *sig_pvt;
01219    struct ast_cc_config_params *cc_params;
01220    /* DAHDI channel names may differ greatly from the
01221     * string that was provided to an app such as Dial. We
01222     * need to save the original string passed to dahdi_request
01223     * for call completion purposes. This way, we can replicate
01224     * the original dialed string later.
01225     */
01226    char dialstring[AST_CHANNEL_NAME];
01227 };
01228 
01229 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01230    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01231    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01232    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01233    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01234    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01235    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01236    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01237    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01238    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01239    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01240    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01241    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01242    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01243    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01244    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01246    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01247    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01248    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01249    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01250    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01251    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01252    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01253    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01255    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01256    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01257    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01258    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01259    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01260    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01261    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01262    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01263    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01265    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01266    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01267    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01268    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01269    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01270    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01271    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01272    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01273    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01274    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01275    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01276    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01277    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01278    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01279    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01280    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01281    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01282    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01283    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01284    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01285    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01286    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01287    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01288    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01289    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01290    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01291    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01292    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01293    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01294    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01295    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01296    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01297 
01298 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01299 
01300 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01301 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01302 
01303 #if defined(HAVE_PRI)
01304 static struct dahdi_parms_pseudo {
01305    int buf_no;             /*!< Number of buffers */
01306    int buf_policy;            /*!< Buffer policy */
01307    int faxbuf_no;              /*!< Number of Fax buffers */
01308    int faxbuf_policy;          /*!< Fax buffer policy */
01309 } dahdi_pseudo_parms;
01310 #endif   /* defined(HAVE_PRI) */
01311 
01312 /*! \brief Channel configuration from chan_dahdi.conf .
01313  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01314  * Generally there is a field here for every possible configuration item.
01315  *
01316  * The state of fields is saved along the parsing and whenever a 'channel'
01317  * statement is reached, the current dahdi_chan_conf is used to configure the
01318  * channel (struct dahdi_pvt)
01319  *
01320  * \see dahdi_chan_init for the default values.
01321  */
01322 struct dahdi_chan_conf {
01323    struct dahdi_pvt chan;
01324 #ifdef HAVE_PRI
01325    struct dahdi_pri pri;
01326 #endif
01327 
01328 #if defined(HAVE_SS7)
01329    struct dahdi_ss7 ss7;
01330 #endif   /* defined(HAVE_SS7) */
01331 
01332 #ifdef HAVE_OPENR2
01333    struct dahdi_mfcr2_conf mfcr2;
01334 #endif
01335    struct dahdi_params timing;
01336    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01337    /*! Continue configuration even if a channel is not there. */
01338    int ignore_failed_channels;
01339 
01340    /*!
01341     * \brief The serial port to listen for SMDI data on
01342     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01343     */
01344    char smdi_port[SMDI_MAX_FILENAME_LEN];
01345 };
01346 
01347 /*! returns a new dahdi_chan_conf with default values (by-value) */
01348 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01349 {
01350    /* recall that if a field is not included here it is initialized
01351     * to 0 or equivalent
01352     */
01353    struct dahdi_chan_conf conf = {
01354 #ifdef HAVE_PRI
01355       .pri.pri = {
01356          .nsf = PRI_NSF_NONE,
01357          .switchtype = PRI_SWITCH_NI2,
01358          .dialplan = PRI_UNKNOWN + 1,
01359          .localdialplan = PRI_NATIONAL_ISDN + 1,
01360          .nodetype = PRI_CPE,
01361          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01362 
01363 #if defined(HAVE_PRI_CCSS)
01364          .cc_ptmp_recall_mode = 1,/* specificRecall */
01365          .cc_qsig_signaling_link_req = 1,/* retain */
01366          .cc_qsig_signaling_link_rsp = 1,/* retain */
01367 #endif   /* defined(HAVE_PRI_CCSS) */
01368 
01369          .minunused = 2,
01370          .idleext = "",
01371          .idledial = "",
01372          .internationalprefix = "",
01373          .nationalprefix = "",
01374          .localprefix = "",
01375          .privateprefix = "",
01376          .unknownprefix = "",
01377          .resetinterval = -1,
01378       },
01379 #endif
01380 #if defined(HAVE_SS7)
01381       .ss7.ss7 = {
01382          .called_nai = SS7_NAI_NATIONAL,
01383          .calling_nai = SS7_NAI_NATIONAL,
01384          .internationalprefix = "",
01385          .nationalprefix = "",
01386          .subscriberprefix = "",
01387          .unknownprefix = ""
01388       },
01389 #endif   /* defined(HAVE_SS7) */
01390 #ifdef HAVE_OPENR2
01391       .mfcr2 = {
01392          .variant = OR2_VAR_ITU,
01393          .mfback_timeout = -1,
01394          .metering_pulse_timeout = -1,
01395          .max_ani = 10,
01396          .max_dnis = 4,
01397          .get_ani_first = -1,
01398 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01399          .skip_category_request = -1,
01400 #endif
01401          .call_files = 0,
01402          .allow_collect_calls = 0,
01403          .charge_calls = 1,
01404          .accept_on_offer = 1,
01405          .forced_release = 0,
01406          .double_answer = 0,
01407          .immediate_accept = -1,
01408          .logdir = "",
01409          .r2proto_file = "",
01410          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01411          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01412       },
01413 #endif
01414       .chan = {
01415          .context = "default",
01416          .cid_num = "",
01417          .cid_name = "",
01418          .cid_tag = "",
01419          .mohinterpret = "default",
01420          .mohsuggest = "",
01421          .parkinglot = "",
01422          .transfertobusy = 1,
01423 
01424          .cid_signalling = CID_SIG_BELL,
01425          .cid_start = CID_START_RING,
01426          .dahditrcallerid = 0,
01427          .use_callerid = 1,
01428          .sig = -1,
01429          .outsigmod = -1,
01430 
01431          .cid_rxgain = +5.0,
01432 
01433          .tonezone = -1,
01434 
01435          .echocancel.head.tap_length = 1,
01436 
01437          .busycount = 3,
01438 
01439          .accountcode = "",
01440 
01441          .mailbox = "",
01442 
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444          .mwisend_fsk = 1,
01445 #endif
01446          .polarityonanswerdelay = 600,
01447 
01448          .sendcalleridafter = DEFAULT_CIDRINGS,
01449 
01450          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451          .buf_no = numbufs,
01452          .usefaxbuffers = 0,
01453          .cc_params = ast_cc_config_params_init(),
01454       },
01455       .timing = {
01456          .prewinktime = -1,
01457          .preflashtime = -1,
01458          .winktime = -1,
01459          .flashtime = -1,
01460          .starttime = -1,
01461          .rxwinktime = -1,
01462          .rxflashtime = -1,
01463          .debouncetime = -1
01464       },
01465       .is_sig_auto = 1,
01466       .smdi_port = "/dev/ttyS0",
01467    };
01468 
01469    return conf;
01470 }
01471 
01472 
01473 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01474 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01475 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01476 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01477 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01478 static int dahdi_hangup(struct ast_channel *ast);
01479 static int dahdi_answer(struct ast_channel *ast);
01480 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01481 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01482 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01483 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01484 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01485 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01486 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01487 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01488 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01489 static int dahdi_devicestate(void *data);
01490 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01491 
01492 static const struct ast_channel_tech dahdi_tech = {
01493    .type = "DAHDI",
01494    .description = tdesc,
01495    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01496    .requester = dahdi_request,
01497    .send_digit_begin = dahdi_digit_begin,
01498    .send_digit_end = dahdi_digit_end,
01499    .send_text = dahdi_sendtext,
01500    .call = dahdi_call,
01501    .hangup = dahdi_hangup,
01502    .answer = dahdi_answer,
01503    .read = dahdi_read,
01504    .write = dahdi_write,
01505    .bridge = dahdi_bridge,
01506    .exception = dahdi_exception,
01507    .indicate = dahdi_indicate,
01508    .fixup = dahdi_fixup,
01509    .setoption = dahdi_setoption,
01510    .queryoption = dahdi_queryoption,
01511    .func_channel_read = dahdi_func_read,
01512    .func_channel_write = dahdi_func_write,
01513    .devicestate = dahdi_devicestate,
01514    .cc_callback = dahdi_cc_callback,
01515 };
01516 
01517 #define GET_CHANNEL(p) ((p)->channel)
01518 
01519 #define SIG_PRI_LIB_HANDLE_CASES \
01520    SIG_PRI:                \
01521    case SIG_BRI:              \
01522    case SIG_BRI_PTMP
01523 
01524 /*!
01525  * \internal
01526  * \brief Determine if sig_pri handles the signaling.
01527  * \since 1.8
01528  *
01529  * \param signaling Signaling to determine if is for sig_pri.
01530  *
01531  * \return TRUE if the signaling is for sig_pri.
01532  */
01533 static inline int dahdi_sig_pri_lib_handles(int signaling)
01534 {
01535    int handles;
01536 
01537    switch (signaling) {
01538    case SIG_PRI_LIB_HANDLE_CASES:
01539       handles = 1;
01540       break;
01541    default:
01542       handles = 0;
01543       break;
01544    }
01545 
01546    return handles;
01547 }
01548 
01549 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01550 {
01551    switch (sig) {
01552    case SIG_FXOLS:
01553       return ANALOG_SIG_FXOLS;
01554    case SIG_FXOGS:
01555       return ANALOG_SIG_FXOGS;
01556    case SIG_FXOKS:
01557       return ANALOG_SIG_FXOKS;
01558    case SIG_FXSLS:
01559       return ANALOG_SIG_FXSLS;
01560    case SIG_FXSGS:
01561       return ANALOG_SIG_FXSGS;
01562    case SIG_FXSKS:
01563       return ANALOG_SIG_FXSKS;
01564    case SIG_EMWINK:
01565       return ANALOG_SIG_EMWINK;
01566    case SIG_EM:
01567       return ANALOG_SIG_EM;
01568    case SIG_EM_E1:
01569       return ANALOG_SIG_EM_E1;
01570    case SIG_FEATD:
01571       return ANALOG_SIG_FEATD;
01572    case SIG_FEATDMF:
01573       return ANALOG_SIG_FEATDMF;
01574    case SIG_E911:
01575       return SIG_E911;
01576    case SIG_FGC_CAMA:
01577       return ANALOG_SIG_FGC_CAMA;
01578    case SIG_FGC_CAMAMF:
01579       return ANALOG_SIG_FGC_CAMAMF;
01580    case SIG_FEATB:
01581       return ANALOG_SIG_FEATB;
01582    case SIG_SFWINK:
01583       return ANALOG_SIG_SFWINK;
01584    case SIG_SF:
01585       return ANALOG_SIG_SF;
01586    case SIG_SF_FEATD:
01587       return ANALOG_SIG_SF_FEATD;
01588    case SIG_SF_FEATDMF:
01589       return ANALOG_SIG_SF_FEATDMF;
01590    case SIG_FEATDMF_TA:
01591       return ANALOG_SIG_FEATDMF_TA;
01592    case SIG_SF_FEATB:
01593       return ANALOG_SIG_FEATB;
01594    default:
01595       return -1;
01596    }
01597 }
01598 
01599 
01600 static int analog_tone_to_dahditone(enum analog_tone tone)
01601 {
01602    switch (tone) {
01603    case ANALOG_TONE_RINGTONE:
01604       return DAHDI_TONE_RINGTONE;
01605    case ANALOG_TONE_STUTTER:
01606       return DAHDI_TONE_STUTTER;
01607    case ANALOG_TONE_CONGESTION:
01608       return DAHDI_TONE_CONGESTION;
01609    case ANALOG_TONE_DIALTONE:
01610       return DAHDI_TONE_DIALTONE;
01611    case ANALOG_TONE_DIALRECALL:
01612       return DAHDI_TONE_DIALRECALL;
01613    case ANALOG_TONE_INFO:
01614       return DAHDI_TONE_INFO;
01615    default:
01616       return -1;
01617    }
01618 }
01619 
01620 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01621 {
01622    int index;
01623 
01624    switch (analogsub) {
01625    case ANALOG_SUB_REAL:
01626       index = SUB_REAL;
01627       break;
01628    case ANALOG_SUB_CALLWAIT:
01629       index = SUB_CALLWAIT;
01630       break;
01631    case ANALOG_SUB_THREEWAY:
01632       index = SUB_THREEWAY;
01633       break;
01634    default:
01635       ast_log(LOG_ERROR, "Unidentified sub!\n");
01636       index = SUB_REAL;
01637    }
01638 
01639    return index;
01640 }
01641 
01642 static enum analog_event dahdievent_to_analogevent(int event);
01643 static int bump_gains(struct dahdi_pvt *p);
01644 static int dahdi_setlinear(int dfd, int linear);
01645 
01646 static int my_start_cid_detect(void *pvt, int cid_signalling)
01647 {
01648    struct dahdi_pvt *p = pvt;
01649    int index = SUB_REAL;
01650    p->cs = callerid_new(cid_signalling);
01651    if (!p->cs) {
01652       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653       return -1;
01654    }
01655    bump_gains(p);
01656    dahdi_setlinear(p->subs[index].dfd, 0);
01657 
01658    return 0;
01659 }
01660 
01661 static int my_stop_cid_detect(void *pvt)
01662 {
01663    struct dahdi_pvt *p = pvt;
01664    int index = SUB_REAL;
01665    if (p->cs)
01666       callerid_free(p->cs);
01667    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668    return 0;
01669 }
01670 
01671 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01672 {
01673    struct dahdi_pvt *p = pvt;
01674    struct analog_pvt *analog_p = p->sig_pvt;
01675    struct pollfd poller;
01676    char *name, *num;
01677    int index = SUB_REAL;
01678    int res;
01679    unsigned char buf[256];
01680    int flags;
01681 
01682    poller.fd = p->subs[SUB_REAL].dfd;
01683    poller.events = POLLPRI | POLLIN;
01684    poller.revents = 0;
01685 
01686    res = poll(&poller, 1, timeout);
01687 
01688    if (poller.revents & POLLPRI) {
01689       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690       return 1;
01691    }
01692 
01693    if (poller.revents & POLLIN) {
01694       /*** NOTES ***/
01695       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01696        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01697        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01698        * a failure and die, and returning 2 means no event was received. */
01699       res = read(p->subs[index].dfd, buf, sizeof(buf));
01700       if (res < 0) {
01701          if (errno != ELAST) {
01702             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703             callerid_free(p->cs);
01704             return -1;
01705          }
01706       }
01707 
01708       if (analog_p->ringt > 0) {
01709          if (!(--analog_p->ringt)) {
01710             /* only return if we timeout from a ring event */
01711             return -1;
01712          }
01713       }
01714 
01715       if (p->cid_signalling == CID_SIG_V23_JP) {
01716          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717       } else {
01718          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719       }
01720       if (res < 0) {
01721          /*
01722           * The previous diagnostic message output likely
01723           * explains why it failed.
01724           */
01725          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726          return -1;
01727       }
01728 
01729       if (res == 1) {
01730          callerid_get(p->cs, &name, &num, &flags);
01731          if (name)
01732             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733          if (num)
01734             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735 
01736          ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737          return 0;
01738       }
01739    }
01740 
01741    *ev = ANALOG_EVENT_NONE;
01742    return 2;
01743 }
01744 
01745 static const char *event2str(int event);
01746 static int restore_gains(struct dahdi_pvt *p);
01747 
01748 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01749 {
01750    unsigned char buf[256];
01751    int distMatches;
01752    int curRingData[RING_PATTERNS];
01753    int receivedRingT;
01754    int counter1;
01755    int counter;
01756    int i;
01757    int res;
01758    int checkaftercid = 0;
01759 
01760    struct dahdi_pvt *p = pvt;
01761    struct analog_pvt *analog_p = p->sig_pvt;
01762 
01763    if (ringdata == NULL) {
01764       ringdata = curRingData;
01765    } else {
01766       checkaftercid = 1;
01767    }
01768 
01769    /* We must have a ring by now, so, if configured, lets try to listen for
01770     * distinctive ringing */
01771    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772       /* Clear the current ring data array so we don't have old data in it. */
01773       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774          ringdata[receivedRingT] = 0;
01775       receivedRingT = 0;
01776       if (checkaftercid && distinctiveringaftercid)
01777          ast_verb(3, "Detecting post-CID distinctive ring\n");
01778       /* Check to see if context is what it should be, if not set to be. */
01779       else if (strcmp(p->context,p->defcontext) != 0) {
01780          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782       }
01783 
01784       for (;;) {
01785          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788             ast_hangup(chan);
01789             return 1;
01790          }
01791          if (i & DAHDI_IOMUX_SIGEVENT) {
01792             res = dahdi_get_event(p->subs[idx].dfd);
01793             if (res == DAHDI_EVENT_NOALARM) {
01794                p->inalarm = 0;
01795                analog_p->inalarm = 0;
01796             }
01797             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798             res = 0;
01799             /* Let us detect distinctive ring */
01800 
01801             ringdata[receivedRingT] = analog_p->ringt;
01802 
01803             if (analog_p->ringt < analog_p->ringt_base/2)
01804                break;
01805             /* Increment the ringT counter so we can match it against
01806                values in chan_dahdi.conf for distinctive ring */
01807             if (++receivedRingT == RING_PATTERNS)
01808                break;
01809          } else if (i & DAHDI_IOMUX_READ) {
01810             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811             if (res < 0) {
01812                if (errno != ELAST) {
01813                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814                   ast_hangup(chan);
01815                   return 1;
01816                }
01817                break;
01818             }
01819             if (analog_p->ringt > 0) {
01820                if (!(--analog_p->ringt)) {
01821                   res = -1;
01822                   break;
01823                }
01824             }
01825          }
01826       }
01827    }
01828    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829       /* this only shows up if you have n of the dring patterns filled in */
01830       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831       for (counter = 0; counter < 3; counter++) {
01832       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01833          distMatches = 0;
01834          /* this only shows up if you have n of the dring patterns filled in */
01835          ast_verb(3, "Checking %d,%d,%d\n",
01836                p->drings.ringnum[counter].ring[0],
01837                p->drings.ringnum[counter].ring[1],
01838                p->drings.ringnum[counter].ring[2]);
01839          for (counter1 = 0; counter1 < 3; counter1++) {
01840             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843                ringdata[counter1]);
01844                distMatches++;
01845             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850                distMatches++;
01851             }
01852          }
01853 
01854          if (distMatches == 3) {
01855             /* The ring matches, set the context to whatever is for distinctive ring.. */
01856             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859             break;
01860          }
01861       }
01862    }
01863    /* Restore linear mode (if appropriate) for Caller*ID processing */
01864    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865    restore_gains(p);
01866 
01867    return 0;
01868 }
01869 
01870 static int my_stop_callwait(void *pvt)
01871 {
01872    struct dahdi_pvt *p = pvt;
01873    p->callwaitingrepeat = 0;
01874    p->cidcwexpire = 0;
01875    p->cid_suppress_expire = 0;
01876 
01877    return 0;
01878 }
01879 
01880 static int send_callerid(struct dahdi_pvt *p);
01881 static int save_conference(struct dahdi_pvt *p);
01882 static int restore_conference(struct dahdi_pvt *p);
01883 
01884 static int my_callwait(void *pvt)
01885 {
01886    struct dahdi_pvt *p = pvt;
01887    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888    if (p->cidspill) {
01889       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890       ast_free(p->cidspill);
01891    }
01892 
01893    /*
01894     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01895     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01896     */
01897    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01898       return -1;
01899    save_conference(p);
01900    /* Silence */
01901    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902    if (!p->callwaitrings && p->callwaitingcallerid) {
01903       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904       p->callwaitcas = 1;
01905       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906    } else {
01907       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908       p->callwaitcas = 0;
01909       p->cidlen = 2400 + READ_SIZE * 4;
01910    }
01911    p->cidpos = 0;
01912    send_callerid(p);
01913 
01914    return 0;
01915 }
01916 
01917 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01918 {
01919    struct dahdi_pvt *p = pvt;
01920 
01921    ast_debug(2, "Starting cid spill\n");
01922 
01923    if (p->cidspill) {
01924       ast_log(LOG_WARNING, "cidspill already exists??\n");
01925       ast_free(p->cidspill);
01926    }
01927 
01928    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929       if (cwcid == 0) {
01930          p->cidlen = ast_callerid_generate(p->cidspill,
01931             caller->id.name.str,
01932             caller->id.number.str,
01933             AST_LAW(p));
01934       } else {
01935          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01936             caller->id.name.str, caller->id.number.str);
01937          p->callwaitcas = 0;
01938          p->cidcwexpire = 0;
01939          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940             caller->id.name.str,
01941             caller->id.number.str,
01942             AST_LAW(p));
01943          p->cidlen += READ_SIZE * 4;
01944       }
01945       p->cidpos = 0;
01946       p->cid_suppress_expire = 0;
01947       send_callerid(p);
01948    }
01949    return 0;
01950 }
01951 
01952 static int my_dsp_reset_and_flush_digits(void *pvt)
01953 {
01954    struct dahdi_pvt *p = pvt;
01955    if (p->dsp)
01956       ast_dsp_digitreset(p->dsp);
01957 
01958    return 0;
01959 }
01960 
01961 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01962 {
01963    struct dahdi_pvt *p = pvt;
01964 
01965    if (p->channel == CHAN_PSEUDO)
01966       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967 
01968    if (mode == ANALOG_DIGITMODE_DTMF) {
01969       /* If we do hardware dtmf, no need for a DSP */
01970       if (p->hardwaredtmf) {
01971          if (p->dsp) {
01972             ast_dsp_free(p->dsp);
01973             p->dsp = NULL;
01974          }
01975          return 0;
01976       }
01977 
01978       if (!p->dsp) {
01979          p->dsp = ast_dsp_new();
01980          if (!p->dsp) {
01981             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982             return -1;
01983          }
01984       }
01985 
01986       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987    } else if (mode == ANALOG_DIGITMODE_MF) {
01988       if (!p->dsp) {
01989          p->dsp = ast_dsp_new();
01990          if (!p->dsp) {
01991             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992             return -1;
01993          }
01994       }
01995       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996    }
01997    return 0;
01998 }
01999 
02000 static int dahdi_wink(struct dahdi_pvt *p, int index);
02001 
02002 static int my_wink(void *pvt, enum analog_sub sub)
02003 {
02004    struct dahdi_pvt *p = pvt;
02005    int index = analogsub_to_dahdisub(sub);
02006    if (index != SUB_REAL) {
02007       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008    }
02009    return dahdi_wink(p, index);
02010 }
02011 
02012 static void wakeup_sub(struct dahdi_pvt *p, int a);
02013 
02014 static int reset_conf(struct dahdi_pvt *p);
02015 
02016 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02017 
02018 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02019 {
02020    struct ast_frame *f = *dest;
02021    struct dahdi_pvt *p = pvt;
02022    int idx = analogsub_to_dahdisub(analog_index);
02023 
02024    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026       f->subclass.integer, f->subclass.integer, ast->name);
02027 
02028    if (f->subclass.integer == 'f') {
02029       if (f->frametype == AST_FRAME_DTMF_END) {
02030          /* Fax tone -- Handle and return NULL */
02031          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032             /* If faxbuffers are configured, use them for the fax transmission */
02033             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034                struct dahdi_bufferinfo bi = {
02035                   .txbufpolicy = p->faxbuf_policy,
02036                   .bufsize = p->bufsize,
02037                   .numbufs = p->faxbuf_no
02038                };
02039                int res;
02040 
02041                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043                } else {
02044                   p->bufferoverrideinuse = 1;
02045                }
02046             }
02047             p->faxhandled = 1;
02048             if (p->dsp) {
02049                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050                ast_dsp_set_features(p->dsp, p->dsp_features);
02051                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052             }
02053             if (strcmp(ast->exten, "fax")) {
02054                const char *target_context = S_OR(ast->macrocontext, ast->context);
02055 
02056                /* We need to unlock 'ast' here because ast_exists_extension has the
02057                 * potential to start autoservice on the channel. Such action is prone
02058                 * to deadlock.
02059                 */
02060                ast_mutex_unlock(&p->lock);
02061                ast_channel_unlock(ast);
02062                if (ast_exists_extension(ast, target_context, "fax", 1,
02063                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064                   ast_channel_lock(ast);
02065                   ast_mutex_lock(&p->lock);
02066                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02068                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069                   if (ast_async_goto(ast, target_context, "fax", 1))
02070                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071                } else {
02072                   ast_channel_lock(ast);
02073                   ast_mutex_lock(&p->lock);
02074                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075                }
02076             } else {
02077                ast_debug(1, "Already in a fax extension, not redirecting\n");
02078             }
02079          } else {
02080             ast_debug(1, "Fax already handled\n");
02081          }
02082          dahdi_confmute(p, 0);
02083       }
02084       p->subs[idx].f.frametype = AST_FRAME_NULL;
02085       p->subs[idx].f.subclass.integer = 0;
02086       *dest = &p->subs[idx].f;
02087    }
02088 }
02089 
02090 static void my_lock_private(void *pvt)
02091 {
02092    struct dahdi_pvt *p = pvt;
02093    ast_mutex_lock(&p->lock);
02094 }
02095 
02096 static void my_unlock_private(void *pvt)
02097 {
02098    struct dahdi_pvt *p = pvt;
02099    ast_mutex_unlock(&p->lock);
02100 }
02101 
02102 static void my_deadlock_avoidance_private(void *pvt)
02103 {
02104    struct dahdi_pvt *p = pvt;
02105 
02106    DEADLOCK_AVOIDANCE(&p->lock);
02107 }
02108 
02109 /*!
02110  * \internal
02111  * \brief Post an AMI DAHDI channel association event.
02112  * \since 1.8
02113  *
02114  * \param p DAHDI private pointer
02115  * \param chan Channel associated with the private pointer
02116  *
02117  * \return Nothing
02118  */
02119 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02120 {
02121    char ch_name[20];
02122 
02123    if (p->channel < CHAN_PSEUDO) {
02124       /* No B channel */
02125       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02126    } else if (p->channel == CHAN_PSEUDO) {
02127       /* Pseudo channel */
02128       strcpy(ch_name, "pseudo");
02129    } else {
02130       /* Real channel */
02131       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02132    }
02133    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02134       "Channel: %s\r\n"
02135       "Uniqueid: %s\r\n"
02136       "DAHDISpan: %d\r\n"
02137       "DAHDIChannel: %s\r\n",
02138       chan->name,
02139       chan->uniqueid,
02140       p->span,
02141       ch_name);
02142 }
02143 
02144 #ifdef HAVE_PRI
02145 /*!
02146  * \internal
02147  * \brief Post an AMI DAHDI channel association event.
02148  * \since 1.8
02149  *
02150  * \param pvt DAHDI private pointer
02151  * \param chan Channel associated with the private pointer
02152  *
02153  * \return Nothing
02154  */
02155 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02156 {
02157    struct dahdi_pvt *p = pvt;
02158 
02159    dahdi_ami_channel_event(p, chan);
02160 }
02161 #endif
02162 
02163 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02164 *  returns the last value of the linear setting 
02165 */ 
02166 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02167 {
02168    struct dahdi_pvt *p = pvt;
02169    int oldval;
02170    int idx = analogsub_to_dahdisub(sub);
02171    
02172    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02173    oldval = p->subs[idx].linear;
02174    p->subs[idx].linear = linear_mode ? 1 : 0;
02175    return oldval;
02176 }
02177 
02178 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02179 {
02180    struct dahdi_pvt *p = pvt;
02181    int idx = analogsub_to_dahdisub(sub);
02182 
02183    p->subs[idx].inthreeway = inthreeway;
02184 }
02185 
02186 static int get_alarms(struct dahdi_pvt *p);
02187 static void handle_alarms(struct dahdi_pvt *p, int alms);
02188 static void my_get_and_handle_alarms(void *pvt)
02189 {
02190    int res;
02191    struct dahdi_pvt *p = pvt;
02192 
02193    res = get_alarms(p);
02194    handle_alarms(p, res);
02195 }
02196 
02197 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02198 {
02199    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02200    if (p)
02201       return p->sig_pvt;
02202    else
02203       return NULL;
02204 }
02205 
02206 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02207 {
02208    struct dahdi_pvt *p = pvt;
02209    int dahdi_sub = analogsub_to_dahdisub(sub);
02210    return p->subs[dahdi_sub].dfd;
02211 }
02212 
02213 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02214 {
02215    struct dahdi_pvt *p = pvt;
02216 
02217    /* Choose proper cadence */
02218    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02219       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02220          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02221       *cidrings = cidrings[p->distinctivering - 1];
02222    } else {
02223       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02224          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02225       *cidrings = p->sendcalleridafter;
02226    }
02227 }
02228 
02229 static void my_set_alarm(void *pvt, int in_alarm)
02230 {
02231    struct dahdi_pvt *p = pvt;
02232 
02233    p->inalarm = in_alarm;
02234 }
02235 
02236 static void my_set_dialing(void *pvt, int is_dialing)
02237 {
02238    struct dahdi_pvt *p = pvt;
02239 
02240    p->dialing = is_dialing;
02241 }
02242 
02243 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02244 static void my_set_digital(void *pvt, int is_digital)
02245 {
02246    struct dahdi_pvt *p = pvt;
02247 
02248    p->digital = is_digital;
02249 }
02250 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02251 
02252 #if defined(HAVE_SS7)
02253 static void my_set_inservice(void *pvt, int is_inservice)
02254 {
02255    struct dahdi_pvt *p = pvt;
02256 
02257    p->inservice = is_inservice;
02258 }
02259 #endif   /* defined(HAVE_SS7) */
02260 
02261 #if defined(HAVE_SS7)
02262 static void my_set_locallyblocked(void *pvt, int is_blocked)
02263 {
02264    struct dahdi_pvt *p = pvt;
02265 
02266    p->locallyblocked = is_blocked;
02267 }
02268 #endif   /* defined(HAVE_SS7) */
02269 
02270 #if defined(HAVE_SS7)
02271 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02272 {
02273    struct dahdi_pvt *p = pvt;
02274 
02275    p->remotelyblocked = is_blocked;
02276 }
02277 #endif   /* defined(HAVE_SS7) */
02278 
02279 static void my_set_ringtimeout(void *pvt, int ringt)
02280 {
02281    struct dahdi_pvt *p = pvt;
02282    p->ringt = ringt;
02283 }
02284 
02285 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02286 {
02287    struct dahdi_pvt *p = pvt;
02288 
02289    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02290       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02291       gettimeofday(&p->waitingfordt, NULL);
02292       ast_setstate(ast, AST_STATE_OFFHOOK);
02293    }
02294 }
02295 
02296 static int my_check_waitingfordt(void *pvt)
02297 {
02298    struct dahdi_pvt *p = pvt;
02299 
02300    if (p->waitingfordt.tv_usec) {
02301       return 1;
02302    }
02303 
02304    return 0;
02305 }
02306 
02307 static void my_set_confirmanswer(void *pvt, int flag)
02308 {
02309    struct dahdi_pvt *p = pvt;
02310    p->confirmanswer = flag;
02311 }
02312 
02313 static int my_check_confirmanswer(void *pvt)
02314 {
02315    struct dahdi_pvt *p = pvt;
02316    if (p->confirmanswer) {
02317       return 1;
02318    }
02319 
02320    return 0;
02321 }
02322 
02323 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02324 {
02325    struct dahdi_pvt *p = pvt;
02326 
02327    p->callwaiting = callwaiting_enable;
02328 }
02329 
02330 static void my_cancel_cidspill(void *pvt)
02331 {
02332    struct dahdi_pvt *p = pvt;
02333 
02334    ast_free(p->cidspill);
02335    p->cidspill = NULL;
02336    restore_conference(p);
02337 }
02338 
02339 static int my_confmute(void *pvt, int mute)
02340 {
02341    struct dahdi_pvt *p = pvt;
02342    return dahdi_confmute(p, mute);
02343 }
02344 
02345 static void my_set_pulsedial(void *pvt, int flag)
02346 {
02347    struct dahdi_pvt *p = pvt;
02348    p->pulsedial = flag;
02349 }
02350 
02351 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02352 {
02353    struct dahdi_pvt *p = pvt;
02354 
02355    p->owner = new_owner;
02356 }
02357 
02358 static const char *my_get_orig_dialstring(void *pvt)
02359 {
02360    struct dahdi_pvt *p = pvt;
02361 
02362    return p->dialstring;
02363 }
02364 
02365 static void my_increase_ss_count(void)
02366 {
02367    ast_mutex_lock(&ss_thread_lock);
02368    ss_thread_count++;
02369    ast_mutex_unlock(&ss_thread_lock);
02370 }
02371 
02372 static void my_decrease_ss_count(void)
02373 {
02374    ast_mutex_lock(&ss_thread_lock);
02375    ss_thread_count--;
02376    ast_cond_signal(&ss_thread_complete);
02377    ast_mutex_unlock(&ss_thread_lock);
02378 }
02379 
02380 static void my_all_subchannels_hungup(void *pvt)
02381 {
02382    struct dahdi_pvt *p = pvt;
02383    int res, law;
02384 
02385    p->faxhandled = 0;
02386    p->didtdd = 0;
02387 
02388    if (p->dsp) {
02389       ast_dsp_free(p->dsp);
02390       p->dsp = NULL;
02391    }
02392 
02393    p->law = p->law_default;
02394    law = p->law_default;
02395    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02396    if (res < 0)
02397       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02398 
02399    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02400 
02401 #if 1
02402    {
02403    int i;
02404    p->owner = NULL;
02405    /* Cleanup owners here */
02406    for (i = 0; i < 3; i++) {
02407       p->subs[i].owner = NULL;
02408    }
02409    }
02410 #endif
02411 
02412    reset_conf(p);
02413    if (num_restart_pending == 0) {
02414       restart_monitor();
02415    }
02416 }
02417 
02418 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02419 
02420 static int my_conf_del(void *pvt, enum analog_sub sub)
02421 {
02422    struct dahdi_pvt *p = pvt;
02423    int x = analogsub_to_dahdisub(sub);
02424 
02425    return conf_del(p, &p->subs[x], x);
02426 }
02427 
02428 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02429 
02430 static int my_conf_add(void *pvt, enum analog_sub sub)
02431 {
02432    struct dahdi_pvt *p = pvt;
02433    int x = analogsub_to_dahdisub(sub);
02434 
02435    return conf_add(p, &p->subs[x], x, 0);
02436 }
02437 
02438 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02439 
02440 static int my_complete_conference_update(void *pvt, int needconference)
02441 {
02442    struct dahdi_pvt *p = pvt;
02443    int needconf = needconference;
02444    int x;
02445    int useslavenative;
02446    struct dahdi_pvt *slave = NULL;
02447 
02448    useslavenative = isslavenative(p, &slave);
02449 
02450    /* If we have a slave, add him to our conference now. or DAX
02451       if this is slave native */
02452    for (x = 0; x < MAX_SLAVES; x++) {
02453       if (p->slaves[x]) {
02454          if (useslavenative)
02455             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02456          else {
02457             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02458             needconf++;
02459          }
02460       }
02461    }
02462    /* If we're supposed to be in there, do so now */
02463    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02464       if (useslavenative)
02465          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02466       else {
02467          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02468          needconf++;
02469       }
02470    }
02471    /* If we have a master, add ourselves to his conference */
02472    if (p->master) {
02473       if (isslavenative(p->master, NULL)) {
02474          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02475       } else {
02476          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02477       }
02478    }
02479    if (!needconf) {
02480       /* Nobody is left (or should be left) in our conference.
02481          Kill it. */
02482       p->confno = -1;
02483    }
02484 
02485    return 0;
02486 }
02487 
02488 static int check_for_conference(struct dahdi_pvt *p);
02489 
02490 static int my_check_for_conference(void *pvt)
02491 {
02492    struct dahdi_pvt *p = pvt;
02493    return check_for_conference(p);
02494 }
02495 
02496 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)
02497 {
02498    struct dahdi_pvt *p = pvt;
02499    int da, db;
02500    int tchan;
02501    int tinthreeway;
02502 
02503    da = analogsub_to_dahdisub(a);
02504    db = analogsub_to_dahdisub(b);
02505 
02506    tchan = p->subs[da].chan;
02507    p->subs[da].chan = p->subs[db].chan;
02508    p->subs[db].chan = tchan;
02509 
02510    tinthreeway = p->subs[da].inthreeway;
02511    p->subs[da].inthreeway = p->subs[db].inthreeway;
02512    p->subs[db].inthreeway = tinthreeway;
02513 
02514    p->subs[da].owner = ast_a;
02515    p->subs[db].owner = ast_b;
02516 
02517    if (ast_a)
02518       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02519    if (ast_b)
02520       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02521 
02522    wakeup_sub(p, a);
02523    wakeup_sub(p, b);
02524 
02525    return;
02526 }
02527 
02528 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02529 
02530 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02531 {
02532    struct dahdi_pvt *p = pvt;
02533    int dsub = analogsub_to_dahdisub(sub);
02534 
02535    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02536 }
02537 
02538 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02539 static int dahdi_setlaw(int dfd, int law)
02540 {
02541    int res;
02542    res = ioctl(dfd, DAHDI_SETLAW, &law);
02543    if (res)
02544       return res;
02545    return 0;
02546 }
02547 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02548 
02549 #if defined(HAVE_PRI)
02550 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)
02551 {
02552    struct dahdi_pvt *p = pvt;
02553    int audio;
02554    int newlaw = -1;
02555 
02556    switch (p->sig) {
02557    case SIG_PRI_LIB_HANDLE_CASES:
02558       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02559          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02560          break;
02561       }
02562       /* Fall through */
02563    default:
02564       /* Set to audio mode at this point */
02565       audio = 1;
02566       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02567          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02568             p->channel, audio, strerror(errno));
02569       }
02570       break;
02571    }
02572 
02573    if (law != SIG_PRI_DEFLAW) {
02574       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02575    }
02576 
02577    ast_copy_string(p->exten, exten, sizeof(p->exten));
02578 
02579    switch (law) {
02580       case SIG_PRI_DEFLAW:
02581          newlaw = 0;
02582          break;
02583       case SIG_PRI_ALAW:
02584          newlaw = DAHDI_LAW_ALAW;
02585          break;
02586       case SIG_PRI_ULAW:
02587          newlaw = DAHDI_LAW_MULAW;
02588          break;
02589    }
02590    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02591 }
02592 #endif   /* defined(HAVE_PRI) */
02593 
02594 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02595 
02596 #if defined(HAVE_PRI)
02597 /*!
02598  * \internal
02599  * \brief Open the PRI channel media path.
02600  * \since 1.8
02601  *
02602  * \param p Channel private control structure.
02603  *
02604  * \return Nothing
02605  */
02606 static void my_pri_open_media(void *p)
02607 {
02608    struct dahdi_pvt *pvt = p;
02609    int res;
02610    int dfd;
02611    int set_val;
02612 
02613    dfd = pvt->subs[SUB_REAL].dfd;
02614 
02615    /* Open the media path. */
02616    set_val = 1;
02617    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02618    if (res < 0) {
02619       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02620          pvt->channel, strerror(errno));
02621    }
02622 
02623    /* Set correct companding law for this call. */
02624    res = dahdi_setlaw(dfd, pvt->law);
02625    if (res < 0) {
02626       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02627    }
02628 
02629    /* Set correct gain for this call. */
02630    if (pvt->digital) {
02631       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02632    } else {
02633       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02634          pvt->law);
02635    }
02636    if (res < 0) {
02637       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02638    }
02639 
02640    if (pvt->dsp_features && pvt->dsp) {
02641       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02642       pvt->dsp_features = 0;
02643    }
02644 }
02645 #endif   /* defined(HAVE_PRI) */
02646 
02647 static int unalloc_sub(struct dahdi_pvt *p, int x);
02648 
02649 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02650 {
02651    struct dahdi_pvt *p = pvt;
02652 
02653    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02654 }
02655 
02656 static int alloc_sub(struct dahdi_pvt *p, int x);
02657 
02658 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02659 {
02660    struct dahdi_pvt *p = pvt;
02661 
02662    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02663 }
02664 
02665 static int has_voicemail(struct dahdi_pvt *p);
02666 
02667 static int my_has_voicemail(void *pvt)
02668 {
02669    struct dahdi_pvt *p = pvt;
02670 
02671    return has_voicemail(p);
02672 }
02673 
02674 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02675 {
02676    struct dahdi_pvt *p = pvt;
02677    int index;
02678 
02679    index = analogsub_to_dahdisub(sub);
02680 
02681    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02682 }
02683 
02684 static enum analog_event dahdievent_to_analogevent(int event)
02685 {
02686    enum analog_event res;
02687 
02688    switch (event) {
02689    case DAHDI_EVENT_ONHOOK:
02690       res = ANALOG_EVENT_ONHOOK;
02691       break;
02692    case DAHDI_EVENT_RINGOFFHOOK:
02693       res = ANALOG_EVENT_RINGOFFHOOK;
02694       break;
02695    case DAHDI_EVENT_WINKFLASH:
02696       res = ANALOG_EVENT_WINKFLASH;
02697       break;
02698    case DAHDI_EVENT_ALARM:
02699       res = ANALOG_EVENT_ALARM;
02700       break;
02701    case DAHDI_EVENT_NOALARM:
02702       res = ANALOG_EVENT_NOALARM;
02703       break;
02704    case DAHDI_EVENT_DIALCOMPLETE:
02705       res = ANALOG_EVENT_DIALCOMPLETE;
02706       break;
02707    case DAHDI_EVENT_RINGERON:
02708       res = ANALOG_EVENT_RINGERON;
02709       break;
02710    case DAHDI_EVENT_RINGEROFF:
02711       res = ANALOG_EVENT_RINGEROFF;
02712       break;
02713    case DAHDI_EVENT_HOOKCOMPLETE:
02714       res = ANALOG_EVENT_HOOKCOMPLETE;
02715       break;
02716    case DAHDI_EVENT_PULSE_START:
02717       res = ANALOG_EVENT_PULSE_START;
02718       break;
02719    case DAHDI_EVENT_POLARITY:
02720       res = ANALOG_EVENT_POLARITY;
02721       break;
02722    case DAHDI_EVENT_RINGBEGIN:
02723       res = ANALOG_EVENT_RINGBEGIN;
02724       break;
02725    case DAHDI_EVENT_EC_DISABLED:
02726       res = ANALOG_EVENT_EC_DISABLED;
02727       break;
02728    case DAHDI_EVENT_REMOVED:
02729       res = ANALOG_EVENT_REMOVED;
02730       break;
02731    case DAHDI_EVENT_NEONMWI_ACTIVE:
02732       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02733       break;
02734    case DAHDI_EVENT_NEONMWI_INACTIVE:
02735       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02736       break;
02737 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02738    case DAHDI_EVENT_TX_CED_DETECTED:
02739       res = ANALOG_EVENT_TX_CED_DETECTED;
02740       break;
02741    case DAHDI_EVENT_RX_CED_DETECTED:
02742       res = ANALOG_EVENT_RX_CED_DETECTED;
02743       break;
02744    case DAHDI_EVENT_EC_NLP_DISABLED:
02745       res = ANALOG_EVENT_EC_NLP_DISABLED;
02746       break;
02747    case DAHDI_EVENT_EC_NLP_ENABLED:
02748       res = ANALOG_EVENT_EC_NLP_ENABLED;
02749       break;
02750 #endif
02751    case DAHDI_EVENT_PULSEDIGIT:
02752       res = ANALOG_EVENT_PULSEDIGIT;
02753       break;
02754    case DAHDI_EVENT_DTMFDOWN:
02755       res = ANALOG_EVENT_DTMFDOWN;
02756       break;
02757    case DAHDI_EVENT_DTMFUP:
02758       res = ANALOG_EVENT_DTMFUP;
02759       break;
02760    default:
02761       switch(event & 0xFFFF0000) {
02762       case DAHDI_EVENT_PULSEDIGIT:
02763       case DAHDI_EVENT_DTMFDOWN:
02764       case DAHDI_EVENT_DTMFUP:
02765          /* The event includes a digit number in the low word.
02766           * Converting it to a 'enum analog_event' would remove
02767           * that information. Thus it is returned as-is.
02768           */
02769          return event;
02770       }
02771 
02772       res = ANALOG_EVENT_ERROR;
02773       break;
02774    }
02775 
02776    return res;
02777 }
02778 
02779 static inline int dahdi_wait_event(int fd);
02780 
02781 static int my_wait_event(void *pvt)
02782 {
02783    struct dahdi_pvt *p = pvt;
02784 
02785    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02786 }
02787 
02788 static int my_get_event(void *pvt)
02789 {
02790    struct dahdi_pvt *p = pvt;
02791    int res;
02792 
02793    if (p->fake_event) {
02794       res = p->fake_event;
02795       p->fake_event = 0;
02796    } else
02797       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02798 
02799    return dahdievent_to_analogevent(res);
02800 }
02801 
02802 static int my_is_off_hook(void *pvt)
02803 {
02804    struct dahdi_pvt *p = pvt;
02805    int res;
02806    struct dahdi_params par;
02807 
02808    memset(&par, 0, sizeof(par));
02809 
02810    if (p->subs[SUB_REAL].dfd > -1)
02811       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02812    else {
02813       /* Assume not off hook on CVRS */
02814       res = 0;
02815       par.rxisoffhook = 0;
02816    }
02817    if (res) {
02818       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02819    }
02820 
02821    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02822       /* When "onhook" that means no battery on the line, and thus
02823       it is out of service..., if it's on a TDM card... If it's a channel
02824       bank, there is no telling... */
02825       return (par.rxbits > -1) || par.rxisoffhook;
02826    }
02827 
02828    return par.rxisoffhook;
02829 }
02830 
02831 static void dahdi_enable_ec(struct dahdi_pvt *p);
02832 static void dahdi_disable_ec(struct dahdi_pvt *p);
02833 
02834 static int my_set_echocanceller(void *pvt, int enable)
02835 {
02836    struct dahdi_pvt *p = pvt;
02837 
02838    if (enable)
02839       dahdi_enable_ec(p);
02840    else
02841       dahdi_disable_ec(p);
02842 
02843    return 0;
02844 }
02845 
02846 static int dahdi_ring_phone(struct dahdi_pvt *p);
02847 
02848 static int my_ring(void *pvt)
02849 {
02850    struct dahdi_pvt *p = pvt;
02851 
02852    return dahdi_ring_phone(p);
02853 }
02854 
02855 static int my_flash(void *pvt)
02856 {
02857    struct dahdi_pvt *p = pvt;
02858    int func = DAHDI_FLASH;
02859    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02860 }
02861 
02862 static inline int dahdi_set_hook(int fd, int hs);
02863 
02864 static int my_off_hook(void *pvt)
02865 {
02866    struct dahdi_pvt *p = pvt;
02867    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02868 }
02869 
02870 static void my_set_needringing(void *pvt, int value)
02871 {
02872    struct dahdi_pvt *p = pvt;
02873    p->subs[SUB_REAL].needringing = value;
02874 }
02875 
02876 static void my_set_polarity(void *pvt, int value)
02877 {
02878    struct dahdi_pvt *p = pvt;
02879 
02880    if (p->channel == CHAN_PSEUDO) {
02881       return;
02882    }
02883    p->polarity = value;
02884    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02885 }
02886 
02887 static void my_start_polarityswitch(void *pvt)
02888 {
02889    struct dahdi_pvt *p = pvt;
02890 
02891    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02892       my_set_polarity(pvt, 0);
02893    }
02894 }
02895 
02896 static void my_answer_polarityswitch(void *pvt)
02897 {
02898    struct dahdi_pvt *p = pvt;
02899 
02900    if (!p->answeronpolarityswitch) {
02901       return;
02902    }
02903 
02904    my_set_polarity(pvt, 1);
02905 }
02906 
02907 static void my_hangup_polarityswitch(void *pvt)
02908 {
02909    struct dahdi_pvt *p = pvt;
02910 
02911    if (!p->hanguponpolarityswitch) {
02912       return;
02913    }
02914 
02915    if (p->answeronpolarityswitch) {
02916       my_set_polarity(pvt, 0);
02917    } else {
02918       my_set_polarity(pvt, 1);
02919    }
02920 }
02921 
02922 static int my_start(void *pvt)
02923 {
02924    struct dahdi_pvt *p = pvt;
02925    int x = DAHDI_START;
02926 
02927    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02928 }
02929 
02930 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02931 {
02932    int index = analogsub_to_dahdisub(sub);
02933    int res;
02934    struct dahdi_pvt *p = pvt;
02935    struct dahdi_dialoperation ddop;
02936 
02937    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02938       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02939       return -1;
02940    }
02941 
02942    if (sub != ANALOG_SUB_REAL) {
02943       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02944          dop->dialstr, p->channel, sub);
02945       return -1;
02946    }
02947 
02948    ddop.op = DAHDI_DIAL_OP_REPLACE;
02949    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02950 
02951    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02952 
02953    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02954    if (res == -1) {
02955       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02956    }
02957 
02958    return res;
02959 }
02960 
02961 static void dahdi_train_ec(struct dahdi_pvt *p);
02962 
02963 static int my_train_echocanceller(void *pvt)
02964 {
02965    struct dahdi_pvt *p = pvt;
02966 
02967    dahdi_train_ec(p);
02968 
02969    return 0;
02970 }
02971 
02972 static int my_is_dialing(void *pvt, enum analog_sub sub)
02973 {
02974    struct dahdi_pvt *p = pvt;
02975    int index;
02976    int x;
02977 
02978    index = analogsub_to_dahdisub(sub);
02979 
02980    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02981       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02982       return -1;
02983    }
02984 
02985    return x;
02986 }
02987 
02988 static int my_on_hook(void *pvt)
02989 {
02990    struct dahdi_pvt *p = pvt;
02991    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02992 }
02993 
02994 #if defined(HAVE_PRI)
02995 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02996 {
02997    struct dahdi_pvt *old_chan = chan_old;
02998    struct dahdi_pvt *new_chan = chan_new;
02999 
03000    new_chan->owner = old_chan->owner;
03001    old_chan->owner = NULL;
03002    if (new_chan->owner) {
03003       new_chan->owner->tech_pvt = new_chan;
03004       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03005       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03006       old_chan->subs[SUB_REAL].owner = NULL;
03007    }
03008    /* Copy any DSP that may be present */
03009    new_chan->dsp = old_chan->dsp;
03010    new_chan->dsp_features = old_chan->dsp_features;
03011    old_chan->dsp = NULL;
03012    old_chan->dsp_features = 0;
03013 
03014    /* Transfer flags from the old channel. */
03015    new_chan->dialing = old_chan->dialing;
03016    new_chan->digital = old_chan->digital;
03017    new_chan->outgoing = old_chan->outgoing;
03018    old_chan->dialing = 0;
03019    old_chan->digital = 0;
03020    old_chan->outgoing = 0;
03021 
03022    /* More stuff to transfer to the new channel. */
03023    new_chan->law = old_chan->law;
03024    strcpy(new_chan->dialstring, old_chan->dialstring);
03025 }
03026 #endif   /* defined(HAVE_PRI) */
03027 
03028 #if defined(HAVE_PRI)
03029 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03030 {
03031    switch (tone) {
03032    case SIG_PRI_TONE_RINGTONE:
03033       return DAHDI_TONE_RINGTONE;
03034    case SIG_PRI_TONE_STUTTER:
03035       return DAHDI_TONE_STUTTER;
03036    case SIG_PRI_TONE_CONGESTION:
03037       return DAHDI_TONE_CONGESTION;
03038    case SIG_PRI_TONE_DIALTONE:
03039       return DAHDI_TONE_DIALTONE;
03040    case SIG_PRI_TONE_DIALRECALL:
03041       return DAHDI_TONE_DIALRECALL;
03042    case SIG_PRI_TONE_INFO:
03043       return DAHDI_TONE_INFO;
03044    case SIG_PRI_TONE_BUSY:
03045       return DAHDI_TONE_BUSY;
03046    default:
03047       return -1;
03048    }
03049 }
03050 #endif   /* defined(HAVE_PRI) */
03051 
03052 #if defined(HAVE_PRI)
03053 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03054 {
03055    int x;
03056 
03057    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03058    if (x) {
03059       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03060    }
03061    /* Keep track of alarm state */
03062    switch (x) {
03063    case DAHDI_EVENT_ALARM:
03064       pri_event_alarm(pri, index, 0);
03065       break;
03066    case DAHDI_EVENT_NOALARM:
03067       pri_event_noalarm(pri, index, 0);
03068       break;
03069    default:
03070       break;
03071    }
03072 }
03073 #endif   /* defined(HAVE_PRI) */
03074 
03075 #if defined(HAVE_PRI)
03076 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03077 {
03078    struct dahdi_pvt *p = pvt;
03079 
03080    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03081 }
03082 #endif   /* defined(HAVE_PRI) */
03083 
03084 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03085 /*!
03086  * \internal
03087  * \brief Set the caller id information.
03088  * \since 1.8
03089  *
03090  * \param pvt DAHDI private structure
03091  * \param caller Caller-id information to set.
03092  *
03093  * \return Nothing
03094  */
03095 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03096 {
03097    struct dahdi_pvt *p = pvt;
03098 
03099    ast_copy_string(p->cid_num,
03100       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03101       sizeof(p->cid_num));
03102    ast_copy_string(p->cid_name,
03103       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03104       sizeof(p->cid_name));
03105    ast_copy_string(p->cid_subaddr,
03106       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03107       sizeof(p->cid_subaddr));
03108    p->cid_ton = caller->id.number.plan;
03109    p->callingpres = ast_party_id_presentation(&caller->id);
03110    if (caller->id.tag) {
03111       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03112    }
03113    ast_copy_string(p->cid_ani,
03114       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03115       sizeof(p->cid_ani));
03116    p->cid_ani2 = caller->ani2;
03117 }
03118 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03119 
03120 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03121 /*!
03122  * \internal
03123  * \brief Set the Dialed Number Identifier.
03124  * \since 1.8
03125  *
03126  * \param pvt DAHDI private structure
03127  * \param dnid Dialed Number Identifier string.
03128  *
03129  * \return Nothing
03130  */
03131 static void my_set_dnid(void *pvt, const char *dnid)
03132 {
03133    struct dahdi_pvt *p = pvt;
03134 
03135    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03136 }
03137 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03138 
03139 #if defined(HAVE_PRI)
03140 /*!
03141  * \internal
03142  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03143  * \since 1.8
03144  *
03145  * \param pvt DAHDI private structure
03146  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03147  *
03148  * \return Nothing
03149  */
03150 static void my_set_rdnis(void *pvt, const char *rdnis)
03151 {
03152    struct dahdi_pvt *p = pvt;
03153 
03154    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03155 }
03156 #endif   /* defined(HAVE_PRI) */
03157 
03158 #if defined(HAVE_PRI)
03159 /*!
03160  * \internal
03161  * \brief Make a dialstring for native ISDN CC to recall properly.
03162  * \since 1.8
03163  *
03164  * \param priv Channel private control structure.
03165  * \param buf Where to put the modified dialstring.
03166  * \param buf_size Size of modified dialstring buffer.
03167  *
03168  * \details
03169  * original dialstring:
03170  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03171  *
03172  * The modified dialstring will have prefixed the channel-group section
03173  * with the ISDN channel restriction.
03174  *
03175  * buf:
03176  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03177  *
03178  * The routine will check to see if the ISDN channel restriction is already
03179  * in the original dialstring.
03180  *
03181  * \return Nothing
03182  */
03183 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03184 {
03185    char *dial;
03186    struct dahdi_pvt *pvt;
03187    AST_DECLARE_APP_ARGS(args,
03188       AST_APP_ARG(tech);   /* channel technology token */
03189       AST_APP_ARG(group);  /* channel/group token */
03190       //AST_APP_ARG(ext);  /* extension token */
03191       //AST_APP_ARG(opts); /* options token */
03192       //AST_APP_ARG(other);   /* Any remining unused arguments */
03193    );
03194 
03195    pvt = priv;
03196    dial = ast_strdupa(pvt->dialstring);
03197    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03198    if (!args.tech) {
03199       ast_copy_string(buf, pvt->dialstring, buf_size);
03200       return;
03201    }
03202    if (!args.group) {
03203       /* Append the ISDN span channel restriction to the dialstring. */
03204       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03205       return;
03206    }
03207    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03208       /* The ISDN span channel restriction is not needed or already
03209        * in the dialstring. */
03210       ast_copy_string(buf, pvt->dialstring, buf_size);
03211       return;
03212    }
03213    /* Insert the ISDN span channel restriction into the dialstring. */
03214    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03215 }
03216 #endif   /* defined(HAVE_PRI) */
03217 
03218 #if defined(HAVE_PRI)
03219 /*!
03220  * \internal
03221  * \brief Reevaluate the PRI span device state.
03222  * \since 1.8
03223  *
03224  * \param pri Asterisk D channel control structure.
03225  *
03226  * \return Nothing
03227  *
03228  * \note Assumes the pri->lock is already obtained.
03229  */
03230 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03231 {
03232    unsigned idx;
03233    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03234    unsigned in_use;     /* Number of B channels in use on the span. */
03235    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03236    enum ast_device_state new_state;
03237 
03238    /* Count the number of B channels and the number of B channels in use. */
03239    num_b_chans = 0;
03240    in_use = 0;
03241    in_alarm = 1;
03242    for (idx = pri->numchans; idx--;) {
03243       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03244          /* This is a B channel interface. */
03245          ++num_b_chans;
03246          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03247             ++in_use;
03248          }
03249          if (!pri->pvts[idx]->inalarm) {
03250             /* There is a channel that is not in alarm. */
03251             in_alarm = 0;
03252          }
03253       }
03254    }
03255 
03256    /* Update the span congestion device state and report any change. */
03257    if (in_alarm) {
03258       new_state = AST_DEVICE_UNAVAILABLE;
03259    } else {
03260       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03261    }
03262    if (pri->congestion_devstate != new_state) {
03263       pri->congestion_devstate = new_state;
03264       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03265    }
03266 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03267    /* Update the span threshold device state and report any change. */
03268    if (in_alarm) {
03269       new_state = AST_DEVICE_UNAVAILABLE;
03270    } else if (!in_use) {
03271       new_state = AST_DEVICE_NOT_INUSE;
03272    } else if (!pri->user_busy_threshold) {
03273       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03274    } else {
03275       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03276          : AST_DEVICE_BUSY;
03277    }
03278    if (pri->threshold_devstate != new_state) {
03279       pri->threshold_devstate = new_state;
03280       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03281    }
03282 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03283 }
03284 #endif   /* defined(HAVE_PRI) */
03285 
03286 #if defined(HAVE_PRI)
03287 /*!
03288  * \internal
03289  * \brief Reference this module.
03290  * \since 1.8
03291  *
03292  * \return Nothing
03293  */
03294 static void my_module_ref(void)
03295 {
03296    ast_module_ref(ast_module_info->self);
03297 }
03298 #endif   /* defined(HAVE_PRI) */
03299 
03300 #if defined(HAVE_PRI)
03301 /*!
03302  * \internal
03303  * \brief Unreference this module.
03304  * \since 1.8
03305  *
03306  * \return Nothing
03307  */
03308 static void my_module_unref(void)
03309 {
03310    ast_module_unref(ast_module_info->self);
03311 }
03312 #endif   /* defined(HAVE_PRI) */
03313 
03314 #if defined(HAVE_PRI)
03315 #if defined(HAVE_PRI_CALL_WAITING)
03316 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03317 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03318 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03319 
03320 static struct sig_pri_callback dahdi_pri_callbacks =
03321 {
03322    .handle_dchan_exception = my_handle_dchan_exception,
03323    .play_tone = my_pri_play_tone,
03324    .set_echocanceller = my_set_echocanceller,
03325    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03326    .lock_private = my_lock_private,
03327    .unlock_private = my_unlock_private,
03328    .new_ast_channel = my_new_pri_ast_channel,
03329    .fixup_chans = my_pri_fixup_chans,
03330    .set_alarm = my_set_alarm,
03331    .set_dialing = my_set_dialing,
03332    .set_digital = my_set_digital,
03333    .set_callerid = my_set_callerid,
03334    .set_dnid = my_set_dnid,
03335    .set_rdnis = my_set_rdnis,
03336    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03337 #if defined(HAVE_PRI_CALL_WAITING)
03338    .init_config = my_pri_init_config,
03339 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03340    .get_orig_dialstring = my_get_orig_dialstring,
03341    .make_cc_dialstring = my_pri_make_cc_dialstring,
03342    .update_span_devstate = dahdi_pri_update_span_devstate,
03343    .module_ref = my_module_ref,
03344    .module_unref = my_module_unref,
03345    .open_media = my_pri_open_media,
03346    .ami_channel_event = my_ami_channel_event,
03347 };
03348 #endif   /* defined(HAVE_PRI) */
03349 
03350 #if defined(HAVE_SS7)
03351 /*!
03352  * \internal
03353  * \brief Handle the SS7 link exception.
03354  * \since 1.8
03355  *
03356  * \param linkset Controlling linkset for the channel.
03357  * \param which Link index of the signaling channel.
03358  *
03359  * \return Nothing
03360  */
03361 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03362 {
03363    int event;
03364 
03365    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03366       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03367          linkset->span, which);
03368       return;
03369    }
03370    switch (event) {
03371    case DAHDI_EVENT_NONE:
03372       break;
03373    case DAHDI_EVENT_ALARM:
03374       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03375          event2str(event), event, linkset->span, which);
03376       sig_ss7_link_alarm(linkset, which);
03377       break;
03378    case DAHDI_EVENT_NOALARM:
03379       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03380          event2str(event), event, linkset->span, which);
03381       sig_ss7_link_noalarm(linkset, which);
03382       break;
03383    default:
03384       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03385          event2str(event), event, linkset->span, which);
03386       break;
03387    }
03388 }
03389 #endif   /* defined(HAVE_SS7) */
03390 
03391 #if defined(HAVE_SS7)
03392 static void my_ss7_set_loopback(void *pvt, int enable)
03393 {
03394    struct dahdi_pvt *p = pvt;
03395 
03396    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03397       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03398          strerror(errno));
03399    }
03400 }
03401 #endif   /* defined(HAVE_SS7) */
03402 
03403 #if defined(HAVE_SS7)
03404 /*!
03405  * \internal
03406  * \brief Create a new asterisk channel structure for SS7.
03407  * \since 1.8
03408  *
03409  * \param pvt Private channel structure.
03410  * \param state Initial state of new channel.
03411  * \param law Combanding law to use.
03412  * \param exten Dialplan extension for incoming call.
03413  * \param requestor Channel requesting this new channel.
03414  *
03415  * \retval ast_channel on success.
03416  * \retval NULL on error.
03417  */
03418 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)
03419 {
03420    struct dahdi_pvt *p = pvt;
03421    int audio;
03422    int newlaw;
03423 
03424    /* Set to audio mode at this point */
03425    audio = 1;
03426    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03427       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03428          p->channel, audio, strerror(errno));
03429 
03430    if (law != SIG_SS7_DEFLAW) {
03431       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03432          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03433    }
03434 
03435    ast_copy_string(p->exten, exten, sizeof(p->exten));
03436 
03437    newlaw = -1;
03438    switch (law) {
03439    case SIG_SS7_DEFLAW:
03440       newlaw = 0;
03441       break;
03442    case SIG_SS7_ALAW:
03443       newlaw = DAHDI_LAW_ALAW;
03444       break;
03445    case SIG_SS7_ULAW:
03446       newlaw = DAHDI_LAW_MULAW;
03447       break;
03448    }
03449    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03450 }
03451 #endif   /* defined(HAVE_SS7) */
03452 
03453 #if defined(HAVE_SS7)
03454 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03455 {
03456    switch (tone) {
03457    case SIG_SS7_TONE_RINGTONE:
03458       return DAHDI_TONE_RINGTONE;
03459    case SIG_SS7_TONE_STUTTER:
03460       return DAHDI_TONE_STUTTER;
03461    case SIG_SS7_TONE_CONGESTION:
03462       return DAHDI_TONE_CONGESTION;
03463    case SIG_SS7_TONE_DIALTONE:
03464       return DAHDI_TONE_DIALTONE;
03465    case SIG_SS7_TONE_DIALRECALL:
03466       return DAHDI_TONE_DIALRECALL;
03467    case SIG_SS7_TONE_INFO:
03468       return DAHDI_TONE_INFO;
03469    case SIG_SS7_TONE_BUSY:
03470       return DAHDI_TONE_BUSY;
03471    default:
03472       return -1;
03473    }
03474 }
03475 #endif   /* defined(HAVE_SS7) */
03476 
03477 #if defined(HAVE_SS7)
03478 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03479 {
03480    struct dahdi_pvt *p = pvt;
03481 
03482    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03483 }
03484 #endif   /* defined(HAVE_SS7) */
03485 
03486 #if defined(HAVE_SS7)
03487 static struct sig_ss7_callback dahdi_ss7_callbacks =
03488 {
03489    .lock_private = my_lock_private,
03490    .unlock_private = my_unlock_private,
03491 
03492    .set_echocanceller = my_set_echocanceller,
03493    .set_loopback = my_ss7_set_loopback,
03494 
03495    .new_ast_channel = my_new_ss7_ast_channel,
03496    .play_tone = my_ss7_play_tone,
03497 
03498    .handle_link_exception = my_handle_link_exception,
03499    .set_alarm = my_set_alarm,
03500    .set_dialing = my_set_dialing,
03501    .set_digital = my_set_digital,
03502    .set_inservice = my_set_inservice,
03503    .set_locallyblocked = my_set_locallyblocked,
03504    .set_remotelyblocked = my_set_remotelyblocked,
03505    .set_callerid = my_set_callerid,
03506    .set_dnid = my_set_dnid,
03507 };
03508 #endif   /* defined(HAVE_SS7) */
03509 
03510 /*!
03511  * \brief Send MWI state change
03512  *
03513  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03514  *      MWI state has changed on.
03515  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03516  *      whether there are messages waiting or not.
03517  *
03518  *  \return nothing
03519  *
03520  * This function does two things:
03521  *
03522  * 1) It generates an internal Asterisk event notifying any other module that
03523  *    cares about MWI that the state of a mailbox has changed.
03524  *
03525  * 2) It runs the script specified by the mwimonitornotify option to allow
03526  *    some custom handling of the state change.
03527  */
03528 static void notify_message(char *mailbox_full, int thereornot)
03529 {
03530    char s[sizeof(mwimonitornotify) + 80];
03531    struct ast_event *event;
03532    char *mailbox, *context;
03533 
03534    /* Strip off @default */
03535    context = mailbox = ast_strdupa(mailbox_full);
03536    strsep(&context, "@");
03537    if (ast_strlen_zero(context))
03538       context = "default";
03539 
03540    if (!(event = ast_event_new(AST_EVENT_MWI,
03541          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03542          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03543          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03544          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03545          AST_EVENT_IE_END))) {
03546       return;
03547    }
03548 
03549    ast_event_queue_and_cache(event);
03550 
03551    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03552       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03553       ast_safe_system(s);
03554    }
03555 }
03556 
03557 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03558 {
03559    struct dahdi_pvt *p = pvt;
03560 
03561    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03562       return;
03563 
03564    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03565       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03566       notify_message(p->mailbox, 1);
03567    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03568       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03569       notify_message(p->mailbox, 0);
03570    }
03571    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03572    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03573    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03574       ast_hangup(chan);
03575       return;
03576    }
03577 }
03578 
03579 
03580 
03581 static struct analog_callback dahdi_analog_callbacks =
03582 {
03583    .play_tone = my_play_tone,
03584    .get_event = my_get_event,
03585    .wait_event = my_wait_event,
03586    .is_off_hook = my_is_off_hook,
03587    .set_echocanceller = my_set_echocanceller,
03588    .ring = my_ring,
03589    .flash = my_flash,
03590    .off_hook = my_off_hook,
03591    .dial_digits = my_dial_digits,
03592    .train_echocanceller = my_train_echocanceller,
03593    .on_hook = my_on_hook,
03594    .is_dialing = my_is_dialing,
03595    .allocate_sub = my_allocate_sub,
03596    .unallocate_sub = my_unallocate_sub,
03597    .swap_subs = my_swap_subchannels,
03598    .has_voicemail = my_has_voicemail,
03599    .check_for_conference = my_check_for_conference,
03600    .conf_add = my_conf_add,
03601    .conf_del = my_conf_del,
03602    .complete_conference_update = my_complete_conference_update,
03603    .start = my_start,
03604    .all_subchannels_hungup = my_all_subchannels_hungup,
03605    .lock_private = my_lock_private,
03606    .unlock_private = my_unlock_private,
03607    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03608    .handle_dtmf = my_handle_dtmf,
03609    .wink = my_wink,
03610    .new_ast_channel = my_new_analog_ast_channel,
03611    .dsp_set_digitmode = my_dsp_set_digitmode,
03612    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03613    .send_callerid = my_send_callerid,
03614    .callwait = my_callwait,
03615    .stop_callwait = my_stop_callwait,
03616    .get_callerid = my_get_callerid,
03617    .start_cid_detect = my_start_cid_detect,
03618    .stop_cid_detect = my_stop_cid_detect,
03619    .handle_notify_message = my_handle_notify_message,
03620    .increase_ss_count = my_increase_ss_count,
03621    .decrease_ss_count = my_decrease_ss_count,
03622    .distinctive_ring = my_distinctive_ring,
03623    .set_linear_mode = my_set_linear_mode,
03624    .set_inthreeway = my_set_inthreeway,
03625    .get_and_handle_alarms = my_get_and_handle_alarms,
03626    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03627    .get_sub_fd = my_get_sub_fd,
03628    .set_cadence = my_set_cadence,
03629    .set_alarm = my_set_alarm,
03630    .set_dialing = my_set_dialing,
03631    .set_ringtimeout = my_set_ringtimeout,
03632    .set_waitingfordt = my_set_waitingfordt,
03633    .check_waitingfordt = my_check_waitingfordt,
03634    .set_confirmanswer = my_set_confirmanswer,
03635    .check_confirmanswer = my_check_confirmanswer,
03636    .set_callwaiting = my_set_callwaiting,
03637    .cancel_cidspill = my_cancel_cidspill,
03638    .confmute = my_confmute,
03639    .set_pulsedial = my_set_pulsedial,
03640    .set_new_owner = my_set_new_owner,
03641    .get_orig_dialstring = my_get_orig_dialstring,
03642    .set_needringing = my_set_needringing,
03643    .set_polarity = my_set_polarity,
03644    .start_polarityswitch = my_start_polarityswitch,
03645    .answer_polarityswitch = my_answer_polarityswitch,
03646    .hangup_polarityswitch = my_hangup_polarityswitch,
03647 };
03648 
03649 /*! Round robin search locations. */
03650 static struct dahdi_pvt *round_robin[32];
03651 
03652 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03653 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03654 {
03655    int res;
03656    if (p->subs[SUB_REAL].owner == ast)
03657       res = 0;
03658    else if (p->subs[SUB_CALLWAIT].owner == ast)
03659       res = 1;
03660    else if (p->subs[SUB_THREEWAY].owner == ast)
03661       res = 2;
03662    else {
03663       res = -1;
03664       if (!nullok)
03665          ast_log(LOG_WARNING,
03666             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03667             ast ? ast->name : "", p->channel, fname, line);
03668    }
03669    return res;
03670 }
03671 
03672 /*!
03673  * \internal
03674  * \brief Obtain the specified subchannel owner lock if the owner exists.
03675  *
03676  * \param pvt Channel private struct.
03677  * \param sub_idx Subchannel owner to lock.
03678  *
03679  * \note Assumes the pvt->lock is already obtained.
03680  *
03681  * \note
03682  * Because deadlock avoidance may have been necessary, you need to confirm
03683  * the state of things before continuing.
03684  *
03685  * \return Nothing
03686  */
03687 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03688 {
03689    for (;;) {
03690       if (!pvt->subs[sub_idx].owner) {
03691          /* No subchannel owner pointer */
03692          break;
03693       }
03694       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03695          /* Got subchannel owner lock */
03696          break;
03697       }
03698       /* We must unlock the private to avoid the possibility of a deadlock */
03699       DEADLOCK_AVOIDANCE(&pvt->lock);
03700    }
03701 }
03702 
03703 static void wakeup_sub(struct dahdi_pvt *p, int a)
03704 {
03705    dahdi_lock_sub_owner(p, a);
03706    if (p->subs[a].owner) {
03707       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03708       ast_channel_unlock(p->subs[a].owner);
03709    }
03710 }
03711 
03712 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03713 {
03714    for (;;) {
03715       if (p->owner) {
03716          if (ast_channel_trylock(p->owner)) {
03717             DEADLOCK_AVOIDANCE(&p->lock);
03718          } else {
03719             ast_queue_frame(p->owner, f);
03720             ast_channel_unlock(p->owner);
03721             break;
03722          }
03723       } else
03724          break;
03725    }
03726 }
03727 
03728 static void handle_clear_alarms(struct dahdi_pvt *p)
03729 {
03730    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03731       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03732       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03733    }
03734    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03735       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03736       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03737    }
03738 }
03739 
03740 #ifdef HAVE_OPENR2
03741 
03742 static int dahdi_r2_answer(struct dahdi_pvt *p)
03743 {
03744    int res = 0;
03745    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03746    * and does not has support for openr2_chan_answer_call_with_mode
03747    *  */
03748 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03749    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03750    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03751    if (!double_answer) {
03752       /* this still can result in double answer if the channel context
03753       * was configured that way */
03754       res = openr2_chan_answer_call(p->r2chan);
03755    } else if (wants_double_answer) {
03756       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03757    } else {
03758       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03759    }
03760 #else
03761    res = openr2_chan_answer_call(p->r2chan);
03762 #endif
03763    return res;
03764 }
03765 
03766 
03767 
03768 /* should be called with the ast_channel locked */
03769 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03770 {
03771    openr2_calling_party_category_t cat;
03772    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03773    struct dahdi_pvt *p = c->tech_pvt;
03774    if (ast_strlen_zero(catstr)) {
03775       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03776             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03777       return p->mfcr2_category;
03778    }
03779    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03780       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03781             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03782       return p->mfcr2_category;
03783    }
03784    ast_debug(1, "Using category %s\n", catstr);
03785    return cat;
03786 }
03787 
03788 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03789 {
03790    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03791    ast_mutex_lock(&p->lock);
03792    if (p->mfcr2call) {
03793       ast_mutex_unlock(&p->lock);
03794       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03795          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03796          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03797          the other end will see our seize as a forced release and drop the call, we will see an invalid
03798          pattern that will be seen and treated as protocol error. */
03799       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03800       return;
03801    }
03802    p->mfcr2call = 1;
03803    /* better safe than sorry ... */
03804    p->cid_name[0] = '\0';
03805    p->cid_num[0] = '\0';
03806    p->cid_subaddr[0] = '\0';
03807    p->rdnis[0] = '\0';
03808    p->exten[0] = '\0';
03809    p->mfcr2_ani_index = '\0';
03810    p->mfcr2_dnis_index = '\0';
03811    p->mfcr2_dnis_matched = 0;
03812    p->mfcr2_answer_pending = 0;
03813    p->mfcr2_call_accepted = 0;
03814    ast_mutex_unlock(&p->lock);
03815    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03816 }
03817 
03818 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03819 {
03820    int res;
03821    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03822    ast_mutex_lock(&p->lock);
03823    p->inalarm = alarm ? 1 : 0;
03824    if (p->inalarm) {
03825       res = get_alarms(p);
03826       handle_alarms(p, res);
03827    } else {
03828       handle_clear_alarms(p);
03829    }
03830    ast_mutex_unlock(&p->lock);
03831 }
03832 
03833 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03834 {
03835    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03836 }
03837 
03838 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03839 {
03840    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03841    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03842    if (p->owner) {
03843       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03844       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03845    }
03846    ast_mutex_lock(&p->lock);
03847    p->mfcr2call = 0;
03848    ast_mutex_unlock(&p->lock);
03849 }
03850 
03851 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03852 {
03853    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03854       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03855          p->channel, openr2_proto_get_disconnect_string(cause));
03856       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03857       openr2_chan_set_idle(p->r2chan);
03858       ast_mutex_lock(&p->lock);
03859       p->mfcr2call = 0;
03860       ast_mutex_unlock(&p->lock);
03861    }
03862 }
03863 
03864 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03865 {
03866    struct dahdi_pvt *p;
03867    struct ast_channel *c;
03868    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03869          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03870          openr2_proto_get_category_string(category));
03871    p = openr2_chan_get_client_data(r2chan);
03872    /* if collect calls are not allowed and this is a collect call, reject it! */
03873    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03874       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03875       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03876       return;
03877    }
03878    ast_mutex_lock(&p->lock);
03879    p->mfcr2_recvd_category = category;
03880    /* if we're not supposed to use CID, clear whatever we have */
03881    if (!p->use_callerid) {
03882       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03883       p->cid_num[0] = 0;
03884       p->cid_name[0] = 0;
03885    }
03886    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03887    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03888       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03889       p->exten[0] = 's';
03890       p->exten[1] = 0;
03891    }
03892    ast_mutex_unlock(&p->lock);
03893    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03894       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03895             p->channel, p->exten, p->context);
03896       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03897       return;
03898    }
03899    if (!p->mfcr2_accept_on_offer) {
03900       /* The user wants us to start the PBX thread right away without accepting the call first */
03901       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03902       if (c) {
03903          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03904             the call or reject it and detect the tone off condition of the other end, all of this
03905             will be done in the PBX thread now */
03906          return;
03907       }
03908       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03909       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03910    } else if (p->mfcr2_charge_calls) {
03911       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03912       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03913    } else {
03914       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03915       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03916    }
03917 }
03918 
03919 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03920 {
03921    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03922    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03923    ast_mutex_lock(&p->lock);
03924    p->mfcr2call = 0;
03925    ast_mutex_unlock(&p->lock);
03926 }
03927 
03928 static void dahdi_enable_ec(struct dahdi_pvt *p);
03929 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03930 {
03931    struct dahdi_pvt *p = NULL;
03932    struct ast_channel *c = NULL;
03933    p = openr2_chan_get_client_data(r2chan);
03934    dahdi_enable_ec(p);
03935    p->mfcr2_call_accepted = 1;
03936    /* if it's an incoming call ... */
03937    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03938       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03939       /* If accept on offer is not set, it means at this point the PBX thread is already
03940          launched (was launched in the 'on call offered' handler) and therefore this callback
03941          is being executed already in the PBX thread rather than the monitor thread, don't launch
03942          any other thread, just disable the openr2 reading and answer the call if needed */
03943       if (!p->mfcr2_accept_on_offer) {
03944          openr2_chan_disable_read(r2chan);
03945          if (p->mfcr2_answer_pending) {
03946             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03947             dahdi_r2_answer(p);
03948          }
03949          return;
03950       }
03951       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03952       if (c) {
03953          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03954             library to forget about it */
03955          openr2_chan_disable_read(r2chan);
03956          return;
03957       }
03958       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03959       /* failed to create the channel, bail out and report it as an out of order line */
03960       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03961       return;
03962    }
03963    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03964    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03965    p->subs[SUB_REAL].needringing = 1;
03966    p->dialing = 0;
03967    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
03968    openr2_chan_disable_read(r2chan);
03969 }
03970 
03971 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03972 {
03973    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03974    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03975    p->subs[SUB_REAL].needanswer = 1;
03976 }
03977 
03978 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03979 {
03980    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
03981 }
03982 
03983 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03984 {
03985    switch (cause) {
03986    case OR2_CAUSE_BUSY_NUMBER:
03987       return AST_CAUSE_BUSY;
03988    case OR2_CAUSE_NETWORK_CONGESTION:
03989       return AST_CAUSE_CONGESTION;
03990    case OR2_CAUSE_OUT_OF_ORDER:
03991       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03992    case OR2_CAUSE_UNALLOCATED_NUMBER:
03993       return AST_CAUSE_UNREGISTERED;
03994    case OR2_CAUSE_NO_ANSWER:
03995       return AST_CAUSE_NO_ANSWER;
03996    case OR2_CAUSE_NORMAL_CLEARING:
03997       return AST_CAUSE_NORMAL_CLEARING;
03998    case OR2_CAUSE_UNSPECIFIED:
03999    default:
04000       return AST_CAUSE_NOTDEFINED;
04001    }
04002 }
04003 
04004 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04005 {
04006    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04007    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04008    ast_mutex_lock(&p->lock);
04009    if (!p->owner) {
04010       ast_mutex_unlock(&p->lock);
04011       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04012       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04013       return;
04014    }
04015    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04016       be done in dahdi_hangup */
04017    if (p->owner->_state == AST_STATE_UP) {
04018       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04019       ast_mutex_unlock(&p->lock);
04020    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04021       /* being the forward side we must report what happened to the call to whoever requested it */
04022       switch (cause) {
04023       case OR2_CAUSE_BUSY_NUMBER:
04024          p->subs[SUB_REAL].needbusy = 1;
04025          break;
04026       case OR2_CAUSE_NETWORK_CONGESTION:
04027       case OR2_CAUSE_OUT_OF_ORDER:
04028       case OR2_CAUSE_UNALLOCATED_NUMBER:
04029       case OR2_CAUSE_NO_ANSWER:
04030       case OR2_CAUSE_UNSPECIFIED:
04031       case OR2_CAUSE_NORMAL_CLEARING:
04032          p->subs[SUB_REAL].needcongestion = 1;
04033          break;
04034       default:
04035          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04036       }
04037       ast_mutex_unlock(&p->lock);
04038    } else {
04039       ast_mutex_unlock(&p->lock);
04040       /* being the backward side and not UP yet, we only need to request hangup */
04041       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04042       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04043    }
04044 }
04045 
04046 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04047 {
04048    switch (level) {
04049    case OR2_LOG_NOTICE:
04050       ast_verbose("%s", logmessage);
04051       break;
04052    case OR2_LOG_WARNING:
04053       ast_log(LOG_WARNING, "%s", logmessage);
04054       break;
04055    case OR2_LOG_ERROR:
04056       ast_log(LOG_ERROR, "%s", logmessage);
04057       break;
04058    case OR2_LOG_STACK_TRACE:
04059    case OR2_LOG_MF_TRACE:
04060    case OR2_LOG_CAS_TRACE:
04061    case OR2_LOG_DEBUG:
04062    case OR2_LOG_EX_DEBUG:
04063       ast_log(LOG_DEBUG, "%s", logmessage);
04064       break;
04065    default:
04066       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04067       ast_log(LOG_DEBUG, "%s", logmessage);
04068       break;
04069    }
04070 }
04071 
04072 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04073 {
04074    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04075    ast_mutex_lock(&p->lock);
04076    p->remotelyblocked = 1;
04077    ast_mutex_unlock(&p->lock);
04078    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04079 }
04080 
04081 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04082 {
04083    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04084    ast_mutex_lock(&p->lock);
04085    p->remotelyblocked = 0;
04086    ast_mutex_unlock(&p->lock);
04087    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04088 }
04089 
04090 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04091    __attribute__((format (printf, 3, 0)));
04092 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04093 {
04094 #define CONTEXT_TAG "Context - "
04095    char logmsg[256];
04096    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04097    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04098    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04099    dahdi_r2_write_log(level, completemsg);
04100 #undef CONTEXT_TAG
04101 }
04102 
04103 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04104    __attribute__((format (printf, 3, 0)));
04105 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04106 {
04107 #define CHAN_TAG "Chan "
04108    char logmsg[256];
04109    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04110    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04111    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04112    dahdi_r2_write_log(level, completemsg);
04113 }
04114 
04115 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04116 {
04117    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04118    /* if 'immediate' is set, let's stop requesting DNIS */
04119    if (p->immediate) {
04120       return 0;
04121    }
04122    p->exten[p->mfcr2_dnis_index] = digit;
04123    p->rdnis[p->mfcr2_dnis_index] = digit;
04124    p->mfcr2_dnis_index++;
04125    p->exten[p->mfcr2_dnis_index] = 0;
04126    p->rdnis[p->mfcr2_dnis_index] = 0;
04127    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04128    if ((p->mfcr2_dnis_matched ||
04129        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04130        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04131       return 0;
04132    }
04133    /* otherwise keep going */
04134    return 1;
04135 }
04136 
04137 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04138 {
04139    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04140    p->cid_num[p->mfcr2_ani_index] = digit;
04141    p->cid_name[p->mfcr2_ani_index] = digit;
04142    p->mfcr2_ani_index++;
04143    p->cid_num[p->mfcr2_ani_index] = 0;
04144    p->cid_name[p->mfcr2_ani_index] = 0;
04145 }
04146 
04147 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04148 {
04149    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04150 }
04151 
04152 static openr2_event_interface_t dahdi_r2_event_iface = {
04153    .on_call_init = dahdi_r2_on_call_init,
04154    .on_call_offered = dahdi_r2_on_call_offered,
04155    .on_call_accepted = dahdi_r2_on_call_accepted,
04156    .on_call_answered = dahdi_r2_on_call_answered,
04157    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04158    .on_call_end = dahdi_r2_on_call_end,
04159    .on_call_read = dahdi_r2_on_call_read,
04160    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04161    .on_os_error = dahdi_r2_on_os_error,
04162    .on_protocol_error = dahdi_r2_on_protocol_error,
04163    .on_line_blocked = dahdi_r2_on_line_blocked,
04164    .on_line_idle = dahdi_r2_on_line_idle,
04165    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04166    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04167    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04168    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04169    /* so far we do nothing with billing pulses */
04170    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04171 };
04172 
04173 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04174 {
04175    return AST_ALAW(sample);
04176 }
04177 
04178 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04179 {
04180    return AST_LIN2A(sample);
04181 }
04182 
04183 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04184    dahdi_r2_alaw_to_linear,
04185    dahdi_r2_linear_to_alaw
04186 };
04187 
04188 #endif /* HAVE_OPENR2 */
04189 
04190 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04191 {
04192    int tchan;
04193    int tinthreeway;
04194    struct ast_channel *towner;
04195 
04196    ast_debug(1, "Swapping %d and %d\n", a, b);
04197 
04198    tchan = p->subs[a].chan;
04199    towner = p->subs[a].owner;
04200    tinthreeway = p->subs[a].inthreeway;
04201 
04202    p->subs[a].chan = p->subs[b].chan;
04203    p->subs[a].owner = p->subs[b].owner;
04204    p->subs[a].inthreeway = p->subs[b].inthreeway;
04205 
04206    p->subs[b].chan = tchan;
04207    p->subs[b].owner = towner;
04208    p->subs[b].inthreeway = tinthreeway;
04209 
04210    if (p->subs[a].owner)
04211       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04212    if (p->subs[b].owner)
04213       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04214    wakeup_sub(p, a);
04215    wakeup_sub(p, b);
04216 }
04217 
04218 static int dahdi_open(char *fn)
04219 {
04220    int fd;
04221    int isnum;
04222    int chan = 0;
04223    int bs;
04224    int x;
04225    isnum = 1;
04226    for (x = 0; x < strlen(fn); x++) {
04227       if (!isdigit(fn[x])) {
04228          isnum = 0;
04229          break;
04230       }
04231    }
04232    if (isnum) {
04233       chan = atoi(fn);
04234       if (chan < 1) {
04235          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04236          return -1;
04237       }
04238       fn = "/dev/dahdi/channel";
04239    }
04240    fd = open(fn, O_RDWR | O_NONBLOCK);
04241    if (fd < 0) {
04242       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04243       return -1;
04244    }
04245    if (chan) {
04246       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04247          x = errno;
04248          close(fd);
04249          errno = x;
04250          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04251          return -1;
04252       }
04253    }
04254    bs = READ_SIZE;
04255    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04256       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04257       x = errno;
04258       close(fd);
04259       errno = x;
04260       return -1;
04261    }
04262    return fd;
04263 }
04264 
04265 static void dahdi_close(int fd)
04266 {
04267    if (fd > 0)
04268       close(fd);
04269 }
04270 
04271 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04272 {
04273    dahdi_close(chan_pvt->subs[sub_num].dfd);
04274    chan_pvt->subs[sub_num].dfd = -1;
04275 }
04276 
04277 #if defined(HAVE_PRI)
04278 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04279 {
04280    dahdi_close(pri->pri.fds[fd_num]);
04281    pri->pri.fds[fd_num] = -1;
04282 }
04283 #endif   /* defined(HAVE_PRI) */
04284 
04285 #if defined(HAVE_SS7)
04286 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04287 {
04288    dahdi_close(ss7->ss7.fds[fd_num]);
04289    ss7->ss7.fds[fd_num] = -1;
04290 }
04291 #endif   /* defined(HAVE_SS7) */
04292 
04293 static int dahdi_setlinear(int dfd, int linear)
04294 {
04295    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04296 }
04297 
04298 
04299 static int alloc_sub(struct dahdi_pvt *p, int x)
04300 {
04301    struct dahdi_bufferinfo bi;
04302    int res;
04303    if (p->subs[x].dfd >= 0) {
04304       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04305       return -1;
04306    }
04307 
04308    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04309    if (p->subs[x].dfd <= -1) {
04310       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04311       return -1;
04312    }
04313 
04314    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04315    if (!res) {
04316       bi.txbufpolicy = p->buf_policy;
04317       bi.rxbufpolicy = p->buf_policy;
04318       bi.numbufs = p->buf_no;
04319       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04320       if (res < 0) {
04321          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04322       }
04323    } else
04324       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04325 
04326    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04327       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04328       dahdi_close_sub(p, x);
04329       p->subs[x].dfd = -1;
04330       return -1;
04331    }
04332    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04333    return 0;
04334 }
04335 
04336 static int unalloc_sub(struct dahdi_pvt *p, int x)
04337 {
04338    if (!x) {
04339       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04340       return -1;
04341    }
04342    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04343    dahdi_close_sub(p, x);
04344    p->subs[x].linear = 0;
04345    p->subs[x].chan = 0;
04346    p->subs[x].owner = NULL;
04347    p->subs[x].inthreeway = 0;
04348    p->polarity = POLARITY_IDLE;
04349    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04350    return 0;
04351 }
04352 
04353 static int digit_to_dtmfindex(char digit)
04354 {
04355    if (isdigit(digit))
04356       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04357    else if (digit >= 'A' && digit <= 'D')
04358       return DAHDI_TONE_DTMF_A + (digit - 'A');
04359    else if (digit >= 'a' && digit <= 'd')
04360       return DAHDI_TONE_DTMF_A + (digit - 'a');
04361    else if (digit == '*')
04362       return DAHDI_TONE_DTMF_s;
04363    else if (digit == '#')
04364       return DAHDI_TONE_DTMF_p;
04365    else
04366       return -1;
04367 }
04368 
04369 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04370 {
04371    struct dahdi_pvt *pvt;
04372    int idx;
04373    int dtmf = -1;
04374    int res;
04375 
04376    pvt = chan->tech_pvt;
04377 
04378    ast_mutex_lock(&pvt->lock);
04379 
04380    idx = dahdi_get_index(chan, pvt, 0);
04381 
04382    if ((idx != SUB_REAL) || !pvt->owner)
04383       goto out;
04384 
04385 #ifdef HAVE_PRI
04386    switch (pvt->sig) {
04387    case SIG_PRI_LIB_HANDLE_CASES:
04388       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04389       if (!res)
04390          goto out;
04391       break;
04392    default:
04393       break;
04394    }
04395 #endif
04396    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04397       goto out;
04398 
04399    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04400       struct dahdi_dialoperation zo = {
04401          .op = DAHDI_DIAL_OP_APPEND,
04402       };
04403 
04404       zo.dialstr[0] = 'T';
04405       zo.dialstr[1] = digit;
04406       zo.dialstr[2] = '\0';
04407       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04408          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04409       else
04410          pvt->dialing = 1;
04411    } else {
04412       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04413       pvt->dialing = 1;
04414       pvt->begindigit = digit;
04415    }
04416 
04417 out:
04418    ast_mutex_unlock(&pvt->lock);
04419 
04420    return 0;
04421 }
04422 
04423 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04424 {
04425    struct dahdi_pvt *pvt;
04426    int res = 0;
04427    int idx;
04428    int x;
04429 
04430    pvt = chan->tech_pvt;
04431 
04432    ast_mutex_lock(&pvt->lock);
04433 
04434    idx = dahdi_get_index(chan, pvt, 0);
04435 
04436    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04437       goto out;
04438 
04439 #ifdef HAVE_PRI
04440    /* This means that the digit was already sent via PRI signalling */
04441    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04442       goto out;
04443    }
04444 #endif
04445 
04446    if (pvt->begindigit) {
04447       x = -1;
04448       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04449       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04450       pvt->dialing = 0;
04451       pvt->begindigit = 0;
04452    }
04453 
04454 out:
04455    ast_mutex_unlock(&pvt->lock);
04456 
04457    return res;
04458 }
04459 
04460 static const char * const events[] = {
04461    "No event",
04462    "On hook",
04463    "Ring/Answered",
04464    "Wink/Flash",
04465    "Alarm",
04466    "No more alarm",
04467    "HDLC Abort",
04468    "HDLC Overrun",
04469    "HDLC Bad FCS",
04470    "Dial Complete",
04471    "Ringer On",
04472    "Ringer Off",
04473    "Hook Transition Complete",
04474    "Bits Changed",
04475    "Pulse Start",
04476    "Timer Expired",
04477    "Timer Ping",
04478    "Polarity Reversal",
04479    "Ring Begin",
04480 };
04481 
04482 static struct {
04483    int alarm;
04484    char *name;
04485 } alarms[] = {
04486    { DAHDI_ALARM_RED, "Red Alarm" },
04487    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04488    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04489    { DAHDI_ALARM_RECOVER, "Recovering" },
04490    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04491    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04492    { DAHDI_ALARM_NONE, "None" },
04493 };
04494 
04495 static char *alarm2str(int alm)
04496 {
04497    int x;
04498    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04499       if (alarms[x].alarm & alm)
04500          return alarms[x].name;
04501    }
04502    return alm ? "Unknown Alarm" : "No Alarm";
04503 }
04504 
04505 static const char *event2str(int event)
04506 {
04507    static char buf[256];
04508    if ((event < (ARRAY_LEN(events))) && (event > -1))
04509       return events[event];
04510    sprintf(buf, "Event %d", event); /* safe */
04511    return buf;
04512 }
04513 
04514 static char *dahdi_sig2str(int sig)
04515 {
04516    static char buf[256];
04517    switch (sig) {
04518    case SIG_EM:
04519       return "E & M Immediate";
04520    case SIG_EMWINK:
04521       return "E & M Wink";
04522    case SIG_EM_E1:
04523       return "E & M E1";
04524    case SIG_FEATD:
04525       return "Feature Group D (DTMF)";
04526    case SIG_FEATDMF:
04527       return "Feature Group D (MF)";
04528    case SIG_FEATDMF_TA:
04529       return "Feature Groud D (MF) Tandem Access";
04530    case SIG_FEATB:
04531       return "Feature Group B (MF)";
04532    case SIG_E911:
04533       return "E911 (MF)";
04534    case SIG_FGC_CAMA:
04535       return "FGC/CAMA (Dialpulse)";
04536    case SIG_FGC_CAMAMF:
04537       return "FGC/CAMA (MF)";
04538    case SIG_FXSLS:
04539       return "FXS Loopstart";
04540    case SIG_FXSGS:
04541       return "FXS Groundstart";
04542    case SIG_FXSKS:
04543       return "FXS Kewlstart";
04544    case SIG_FXOLS:
04545       return "FXO Loopstart";
04546    case SIG_FXOGS:
04547       return "FXO Groundstart";
04548    case SIG_FXOKS:
04549       return "FXO Kewlstart";
04550    case SIG_PRI:
04551       return "ISDN PRI";
04552    case SIG_BRI:
04553       return "ISDN BRI Point to Point";
04554    case SIG_BRI_PTMP:
04555       return "ISDN BRI Point to MultiPoint";
04556    case SIG_SS7:
04557       return "SS7";
04558    case SIG_MFCR2:
04559       return "MFC/R2";
04560    case SIG_SF:
04561       return "SF (Tone) Immediate";
04562    case SIG_SFWINK:
04563       return "SF (Tone) Wink";
04564    case SIG_SF_FEATD:
04565       return "SF (Tone) with Feature Group D (DTMF)";
04566    case SIG_SF_FEATDMF:
04567       return "SF (Tone) with Feature Group D (MF)";
04568    case SIG_SF_FEATB:
04569       return "SF (Tone) with Feature Group B (MF)";
04570    case 0:
04571       return "Pseudo";
04572    default:
04573       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04574       return buf;
04575    }
04576 }
04577 
04578 #define sig2str dahdi_sig2str
04579 
04580 static int analog_lib_handles(int signalling, int radio, int oprmode)
04581 {
04582    switch (signalling) {
04583    case SIG_FXOLS:
04584    case SIG_FXOGS:
04585    case SIG_FXOKS:
04586    case SIG_FXSLS:
04587    case SIG_FXSGS:
04588    case SIG_FXSKS:
04589    case SIG_EMWINK:
04590    case SIG_EM:
04591    case SIG_EM_E1:
04592    case SIG_FEATD:
04593    case SIG_FEATDMF:
04594    case SIG_E911:
04595    case SIG_FGC_CAMA:
04596    case SIG_FGC_CAMAMF:
04597    case SIG_FEATB:
04598    case SIG_SFWINK:
04599    case SIG_SF:
04600    case SIG_SF_FEATD:
04601    case SIG_SF_FEATDMF:
04602    case SIG_FEATDMF_TA:
04603    case SIG_SF_FEATB:
04604       break;
04605    default:
04606       /* The rest of the function should cover the remainder of signalling types */
04607       return 0;
04608    }
04609 
04610    if (radio)
04611       return 0;
04612 
04613    if (oprmode)
04614       return 0;
04615 
04616    return 1;
04617 }
04618 
04619 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04620 {
04621    /* If the conference already exists, and we're already in it
04622       don't bother doing anything */
04623    struct dahdi_confinfo zi;
04624 
04625    memset(&zi, 0, sizeof(zi));
04626    zi.chan = 0;
04627 
04628    if (slavechannel > 0) {
04629       /* If we have only one slave, do a digital mon */
04630       zi.confmode = DAHDI_CONF_DIGITALMON;
04631       zi.confno = slavechannel;
04632    } else {
04633       if (!idx) {
04634          /* Real-side and pseudo-side both participate in conference */
04635          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04636             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04637       } else
04638          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04639       zi.confno = p->confno;
04640    }
04641    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04642       return 0;
04643    if (c->dfd < 0)
04644       return 0;
04645    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04646       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04647       return -1;
04648    }
04649    if (slavechannel < 1) {
04650       p->confno = zi.confno;
04651    }
04652    c->curconf = zi;
04653    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04654    return 0;
04655 }
04656 
04657 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04658 {
04659    /* If they're listening to our channel, they're ours */
04660    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04661       return 1;
04662    /* If they're a talker on our (allocated) conference, they're ours */
04663    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04664       return 1;
04665    return 0;
04666 }
04667 
04668 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04669 {
04670    struct dahdi_confinfo zi;
04671    if (/* Can't delete if there's no dfd */
04672       (c->dfd < 0) ||
04673       /* Don't delete from the conference if it's not our conference */
04674       !isourconf(p, c)
04675       /* Don't delete if we don't think it's conferenced at all (implied) */
04676       ) return 0;
04677    memset(&zi, 0, sizeof(zi));
04678    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04679       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04680       return -1;
04681    }
04682    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04683    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04684    return 0;
04685 }
04686 
04687 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04688 {
04689    int x;
04690    int useslavenative;
04691    struct dahdi_pvt *slave = NULL;
04692    /* Start out optimistic */
04693    useslavenative = 1;
04694    /* Update conference state in a stateless fashion */
04695    for (x = 0; x < 3; x++) {
04696       /* Any three-way calling makes slave native mode *definitely* out
04697          of the question */
04698       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04699          useslavenative = 0;
04700    }
04701    /* If we don't have any 3-way calls, check to see if we have
04702       precisely one slave */
04703    if (useslavenative) {
04704       for (x = 0; x < MAX_SLAVES; x++) {
04705          if (p->slaves[x]) {
04706             if (slave) {
04707                /* Whoops already have a slave!  No
04708                   slave native and stop right away */
04709                slave = NULL;
04710                useslavenative = 0;
04711                break;
04712             } else {
04713                /* We have one slave so far */
04714                slave = p->slaves[x];
04715             }
04716          }
04717       }
04718    }
04719    /* If no slave, slave native definitely out */
04720    if (!slave)
04721       useslavenative = 0;
04722    else if (slave->law != p->law) {
04723       useslavenative = 0;
04724       slave = NULL;
04725    }
04726    if (out)
04727       *out = slave;
04728    return useslavenative;
04729 }
04730 
04731 static int reset_conf(struct dahdi_pvt *p)
04732 {
04733    p->confno = -1;
04734    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04735    if (p->subs[SUB_REAL].dfd > -1) {
04736       struct dahdi_confinfo zi;
04737 
04738       memset(&zi, 0, sizeof(zi));
04739       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04740          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04741    }
04742    return 0;
04743 }
04744 
04745 static int update_conf(struct dahdi_pvt *p)
04746 {
04747    int needconf = 0;
04748    int x;
04749    int useslavenative;
04750    struct dahdi_pvt *slave = NULL;
04751 
04752    useslavenative = isslavenative(p, &slave);
04753    /* Start with the obvious, general stuff */
04754    for (x = 0; x < 3; x++) {
04755       /* Look for three way calls */
04756       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04757          conf_add(p, &p->subs[x], x, 0);
04758          needconf++;
04759       } else {
04760          conf_del(p, &p->subs[x], x);
04761       }
04762    }
04763    /* If we have a slave, add him to our conference now. or DAX
04764       if this is slave native */
04765    for (x = 0; x < MAX_SLAVES; x++) {
04766       if (p->slaves[x]) {
04767          if (useslavenative)
04768             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04769          else {
04770             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04771             needconf++;
04772          }
04773       }
04774    }
04775    /* If we're supposed to be in there, do so now */
04776    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04777       if (useslavenative)
04778          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04779       else {
04780          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04781          needconf++;
04782       }
04783    }
04784    /* If we have a master, add ourselves to his conference */
04785    if (p->master) {
04786       if (isslavenative(p->master, NULL)) {
04787          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04788       } else {
04789          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04790       }
04791    }
04792    if (!needconf) {
04793       /* Nobody is left (or should be left) in our conference.
04794          Kill it. */
04795       p->confno = -1;
04796    }
04797    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04798    return 0;
04799 }
04800 
04801 static void dahdi_enable_ec(struct dahdi_pvt *p)
04802 {
04803    int res;
04804    if (!p)
04805       return;
04806    if (p->echocanon) {
04807       ast_debug(1, "Echo cancellation already on\n");
04808       return;
04809    }
04810    if (p->digital) {
04811       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04812       return;
04813    }
04814    if (p->echocancel.head.tap_length) {
04815 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04816       switch (p->sig) {
04817 #if defined(HAVE_PRI)
04818       case SIG_PRI_LIB_HANDLE_CASES:
04819          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04820             /*
04821              * PRI nobch pseudo channel.  Does not need ec anyway.
04822              * Does not handle ioctl(DAHDI_AUDIOMODE)
04823              */
04824             return;
04825          }
04826          /* Fall through */
04827 #endif   /* defined(HAVE_PRI) */
04828 #if defined(HAVE_SS7)
04829       case SIG_SS7:
04830 #endif   /* defined(HAVE_SS7) */
04831          {
04832             int x = 1;
04833 
04834             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04835             if (res)
04836                ast_log(LOG_WARNING,
04837                   "Unable to enable audio mode on channel %d (%s)\n",
04838                   p->channel, strerror(errno));
04839          }
04840          break;
04841       default:
04842          break;
04843       }
04844 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04845       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04846       if (res) {
04847          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04848       } else {
04849          p->echocanon = 1;
04850          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04851       }
04852    } else
04853       ast_debug(1, "No echo cancellation requested\n");
04854 }
04855 
04856 static void dahdi_train_ec(struct dahdi_pvt *p)
04857 {
04858    int x;
04859    int res;
04860 
04861    if (p && p->echocanon && p->echotraining) {
04862       x = p->echotraining;
04863       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04864       if (res)
04865          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04866       else
04867          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04868    } else {
04869       ast_debug(1, "No echo training requested\n");
04870    }
04871 }
04872 
04873 static void dahdi_disable_ec(struct dahdi_pvt *p)
04874 {
04875    int res;
04876 
04877    if (p->echocanon) {
04878       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04879 
04880       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04881 
04882       if (res)
04883          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04884       else
04885          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04886    }
04887 
04888    p->echocanon = 0;
04889 }
04890 
04891 /* perform a dynamic range compression transform on the given sample */
04892 static int drc_sample(int sample, float drc)
04893 {
04894    float neg;
04895    float shallow, steep;
04896    float max = SHRT_MAX;
04897    
04898    neg = (sample < 0 ? -1 : 1);
04899    steep = drc*sample;
04900    shallow = neg*(max-max/drc)+(float)sample/drc;
04901    if (abs(steep) < abs(shallow)) {
04902       sample = steep;
04903    }
04904    else {
04905       sample = shallow;
04906    }
04907 
04908    return sample;
04909 }
04910 
04911 
04912 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04913 {
04914    int j;
04915    int k;
04916 
04917    float linear_gain = pow(10.0, gain / 20.0);
04918 
04919    switch (law) {
04920    case DAHDI_LAW_ALAW:
04921       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04922          if (gain || drc) {
04923             k = AST_ALAW(j);
04924             if (drc) {
04925                k = drc_sample(k, drc);
04926             }
04927             k = (float)k*linear_gain;
04928             if (k > 32767) k = 32767;
04929             if (k < -32767) k = -32767;
04930             g->txgain[j] = AST_LIN2A(k);
04931          } else {
04932             g->txgain[j] = j;
04933          }
04934       }
04935       break;
04936    case DAHDI_LAW_MULAW:
04937       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04938          if (gain || drc) {
04939             k = AST_MULAW(j);
04940             if (drc) {
04941                k = drc_sample(k, drc);
04942             }
04943             k = (float)k*linear_gain;
04944             if (k > 32767) k = 32767;
04945             if (k < -32767) k = -32767;
04946             g->txgain[j] = AST_LIN2MU(k);
04947 
04948          } else {
04949             g->txgain[j] = j;
04950          }
04951       }
04952       break;
04953    }
04954 }
04955 
04956 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04957 {
04958    int j;
04959    int k;
04960    float linear_gain = pow(10.0, gain / 20.0);
04961 
04962    switch (law) {
04963    case DAHDI_LAW_ALAW:
04964       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04965          if (gain || drc) {
04966             k = AST_ALAW(j);
04967             if (drc) {
04968                k = drc_sample(k, drc);
04969             }
04970             k = (float)k*linear_gain;
04971             if (k > 32767) k = 32767;
04972             if (k < -32767) k = -32767;
04973             g->rxgain[j] = AST_LIN2A(k);
04974          } else {
04975             g->rxgain[j] = j;
04976          }
04977       }
04978       break;
04979    case DAHDI_LAW_MULAW:
04980       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04981          if (gain || drc) {
04982             k = AST_MULAW(j);
04983             if (drc) {
04984                k = drc_sample(k, drc);
04985             }
04986             k = (float)k*linear_gain;
04987             if (k > 32767) k = 32767;
04988             if (k < -32767) k = -32767;
04989             g->rxgain[j] = AST_LIN2MU(k);
04990          } else {
04991             g->rxgain[j] = j;
04992          }
04993       }
04994       break;
04995    }
04996 }
04997 
04998 static int set_actual_txgain(int fd, float gain, float drc, int law)
04999 {
05000    struct dahdi_gains g;
05001    int res;
05002 
05003    memset(&g, 0, sizeof(g));
05004    res = ioctl(fd, DAHDI_GETGAINS, &g);
05005    if (res) {
05006       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05007       return res;
05008    }
05009 
05010    fill_txgain(&g, gain, drc, law);
05011 
05012    return ioctl(fd, DAHDI_SETGAINS, &g);
05013 }
05014 
05015 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05016 {
05017    struct dahdi_gains g;
05018    int res;
05019 
05020    memset(&g, 0, sizeof(g));
05021    res = ioctl(fd, DAHDI_GETGAINS, &g);
05022    if (res) {
05023       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05024       return res;
05025    }
05026 
05027    fill_rxgain(&g, gain, drc, law);
05028 
05029    return ioctl(fd, DAHDI_SETGAINS, &g);
05030 }
05031 
05032 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05033 {
05034    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05035 }
05036 
05037 static int bump_gains(struct dahdi_pvt *p)
05038 {
05039    int res;
05040 
05041    /* Bump receive gain by value stored in cid_rxgain */
05042    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05043    if (res) {
05044       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05045       return -1;
05046    }
05047 
05048    return 0;
05049 }
05050 
05051 static int restore_gains(struct dahdi_pvt *p)
05052 {
05053    int res;
05054 
05055    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05056    if (res) {
05057       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05058       return -1;
05059    }
05060 
05061    return 0;
05062 }
05063 
05064 static inline int dahdi_set_hook(int fd, int hs)
05065 {
05066    int x, res;
05067 
05068    x = hs;
05069    res = ioctl(fd, DAHDI_HOOK, &x);
05070 
05071    if (res < 0) {
05072       if (errno == EINPROGRESS)
05073          return 0;
05074       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05075       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05076    }
05077 
05078    return res;
05079 }
05080 
05081 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05082 {
05083    int x, res;
05084 
05085    x = muted;
05086 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05087    switch (p->sig) {
05088 #if defined(HAVE_PRI)
05089    case SIG_PRI_LIB_HANDLE_CASES:
05090       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05091          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05092          break;
05093       }
05094       /* Fall through */
05095 #endif   /* defined(HAVE_PRI) */
05096 #if defined(HAVE_SS7)
05097    case SIG_SS7:
05098 #endif   /* defined(HAVE_SS7) */
05099       {
05100          int y = 1;
05101 
05102          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05103          if (res)
05104             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05105                p->channel, strerror(errno));
05106       }
05107       break;
05108    default:
05109       break;
05110    }
05111 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05112    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05113    if (res < 0)
05114       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05115    return res;
05116 }
05117 
05118 static int save_conference(struct dahdi_pvt *p)
05119 {
05120    struct dahdi_confinfo c;
05121    int res;
05122    if (p->saveconf.confmode) {
05123       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05124       return -1;
05125    }
05126    p->saveconf.chan = 0;
05127    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05128    if (res) {
05129       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05130       p->saveconf.confmode = 0;
05131       return -1;
05132    }
05133    memset(&c, 0, sizeof(c));
05134    c.confmode = DAHDI_CONF_NORMAL;
05135    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05136    if (res) {
05137       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05138       return -1;
05139    }
05140    ast_debug(1, "Disabled conferencing\n");
05141    return 0;
05142 }
05143 
05144 static int restore_conference(struct dahdi_pvt *p)
05145 {
05146    int res;
05147    if (p->saveconf.confmode) {
05148       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05149       p->saveconf.confmode = 0;
05150       if (res) {
05151          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05152          return -1;
05153       }
05154       ast_debug(1, "Restored conferencing\n");
05155    }
05156    return 0;
05157 }
05158 
05159 static int send_cwcidspill(struct dahdi_pvt *p)
05160 {
05161    p->callwaitcas = 0;
05162    p->cidcwexpire = 0;
05163    p->cid_suppress_expire = 0;
05164    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05165       return -1;
05166    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05167    /* Make sure we account for the end */
05168    p->cidlen += READ_SIZE * 4;
05169    p->cidpos = 0;
05170    send_callerid(p);
05171    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05172    return 0;
05173 }
05174 
05175 static int has_voicemail(struct dahdi_pvt *p)
05176 {
05177    int new_msgs;
05178    struct ast_event *event;
05179    char *mailbox, *context;
05180 
05181    mailbox = context = ast_strdupa(p->mailbox);
05182    strsep(&context, "@");
05183    if (ast_strlen_zero(context))
05184       context = "default";
05185 
05186    event = ast_event_get_cached(AST_EVENT_MWI,
05187       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05188       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05189       AST_EVENT_IE_END);
05190 
05191    if (event) {
05192       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05193       ast_event_destroy(event);
05194    } else
05195       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05196 
05197    return new_msgs;
05198 }
05199 
05200 
05201 
05202 static int send_callerid(struct dahdi_pvt *p)
05203 {
05204    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05205    int res;
05206    /* Take out of linear mode if necessary */
05207    if (p->subs[SUB_REAL].linear) {
05208       p->subs[SUB_REAL].linear = 0;
05209       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05210    }
05211    while (p->cidpos < p->cidlen) {
05212       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05213       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05214       if (res < 0) {
05215          if (errno == EAGAIN)
05216             return 0;
05217          else {
05218             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05219             return -1;
05220          }
05221       }
05222       if (!res)
05223          return 0;
05224       p->cidpos += res;
05225    }
05226    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05227    ast_free(p->cidspill);
05228    p->cidspill = NULL;
05229    if (p->callwaitcas) {
05230       /* Wait for CID/CW to expire */
05231       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05232       p->cid_suppress_expire = p->cidcwexpire;
05233    } else
05234       restore_conference(p);
05235    return 0;
05236 }
05237 
05238 static int dahdi_callwait(struct ast_channel *ast)
05239 {
05240    struct dahdi_pvt *p = ast->tech_pvt;
05241    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05242    if (p->cidspill) {
05243       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05244       ast_free(p->cidspill);
05245    }
05246 
05247    /*
05248     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05249     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05250     */
05251    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05252       return -1;
05253    save_conference(p);
05254    /* Silence */
05255    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05256    if (!p->callwaitrings && p->callwaitingcallerid) {
05257       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05258       p->callwaitcas = 1;
05259       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05260    } else {
05261       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05262       p->callwaitcas = 0;
05263       p->cidlen = 2400 + READ_SIZE * 4;
05264    }
05265    p->cidpos = 0;
05266    send_callerid(p);
05267 
05268    return 0;
05269 }
05270 
05271 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05272 {
05273    struct dahdi_pvt *p = ast->tech_pvt;
05274    int x, res, mysig;
05275    char dest[256]; /* must be same length as p->dialdest */
05276 
05277    ast_mutex_lock(&p->lock);
05278    ast_copy_string(dest, rdest, sizeof(dest));
05279    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05280    if ((ast->_state == AST_STATE_BUSY)) {
05281       p->subs[SUB_REAL].needbusy = 1;
05282       ast_mutex_unlock(&p->lock);
05283       return 0;
05284    }
05285    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05286       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05287       ast_mutex_unlock(&p->lock);
05288       return -1;
05289    }
05290    p->waitingfordt.tv_sec = 0;
05291    p->dialednone = 0;
05292    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05293    {
05294       /* Special pseudo -- automatically up */
05295       ast_setstate(ast, AST_STATE_UP);
05296       ast_mutex_unlock(&p->lock);
05297       return 0;
05298    }
05299    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05300    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05301    if (res)
05302       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05303    p->outgoing = 1;
05304 
05305    if (IS_DIGITAL(ast->transfercapability)){
05306       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05307    } else {
05308       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05309    }  
05310 
05311 #ifdef HAVE_PRI
05312    if (dahdi_sig_pri_lib_handles(p->sig)) {
05313       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05314          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05315       ast_mutex_unlock(&p->lock);
05316       return res;
05317    }
05318 #endif
05319 
05320 #if defined(HAVE_SS7)
05321    if (p->sig == SIG_SS7) {
05322       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05323       ast_mutex_unlock(&p->lock);
05324       return res;
05325    }
05326 #endif   /* defined(HAVE_SS7) */
05327 
05328    /* If this is analog signalling we can exit here */
05329    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05330       p->callwaitrings = 0;
05331       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05332       ast_mutex_unlock(&p->lock);
05333       return res;
05334    }
05335 
05336    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05337    switch (mysig) {
05338    case 0:
05339       /* Special pseudo -- automatically up*/
05340       ast_setstate(ast, AST_STATE_UP);
05341       break;
05342    case SIG_MFCR2:
05343       break;
05344    default:
05345       ast_debug(1, "not yet implemented\n");
05346       ast_mutex_unlock(&p->lock);
05347       return -1;
05348    }
05349 
05350 #ifdef HAVE_OPENR2
05351    if (p->mfcr2) {
05352       openr2_calling_party_category_t chancat;
05353       int callres = 0;
05354       char *c, *l;
05355 
05356       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05357       p->dialdest[0] = '\0';
05358 
05359       c = strchr(dest, '/');
05360       if (c) {
05361          c++;
05362       } else {
05363          c = "";
05364       }
05365       if (!p->hidecallerid) {
05366          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05367       } else {
05368          l = NULL;
05369       }
05370       if (strlen(c) < p->stripmsd) {
05371          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05372          ast_mutex_unlock(&p->lock);
05373          return -1;
05374       }
05375       p->dialing = 1;
05376       chancat = dahdi_r2_get_channel_category(ast);
05377       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05378       if (-1 == callres) {
05379          ast_mutex_unlock(&p->lock);
05380          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05381          return -1;
05382       }
05383       p->mfcr2_call_accepted = 0;
05384       p->mfcr2_progress = 0;
05385       ast_setstate(ast, AST_STATE_DIALING);
05386    }
05387 #endif /* HAVE_OPENR2 */
05388    ast_mutex_unlock(&p->lock);
05389    return 0;
05390 }
05391 
05392 /*!
05393  * \internal
05394  * \brief Insert the given chan_dahdi interface structure into the interface list.
05395  * \since 1.8
05396  *
05397  * \param pvt chan_dahdi private interface structure to insert.
05398  *
05399  * \details
05400  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05401  * Any duplicates are inserted after the existing entries.
05402  *
05403  * \note The new interface must not already be in the list.
05404  *
05405  * \return Nothing
05406  */
05407 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05408 {
05409    struct dahdi_pvt *cur;
05410 
05411    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05412 
05413    /* Find place in middle of list for the new interface. */
05414    for (cur = iflist; cur; cur = cur->next) {
05415       if (pvt->channel < cur->channel) {
05416          /* New interface goes before the current interface. */
05417          pvt->prev = cur->prev;
05418          pvt->next = cur;
05419          if (cur->prev) {
05420             /* Insert into the middle of the list. */
05421             cur->prev->next = pvt;
05422          } else {
05423             /* Insert at head of list. */
05424             iflist = pvt;
05425          }
05426          cur->prev = pvt;
05427          return;
05428       }
05429    }
05430 
05431    /* New interface goes onto the end of the list */
05432    pvt->prev = ifend;
05433    pvt->next = NULL;
05434    if (ifend) {
05435       ifend->next = pvt;
05436    }
05437    ifend = pvt;
05438    if (!iflist) {
05439       /* List was empty */
05440       iflist = pvt;
05441    }
05442 }
05443 
05444 /*!
05445  * \internal
05446  * \brief Extract the given chan_dahdi interface structure from the interface list.
05447  * \since 1.8
05448  *
05449  * \param pvt chan_dahdi private interface structure to extract.
05450  *
05451  * \note
05452  * The given interface structure can be either in the interface list or a stand alone
05453  * structure that has not been put in the list if the next and prev pointers are NULL.
05454  *
05455  * \return Nothing
05456  */
05457 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05458 {
05459    /* Extract from the forward chain. */
05460    if (pvt->prev) {
05461       pvt->prev->next = pvt->next;
05462    } else if (iflist == pvt) {
05463       /* Node is at the head of the list. */
05464       iflist = pvt->next;
05465    }
05466 
05467    /* Extract from the reverse chain. */
05468    if (pvt->next) {
05469       pvt->next->prev = pvt->prev;
05470    } else if (ifend == pvt) {
05471       /* Node is at the end of the list. */
05472       ifend = pvt->prev;
05473    }
05474 
05475    /* Node is no longer in the list. */
05476    pvt->which_iflist = DAHDI_IFLIST_NONE;
05477    pvt->prev = NULL;
05478    pvt->next = NULL;
05479 }
05480 
05481 #if defined(HAVE_PRI)
05482 /*!
05483  * \internal
05484  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05485  * \since 1.8
05486  *
05487  * \param pri sig_pri span control structure holding no B channel list.
05488  * \param pvt chan_dahdi private interface structure to insert.
05489  *
05490  * \details
05491  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05492  * Any duplicates are inserted after the existing entries.
05493  *
05494  * \note The new interface must not already be in the list.
05495  *
05496  * \return Nothing
05497  */
05498 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05499 {
05500    struct dahdi_pvt *cur;
05501 
05502    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05503 
05504    /* Find place in middle of list for the new interface. */
05505    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05506       if (pvt->channel < cur->channel) {
05507          /* New interface goes before the current interface. */
05508          pvt->prev = cur->prev;
05509          pvt->next = cur;
05510          if (cur->prev) {
05511             /* Insert into the middle of the list. */
05512             cur->prev->next = pvt;
05513          } else {
05514             /* Insert at head of list. */
05515             pri->no_b_chan_iflist = pvt;
05516          }
05517          cur->prev = pvt;
05518          return;
05519       }
05520    }
05521 
05522    /* New interface goes onto the end of the list */
05523    pvt->prev = pri->no_b_chan_end;
05524    pvt->next = NULL;
05525    if (pri->no_b_chan_end) {
05526       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05527    }
05528    pri->no_b_chan_end = pvt;
05529    if (!pri->no_b_chan_iflist) {
05530       /* List was empty */
05531       pri->no_b_chan_iflist = pvt;
05532    }
05533 }
05534 #endif   /* defined(HAVE_PRI) */
05535 
05536 #if defined(HAVE_PRI)
05537 /*!
05538  * \internal
05539  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05540  * \since 1.8
05541  *
05542  * \param pri sig_pri span control structure holding no B channel list.
05543  * \param pvt chan_dahdi private interface structure to extract.
05544  *
05545  * \note
05546  * The given interface structure can be either in the interface list or a stand alone
05547  * structure that has not been put in the list if the next and prev pointers are NULL.
05548  *
05549  * \return Nothing
05550  */
05551 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05552 {
05553    /* Extract from the forward chain. */
05554    if (pvt->prev) {
05555       pvt->prev->next = pvt->next;
05556    } else if (pri->no_b_chan_iflist == pvt) {
05557       /* Node is at the head of the list. */
05558       pri->no_b_chan_iflist = pvt->next;
05559    }
05560 
05561    /* Extract from the reverse chain. */
05562    if (pvt->next) {
05563       pvt->next->prev = pvt->prev;
05564    } else if (pri->no_b_chan_end == pvt) {
05565       /* Node is at the end of the list. */
05566       pri->no_b_chan_end = pvt->prev;
05567    }
05568 
05569    /* Node is no longer in the list. */
05570    pvt->which_iflist = DAHDI_IFLIST_NONE;
05571    pvt->prev = NULL;
05572    pvt->next = NULL;
05573 }
05574 #endif   /* defined(HAVE_PRI) */
05575 
05576 #if defined(HAVE_PRI)
05577 /*!
05578  * \internal
05579  * \brief Unlink the channel interface from the PRI private pointer array.
05580  * \since 1.8
05581  *
05582  * \param pvt chan_dahdi private interface structure to unlink.
05583  *
05584  * \return Nothing
05585  */
05586 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05587 {
05588    unsigned idx;
05589    struct sig_pri_span *pri;
05590 
05591    pri = pvt->pri;
05592    if (!pri) {
05593       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05594       return;
05595    }
05596    ast_mutex_lock(&pri->lock);
05597    for (idx = 0; idx < pri->numchans; ++idx) {
05598       if (pri->pvts[idx] == pvt->sig_pvt) {
05599          pri->pvts[idx] = NULL;
05600          ast_mutex_unlock(&pri->lock);
05601          return;
05602       }
05603    }
05604    ast_mutex_unlock(&pri->lock);
05605 }
05606 #endif   /* defined(HAVE_PRI) */
05607 
05608 #if defined(HAVE_SS7)
05609 /*!
05610  * \internal
05611  * \brief Unlink the channel interface from the SS7 private pointer array.
05612  * \since 1.8
05613  *
05614  * \param pvt chan_dahdi private interface structure to unlink.
05615  *
05616  * \return Nothing
05617  */
05618 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05619 {
05620    unsigned idx;
05621    struct sig_ss7_linkset *ss7;
05622 
05623    ss7 = pvt->ss7;
05624    if (!ss7) {
05625       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05626       return;
05627    }
05628    ast_mutex_lock(&ss7->lock);
05629    for (idx = 0; idx < ss7->numchans; ++idx) {
05630       if (ss7->pvts[idx] == pvt->sig_pvt) {
05631          ss7->pvts[idx] = NULL;
05632          ast_mutex_unlock(&ss7->lock);
05633          return;
05634       }
05635    }
05636    ast_mutex_unlock(&ss7->lock);
05637 }
05638 #endif   /* defined(HAVE_SS7) */
05639 
05640 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05641 {
05642    if (cur->next && cur->next->span == cur->span) {
05643       return cur->next;
05644    } else if (cur->prev && cur->prev->span == cur->span) {
05645       return cur->prev;
05646    }
05647 
05648    return NULL;
05649 }
05650 
05651 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05652 {
05653    struct dahdi_pvt *p = pvt;
05654 
05655    if (p->manages_span_alarms) {
05656       struct dahdi_pvt *next = find_next_iface_in_span(p);
05657       if (next) {
05658          next->manages_span_alarms = 1;
05659       }
05660    }
05661 
05662    /* Remove channel from the list */
05663 #if defined(HAVE_PRI)
05664    dahdi_unlink_pri_pvt(p);
05665 #endif   /* defined(HAVE_PRI) */
05666 #if defined(HAVE_SS7)
05667    dahdi_unlink_ss7_pvt(p);
05668 #endif   /* defined(HAVE_SS7) */
05669    switch (pvt->which_iflist) {
05670    case DAHDI_IFLIST_NONE:
05671       break;
05672    case DAHDI_IFLIST_MAIN:
05673       dahdi_iflist_extract(p);
05674       break;
05675 #if defined(HAVE_PRI)
05676    case DAHDI_IFLIST_NO_B_CHAN:
05677       if (p->pri) {
05678          dahdi_nobch_extract(p->pri, p);
05679       }
05680       break;
05681 #endif   /* defined(HAVE_PRI) */
05682    }
05683 
05684    if (p->sig_pvt) {
05685       if (analog_lib_handles(p->sig, 0, 0)) {
05686          analog_delete(p->sig_pvt);
05687       }
05688       switch (p->sig) {
05689 #if defined(HAVE_PRI)
05690       case SIG_PRI_LIB_HANDLE_CASES:
05691          sig_pri_chan_delete(p->sig_pvt);
05692          break;
05693 #endif   /* defined(HAVE_PRI) */
05694 #if defined(HAVE_SS7)
05695       case SIG_SS7:
05696          sig_ss7_chan_delete(p->sig_pvt);
05697          break;
05698 #endif   /* defined(HAVE_SS7) */
05699       default:
05700          break;
05701       }
05702    }
05703    ast_free(p->cidspill);
05704    if (p->use_smdi)
05705       ast_smdi_interface_unref(p->smdi_iface);
05706    if (p->mwi_event_sub)
05707       ast_event_unsubscribe(p->mwi_event_sub);
05708    if (p->vars) {
05709       ast_variables_destroy(p->vars);
05710    }
05711    if (p->cc_params) {
05712       ast_cc_config_params_destroy(p->cc_params);
05713    }
05714    ast_mutex_destroy(&p->lock);
05715    dahdi_close_sub(p, SUB_REAL);
05716    if (p->owner)
05717       p->owner->tech_pvt = NULL;
05718    ast_free(p);
05719 }
05720 
05721 static void destroy_channel(struct dahdi_pvt *cur, int now)
05722 {
05723    int i;
05724 
05725    if (!now) {
05726       /* Do not destroy the channel now if it is owned by someone. */
05727       if (cur->owner) {
05728          return;
05729       }
05730       for (i = 0; i < 3; i++) {
05731          if (cur->subs[i].owner) {
05732             return;
05733          }
05734       }
05735    }
05736    destroy_dahdi_pvt(cur);
05737 }
05738 
05739 static void destroy_all_channels(void)
05740 {
05741    int chan;
05742 #if defined(HAVE_PRI)
05743    unsigned span;
05744    struct sig_pri_span *pri;
05745 #endif   /* defined(HAVE_PRI) */
05746    struct dahdi_pvt *p;
05747 
05748    while (num_restart_pending) {
05749       usleep(1);
05750    }
05751 
05752    ast_mutex_lock(&iflock);
05753    /* Destroy all the interfaces and free their memory */
05754    while (iflist) {
05755       p = iflist;
05756 
05757       chan = p->channel;
05758 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05759       {
05760          char db_chan_name[20];
05761          char db_answer[5];
05762          char state;
05763          int why = -1;
05764 
05765          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05766          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05767             sscanf(db_answer, "%1c:%30d", &state, &why);
05768          }
05769          if (!why) {
05770             /* SRVST persistence is not required */
05771             ast_db_del(db_chan_name, SRVST_DBKEY);
05772          }
05773       }
05774 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05775       /* Free associated memory */
05776       destroy_dahdi_pvt(p);
05777       ast_verb(3, "Unregistered channel %d\n", chan);
05778    }
05779    ifcount = 0;
05780    ast_mutex_unlock(&iflock);
05781 
05782 #if defined(HAVE_PRI)
05783    /* Destroy all of the no B channel interface lists */
05784    for (span = 0; span < NUM_SPANS; ++span) {
05785       if (!pris[span].dchannels[0]) {
05786          break;
05787       }
05788       pri = &pris[span].pri;
05789       ast_mutex_lock(&pri->lock);
05790       while (pri->no_b_chan_iflist) {
05791          p = pri->no_b_chan_iflist;
05792 
05793          /* Free associated memory */
05794          destroy_dahdi_pvt(p);
05795       }
05796       ast_mutex_unlock(&pri->lock);
05797    }
05798 #endif   /* defined(HAVE_PRI) */
05799 }
05800 
05801 #if defined(HAVE_PRI)
05802 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05803 
05804 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05805 {
05806    /* Data will be our digit string */
05807    struct dahdi_pvt *p;
05808 
05809    if (ast_strlen_zero(digits)) {
05810       ast_debug(1, "No digit string sent to application!\n");
05811       return -1;
05812    }
05813 
05814    p = (struct dahdi_pvt *)chan->tech_pvt;
05815 
05816    if (!p) {
05817       ast_debug(1, "Unable to find technology private\n");
05818       return -1;
05819    }
05820 
05821    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05822 
05823    return 0;
05824 }
05825 #endif   /* defined(HAVE_PRI) */
05826 
05827 #if defined(HAVE_PRI)
05828 #if defined(HAVE_PRI_PROG_W_CAUSE)
05829 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05830 
05831 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05832 {
05833    /* Data will be our digit string */
05834    struct dahdi_pvt *pvt;
05835    char *parse;
05836    int res = -1;
05837    AST_DECLARE_APP_ARGS(args,
05838       AST_APP_ARG(destination);
05839       AST_APP_ARG(original);
05840       AST_APP_ARG(reason);
05841    );
05842 
05843    if (ast_strlen_zero(data)) {
05844       ast_log(LOG_DEBUG, "No data sent to application!\n");
05845       return -1;
05846    }
05847    if (chan->tech != &dahdi_tech) {
05848       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05849       return -1;
05850    }
05851    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05852    if (!pvt) {
05853       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05854       return -1;
05855    }
05856    switch (pvt->sig) {
05857    case SIG_PRI_LIB_HANDLE_CASES:
05858       break;
05859    default:
05860       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05861          chan->name);
05862       return -1;
05863    }
05864 
05865    parse = ast_strdupa(data);
05866    AST_STANDARD_APP_ARGS(args, parse);
05867 
05868    if (ast_strlen_zero(args.destination)) {
05869       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05870       return -1;
05871    }
05872 
05873    if (ast_strlen_zero(args.original)) {
05874       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05875       args.original = NULL;
05876    }
05877 
05878    if (ast_strlen_zero(args.reason)) {
05879       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05880       args.reason = NULL;
05881    }
05882 
05883    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05884       args.original, args.reason);
05885 
05886    return res;
05887 }
05888 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05889 #endif   /* defined(HAVE_PRI) */
05890 
05891 #if defined(HAVE_OPENR2)
05892 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05893 
05894 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05895 {
05896    /* data is whether to accept with charge or no charge */
05897    openr2_call_mode_t accept_mode;
05898    int res, timeout, maxloops;
05899    struct ast_frame *f;
05900    struct dahdi_pvt *p;
05901    char *parse;
05902    AST_DECLARE_APP_ARGS(args,
05903          AST_APP_ARG(charge);
05904    );
05905 
05906    if (ast_strlen_zero(data)) {
05907       ast_log(LOG_DEBUG, "No data sent to application!\n");
05908       return -1;
05909    }
05910 
05911    if (chan->tech != &dahdi_tech) {
05912       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05913       return -1;
05914    }
05915 
05916    p = (struct dahdi_pvt *)chan->tech_pvt;
05917    if (!p) {
05918       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05919       return -1;
05920    }
05921 
05922    parse = ast_strdupa(data);
05923    AST_STANDARD_APP_ARGS(args, parse);
05924 
05925    if (ast_strlen_zero(args.charge)) {
05926       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05927       return -1;
05928    }
05929 
05930    ast_mutex_lock(&p->lock);
05931    if (!p->mfcr2 || !p->mfcr2call) {
05932       ast_mutex_unlock(&p->lock);
05933       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05934       return -1;
05935    }
05936 
05937    if (p->mfcr2_call_accepted) {
05938       ast_mutex_unlock(&p->lock);
05939       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05940       return 0;
05941    }
05942    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05943    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05944       ast_mutex_unlock(&p->lock);
05945       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05946       return -1;
05947    }
05948    ast_mutex_unlock(&p->lock);
05949 
05950    res = 0;
05951    timeout = 100;
05952    maxloops = 50; /* wait up to 5 seconds */
05953    /* we need to read() until the call is accepted */
05954    while (maxloops > 0) {
05955       maxloops--;
05956       if (ast_check_hangup(chan)) {
05957          break;
05958       }
05959       res = ast_waitfor(chan, timeout);
05960       if (res < 0) {
05961          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05962          res = -1;
05963          break;
05964       }
05965       if (res == 0) {
05966          continue;
05967       }
05968       f = ast_read(chan);
05969       if (!f) {
05970          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05971          res = -1;
05972          break;
05973       }
05974       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05975          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05976          ast_frfree(f);
05977          res = -1;
05978          break;
05979       }
05980       ast_frfree(f);
05981       ast_mutex_lock(&p->lock);
05982       if (p->mfcr2_call_accepted) {
05983          ast_mutex_unlock(&p->lock);
05984          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05985          break;
05986       }
05987       ast_mutex_unlock(&p->lock);
05988    }
05989    if (res == -1) {
05990       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05991    }
05992    return res;
05993 }
05994 
05995 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05996 {
05997    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05998    switch (cause) {
05999    case AST_CAUSE_USER_BUSY:
06000    case AST_CAUSE_CALL_REJECTED:
06001    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06002       r2cause = OR2_CAUSE_BUSY_NUMBER;
06003       break;
06004 
06005    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06006    case AST_CAUSE_SWITCH_CONGESTION:
06007       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06008       break;
06009 
06010    case AST_CAUSE_UNALLOCATED:
06011       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06012       break;
06013 
06014    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06015    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06016       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06017       break;
06018 
06019    case AST_CAUSE_NO_ANSWER:
06020    case AST_CAUSE_NO_USER_RESPONSE:
06021       r2cause = OR2_CAUSE_NO_ANSWER;
06022       break;
06023 
06024    default:
06025       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06026       break;
06027    }
06028    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06029          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06030    return r2cause;
06031 }
06032 #endif
06033 
06034 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06035 {
06036    if (p->bufferoverrideinuse) {
06037       /* faxbuffers are in use, revert them */
06038       struct dahdi_bufferinfo bi = {
06039          .txbufpolicy = p->buf_policy,
06040          .rxbufpolicy = p->buf_policy,
06041          .bufsize = p->bufsize,
06042          .numbufs = p->buf_no
06043       };
06044       int bpres;
06045 
06046       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06047          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06048       }
06049       p->bufferoverrideinuse = 0;
06050       return bpres;
06051    }
06052 
06053    return -1;
06054 }
06055 
06056 static int dahdi_hangup(struct ast_channel *ast)
06057 {
06058    int res = 0;
06059    int idx,x;
06060    int law;
06061    /*static int restore_gains(struct dahdi_pvt *p);*/
06062    struct dahdi_pvt *p = ast->tech_pvt;
06063    struct dahdi_params par;
06064 
06065    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06066    if (!ast->tech_pvt) {
06067       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06068       return 0;
06069    }
06070 
06071    ast_mutex_lock(&p->lock);
06072    p->exten[0] = '\0';
06073    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06074       dahdi_confmute(p, 0);
06075       restore_gains(p);
06076       p->ignoredtmf = 0;
06077       p->waitingfordt.tv_sec = 0;
06078 
06079       res = analog_hangup(p->sig_pvt, ast);
06080       revert_fax_buffers(p, ast);
06081 
06082       goto hangup_out;
06083    } else {
06084       p->cid_num[0] = '\0';
06085       p->cid_name[0] = '\0';
06086       p->cid_subaddr[0] = '\0';
06087    }
06088 
06089 #if defined(HAVE_PRI)
06090    if (dahdi_sig_pri_lib_handles(p->sig)) {
06091       x = 1;
06092       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06093 
06094       dahdi_confmute(p, 0);
06095       p->muting = 0;
06096       restore_gains(p);
06097       if (p->dsp) {
06098          ast_dsp_free(p->dsp);
06099          p->dsp = NULL;
06100       }
06101       p->ignoredtmf = 0;
06102 
06103       /* Real channel, do some fixup */
06104       p->subs[SUB_REAL].owner = NULL;
06105       p->subs[SUB_REAL].needbusy = 0;
06106       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06107 
06108       p->owner = NULL;
06109       p->cid_tag[0] = '\0';
06110       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06111       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06112       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06113       p->outgoing = 0;
06114       p->digital = 0;
06115       p->faxhandled = 0;
06116       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06117 
06118       revert_fax_buffers(p, ast);
06119 
06120       p->law = p->law_default;
06121       law = p->law_default;
06122       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06123       if (res < 0) {
06124          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06125             p->channel, strerror(errno));
06126       }
06127 
06128       sig_pri_hangup(p->sig_pvt, ast);
06129 
06130       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06131       dahdi_disable_ec(p);
06132 
06133       x = 0;
06134       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06135       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06136 
06137       p->rdnis[0] = '\0';
06138       update_conf(p);
06139       reset_conf(p);
06140 
06141       /* Restore data mode */
06142       x = 0;
06143       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06144 
06145       if (num_restart_pending == 0) {
06146          restart_monitor();
06147       }
06148       goto hangup_out;
06149    }
06150 #endif   /* defined(HAVE_PRI) */
06151 
06152 #if defined(HAVE_SS7)
06153    if (p->sig == SIG_SS7) {
06154       x = 1;
06155       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06156 
06157       dahdi_confmute(p, 0);
06158       p->muting = 0;
06159       restore_gains(p);
06160       if (p->dsp) {
06161          ast_dsp_free(p->dsp);
06162          p->dsp = NULL;
06163       }
06164       p->ignoredtmf = 0;
06165 
06166       /* Real channel, do some fixup */
06167       p->subs[SUB_REAL].owner = NULL;
06168       p->subs[SUB_REAL].needbusy = 0;
06169       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06170 
06171       p->owner = NULL;
06172       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06173       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06174       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06175       p->outgoing = 0;
06176       p->digital = 0;
06177       p->faxhandled = 0;
06178       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06179 
06180       revert_fax_buffers(p, ast);
06181 
06182       p->law = p->law_default;
06183       law = p->law_default;
06184       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06185       if (res < 0) {
06186          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06187             p->channel, strerror(errno));
06188       }
06189 
06190       sig_ss7_hangup(p->sig_pvt, ast);
06191 
06192       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06193       dahdi_disable_ec(p);
06194 
06195       x = 0;
06196       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06197       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06198 
06199       update_conf(p);
06200       reset_conf(p);
06201 
06202       /* Restore data mode */
06203       x = 0;
06204       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06205 
06206       if (num_restart_pending == 0) {
06207          restart_monitor();
06208       }
06209       goto hangup_out;
06210    }
06211 #endif   /* defined(HAVE_SS7) */
06212 
06213    idx = dahdi_get_index(ast, p, 1);
06214 
06215    dahdi_confmute(p, 0);
06216    p->muting = 0;
06217    restore_gains(p);
06218    if (p->origcid_num) {
06219       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06220       ast_free(p->origcid_num);
06221       p->origcid_num = NULL;
06222    }
06223    if (p->origcid_name) {
06224       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06225       ast_free(p->origcid_name);
06226       p->origcid_name = NULL;
06227    }
06228    if (p->dsp)
06229       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06230 
06231    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06232       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06233    p->ignoredtmf = 0;
06234 
06235    if (idx > -1) {
06236       /* Real channel, do some fixup */
06237       p->subs[idx].owner = NULL;
06238       p->subs[idx].needanswer = 0;
06239       p->subs[idx].needflash = 0;
06240       p->subs[idx].needringing = 0;
06241       p->subs[idx].needbusy = 0;
06242       p->subs[idx].needcongestion = 0;
06243       p->subs[idx].linear = 0;
06244       p->polarity = POLARITY_IDLE;
06245       dahdi_setlinear(p->subs[idx].dfd, 0);
06246       if (idx == SUB_REAL) {
06247          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06248             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06249             if (p->subs[SUB_CALLWAIT].inthreeway) {
06250                /* We had flipped over to answer a callwait and now it's gone */
06251                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06252                /* Move to the call-wait, but un-own us until they flip back. */
06253                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06254                unalloc_sub(p, SUB_CALLWAIT);
06255                p->owner = NULL;
06256             } else {
06257                /* The three way hung up, but we still have a call wait */
06258                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06259                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06260                unalloc_sub(p, SUB_THREEWAY);
06261                if (p->subs[SUB_REAL].inthreeway) {
06262                   /* This was part of a three way call.  Immediately make way for
06263                      another call */
06264                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06265                   p->owner = p->subs[SUB_REAL].owner;
06266                } else {
06267                   /* This call hasn't been completed yet...  Set owner to NULL */
06268                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06269                   p->owner = NULL;
06270                }
06271                p->subs[SUB_REAL].inthreeway = 0;
06272             }
06273          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06274             /* Move to the call-wait and switch back to them. */
06275             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06276             unalloc_sub(p, SUB_CALLWAIT);
06277             p->owner = p->subs[SUB_REAL].owner;
06278             if (p->owner->_state != AST_STATE_UP)
06279                p->subs[SUB_REAL].needanswer = 1;
06280             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06281                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06282          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06283             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06284             unalloc_sub(p, SUB_THREEWAY);
06285             if (p->subs[SUB_REAL].inthreeway) {
06286                /* This was part of a three way call.  Immediately make way for
06287                   another call */
06288                ast_debug(1, "Call was complete, setting owner to former third call\n");
06289                p->owner = p->subs[SUB_REAL].owner;
06290             } else {
06291                /* This call hasn't been completed yet...  Set owner to NULL */
06292                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06293                p->owner = NULL;
06294             }
06295             p->subs[SUB_REAL].inthreeway = 0;
06296          }
06297       } else if (idx == SUB_CALLWAIT) {
06298          /* Ditch the holding callwait call, and immediately make it availabe */
06299          if (p->subs[SUB_CALLWAIT].inthreeway) {
06300             /* This is actually part of a three way, placed on hold.  Place the third part
06301                on music on hold now */
06302             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06303                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06304                   S_OR(p->mohsuggest, NULL),
06305                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06306             }
06307             p->subs[SUB_THREEWAY].inthreeway = 0;
06308             /* Make it the call wait now */
06309             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06310             unalloc_sub(p, SUB_THREEWAY);
06311          } else
06312             unalloc_sub(p, SUB_CALLWAIT);
06313       } else if (idx == SUB_THREEWAY) {
06314          if (p->subs[SUB_CALLWAIT].inthreeway) {
06315             /* The other party of the three way call is currently in a call-wait state.
06316                Start music on hold for them, and take the main guy out of the third call */
06317             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06318                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06319                   S_OR(p->mohsuggest, NULL),
06320                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06321             }
06322             p->subs[SUB_CALLWAIT].inthreeway = 0;
06323          }
06324          p->subs[SUB_REAL].inthreeway = 0;
06325          /* If this was part of a three way call index, let us make
06326             another three way call */
06327          unalloc_sub(p, SUB_THREEWAY);
06328       } else {
06329          /* This wasn't any sort of call, but how are we an index? */
06330          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06331       }
06332    }
06333 
06334    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06335       p->owner = NULL;
06336       p->ringt = 0;
06337       p->distinctivering = 0;
06338       p->confirmanswer = 0;
06339       p->outgoing = 0;
06340       p->digital = 0;
06341       p->faxhandled = 0;
06342       p->pulsedial = 0;
06343       if (p->dsp) {
06344          ast_dsp_free(p->dsp);
06345          p->dsp = NULL;
06346       }
06347 
06348       revert_fax_buffers(p, ast);
06349 
06350       p->law = p->law_default;
06351       law = p->law_default;
06352       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06353       if (res < 0)
06354          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06355       /* Perform low level hangup if no owner left */
06356 #ifdef HAVE_OPENR2
06357       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06358          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06359          /* If it's an incoming call, check the mfcr2_forced_release setting */
06360          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06361             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06362          } else {
06363             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06364             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06365             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06366                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06367             dahdi_r2_disconnect_call(p, r2cause);
06368          }
06369       } else if (p->mfcr2call) {
06370          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06371          /* since ast_request() was called but not ast_call() we have not yet dialed
06372          and the openr2 stack will not call on_call_end callback, we need to unset
06373          the mfcr2call flag and bump the monitor count so the monitor thread can take
06374          care of this channel events from now on */
06375          p->mfcr2call = 0;
06376       }
06377 #endif
06378       switch (p->sig) {
06379       case SIG_SS7:
06380       case SIG_MFCR2:
06381       case SIG_PRI_LIB_HANDLE_CASES:
06382       case 0:
06383          break;
06384       default:
06385          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06386          break;
06387       }
06388       if (res < 0) {
06389          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06390       }
06391       switch (p->sig) {
06392       case SIG_FXOGS:
06393       case SIG_FXOLS:
06394       case SIG_FXOKS:
06395          memset(&par, 0, sizeof(par));
06396          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06397          if (!res) {
06398             struct analog_pvt *analog_p = p->sig_pvt;
06399 #if 0
06400             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06401 #endif
06402             /* If they're off hook, try playing congestion */
06403             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06404                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06405             else
06406                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06407             analog_p->fxsoffhookstate = par.rxisoffhook;
06408          }
06409          break;
06410       case SIG_FXSGS:
06411       case SIG_FXSLS:
06412       case SIG_FXSKS:
06413          /* Make sure we're not made available for at least two seconds assuming
06414          we were actually used for an inbound or outbound call. */
06415          if (ast->_state != AST_STATE_RESERVED) {
06416             time(&p->guardtime);
06417             p->guardtime += 2;
06418          }
06419          break;
06420       default:
06421          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06422          break;
06423       }
06424       if (p->sig)
06425          dahdi_disable_ec(p);
06426       x = 0;
06427       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06428       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06429       p->didtdd = 0;
06430       p->callwaitcas = 0;
06431       p->callwaiting = p->permcallwaiting;
06432       p->hidecallerid = p->permhidecallerid;
06433       p->waitingfordt.tv_sec = 0;
06434       p->dialing = 0;
06435       p->rdnis[0] = '\0';
06436       update_conf(p);
06437       reset_conf(p);
06438       /* Restore data mode */
06439       switch (p->sig) {
06440       case SIG_PRI_LIB_HANDLE_CASES:
06441       case SIG_SS7:
06442          x = 0;
06443          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06444          break;
06445       default:
06446          break;
06447       }
06448       if (num_restart_pending == 0)
06449          restart_monitor();
06450    }
06451 
06452    p->callwaitingrepeat = 0;
06453    p->cidcwexpire = 0;
06454    p->cid_suppress_expire = 0;
06455    p->oprmode = 0;
06456 hangup_out:
06457    ast->tech_pvt = NULL;
06458    ast_free(p->cidspill);
06459    p->cidspill = NULL;
06460 
06461    ast_mutex_unlock(&p->lock);
06462    ast_verb(3, "Hungup '%s'\n", ast->name);
06463 
06464    ast_mutex_lock(&iflock);
06465    if (p->restartpending) {
06466       num_restart_pending--;
06467    }
06468 
06469    if (p->destroy) {
06470       destroy_channel(p, 0);
06471    }
06472    ast_mutex_unlock(&iflock);
06473 
06474    ast_module_unref(ast_module_info->self);
06475    return 0;
06476 }
06477 
06478 static int dahdi_answer(struct ast_channel *ast)
06479 {
06480    struct dahdi_pvt *p = ast->tech_pvt;
06481    int res = 0;
06482    int idx;
06483    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06484    ast_mutex_lock(&p->lock);
06485    idx = dahdi_get_index(ast, p, 0);
06486    if (idx < 0)
06487       idx = SUB_REAL;
06488    /* nothing to do if a radio channel */
06489    if ((p->radio || (p->oprmode < 0))) {
06490       ast_mutex_unlock(&p->lock);
06491       return 0;
06492    }
06493 
06494    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06495       res = analog_answer(p->sig_pvt, ast);
06496       ast_mutex_unlock(&p->lock);
06497       return res;
06498    }
06499 
06500    switch (p->sig) {
06501 #if defined(HAVE_PRI)
06502    case SIG_PRI_LIB_HANDLE_CASES:
06503       res = sig_pri_answer(p->sig_pvt, ast);
06504       break;
06505 #endif   /* defined(HAVE_PRI) */
06506 #if defined(HAVE_SS7)
06507    case SIG_SS7:
06508       res = sig_ss7_answer(p->sig_pvt, ast);
06509       break;
06510 #endif   /* defined(HAVE_SS7) */
06511 #ifdef HAVE_OPENR2
06512    case SIG_MFCR2:
06513       if (!p->mfcr2_call_accepted) {
06514          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06515             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06516          p->mfcr2_answer_pending = 1;
06517          if (p->mfcr2_charge_calls) {
06518             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06519             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06520          } else {
06521             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06522             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06523          }
06524       } else {
06525          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06526          dahdi_r2_answer(p);
06527       }
06528       break;
06529 #endif
06530    case 0:
06531       ast_mutex_unlock(&p->lock);
06532       return 0;
06533    default:
06534       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06535       res = -1;
06536       break;
06537    }
06538    ast_mutex_unlock(&p->lock);
06539    return res;
06540 }
06541 
06542 static void disable_dtmf_detect(struct dahdi_pvt *p)
06543 {
06544    int val = 0;
06545 
06546    p->ignoredtmf = 1;
06547 
06548    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06549 
06550    if (!p->hardwaredtmf && p->dsp) {
06551       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06552       ast_dsp_set_features(p->dsp, p->dsp_features);
06553    }
06554 }
06555 
06556 static void enable_dtmf_detect(struct dahdi_pvt *p)
06557 {
06558    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06559 
06560    if (p->channel == CHAN_PSEUDO)
06561       return;
06562 
06563    p->ignoredtmf = 0;
06564 
06565    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06566 
06567    if (!p->hardwaredtmf && p->dsp) {
06568       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06569       ast_dsp_set_features(p->dsp, p->dsp_features);
06570    }
06571 }
06572 
06573 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06574 {
06575    char *cp;
06576    struct dahdi_pvt *p = chan->tech_pvt;
06577 
06578    /* all supported options require data */
06579    if (!data || (*datalen < 1)) {
06580       errno = EINVAL;
06581       return -1;
06582    }
06583 
06584    switch (option) {
06585    case AST_OPTION_DIGIT_DETECT:
06586       cp = (char *) data;
06587       *cp = p->ignoredtmf ? 0 : 1;
06588       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06589       break;
06590    case AST_OPTION_FAX_DETECT:
06591       cp = (char *) data;
06592       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06593       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06594       break;
06595    case AST_OPTION_CC_AGENT_TYPE:
06596 #if defined(HAVE_PRI)
06597 #if defined(HAVE_PRI_CCSS)
06598       if (dahdi_sig_pri_lib_handles(p->sig)) {
06599          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06600          break;
06601       }
06602 #endif   /* defined(HAVE_PRI_CCSS) */
06603 #endif   /* defined(HAVE_PRI) */
06604       return -1;
06605    default:
06606       return -1;
06607    }
06608 
06609    errno = 0;
06610 
06611    return 0;
06612 }
06613 
06614 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06615 {
06616    char *cp;
06617    signed char *scp;
06618    int x;
06619    int idx;
06620    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06621    struct oprmode *oprmode;
06622 
06623 
06624    /* all supported options require data */
06625    if (!data || (datalen < 1)) {
06626       errno = EINVAL;
06627       return -1;
06628    }
06629 
06630    switch (option) {
06631    case AST_OPTION_TXGAIN:
06632       scp = (signed char *) data;
06633       idx = dahdi_get_index(chan, p, 0);
06634       if (idx < 0) {
06635          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06636          return -1;
06637       }
06638       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06639       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06640    case AST_OPTION_RXGAIN:
06641       scp = (signed char *) data;
06642       idx = dahdi_get_index(chan, p, 0);
06643       if (idx < 0) {
06644          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06645          return -1;
06646       }
06647       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06648       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06649    case AST_OPTION_TONE_VERIFY:
06650       if (!p->dsp)
06651          break;
06652       cp = (char *) data;
06653       switch (*cp) {
06654       case 1:
06655          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06656          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06657          break;
06658       case 2:
06659          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06660          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06661          break;
06662       default:
06663          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06664          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06665          break;
06666       }
06667       break;
06668    case AST_OPTION_TDD:
06669       /* turn on or off TDD */
06670       cp = (char *) data;
06671       p->mate = 0;
06672       if (!*cp) { /* turn it off */
06673          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06674          if (p->tdd)
06675             tdd_free(p->tdd);
06676          p->tdd = 0;
06677          break;
06678       }
06679       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06680          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06681       dahdi_disable_ec(p);
06682       /* otherwise, turn it on */
06683       if (!p->didtdd) { /* if havent done it yet */
06684          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06685          unsigned char *buf;
06686          int size, res, fd, len;
06687          struct pollfd fds[1];
06688 
06689          buf = mybuf;
06690          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06691          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06692          len = 40000;
06693          idx = dahdi_get_index(chan, p, 0);
06694          if (idx < 0) {
06695             ast_log(LOG_WARNING, "No index in TDD?\n");
06696             return -1;
06697          }
06698          fd = p->subs[idx].dfd;
06699          while (len) {
06700             if (ast_check_hangup(chan))
06701                return -1;
06702             size = len;
06703             if (size > READ_SIZE)
06704                size = READ_SIZE;
06705             fds[0].fd = fd;
06706             fds[0].events = POLLPRI | POLLOUT;
06707             fds[0].revents = 0;
06708             res = poll(fds, 1, -1);
06709             if (!res) {
06710                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06711                continue;
06712             }
06713             /* if got exception */
06714             if (fds[0].revents & POLLPRI)
06715                return -1;
06716             if (!(fds[0].revents & POLLOUT)) {
06717                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06718                continue;
06719             }
06720             res = write(fd, buf, size);
06721             if (res != size) {
06722                if (res == -1) return -1;
06723                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06724                break;
06725             }
06726             len -= size;
06727             buf += size;
06728          }
06729          p->didtdd = 1; /* set to have done it now */
06730       }
06731       if (*cp == 2) { /* Mate mode */
06732          if (p->tdd)
06733             tdd_free(p->tdd);
06734          p->tdd = 0;
06735          p->mate = 1;
06736          break;
06737       }
06738       if (!p->tdd) { /* if we don't have one yet */
06739          p->tdd = tdd_new(); /* allocate one */
06740       }
06741       break;
06742    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06743       if (!p->dsp)
06744          break;
06745       cp = (char *) data;
06746       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06747          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06748       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06749       break;
06750    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06751 #if defined(HAVE_PRI)
06752       if (dahdi_sig_pri_lib_handles(p->sig)
06753          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06754          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06755          break;
06756       }
06757 #endif   /* defined(HAVE_PRI) */
06758 
06759       cp = (char *) data;
06760       if (!*cp) {
06761          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06762          x = 0;
06763          dahdi_disable_ec(p);
06764       } else {
06765          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06766          x = 1;
06767       }
06768       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06769          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06770       break;
06771    case AST_OPTION_OPRMODE:  /* Operator services mode */
06772       oprmode = (struct oprmode *) data;
06773       /* We don't support operator mode across technologies */
06774       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06775          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06776                chan->tech->type, oprmode->peer->tech->type);
06777          errno = EINVAL;
06778          return -1;
06779       }
06780       pp = oprmode->peer->tech_pvt;
06781       p->oprmode = pp->oprmode = 0;
06782       /* setup peers */
06783       p->oprpeer = pp;
06784       pp->oprpeer = p;
06785       /* setup modes, if any */
06786       if (oprmode->mode)
06787       {
06788          pp->oprmode = oprmode->mode;
06789          p->oprmode = -oprmode->mode;
06790       }
06791       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06792          oprmode->mode, chan->name,oprmode->peer->name);
06793       break;
06794    case AST_OPTION_ECHOCAN:
06795       cp = (char *) data;
06796       if (*cp) {
06797          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06798          dahdi_enable_ec(p);
06799       } else {
06800          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06801          dahdi_disable_ec(p);
06802       }
06803       break;
06804    case AST_OPTION_DIGIT_DETECT:
06805       cp = (char *) data;
06806       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06807       if (*cp) {
06808          enable_dtmf_detect(p);
06809       } else {
06810          disable_dtmf_detect(p);
06811       }
06812       break;
06813    case AST_OPTION_FAX_DETECT:
06814       cp = (char *) data;
06815       if (p->dsp) {
06816          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06817          if (*cp) {
06818             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06819          } else {
06820             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06821          }
06822          ast_dsp_set_features(p->dsp, p->dsp_features);
06823       }
06824       break;
06825    default:
06826       return -1;
06827    }
06828    errno = 0;
06829 
06830    return 0;
06831 }
06832 
06833 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06834 {
06835    struct dahdi_pvt *p = chan->tech_pvt;
06836    int res = 0;
06837 
06838    if (!strcasecmp(data, "rxgain")) {
06839       ast_mutex_lock(&p->lock);
06840       snprintf(buf, len, "%f", p->rxgain);
06841       ast_mutex_unlock(&p->lock);
06842    } else if (!strcasecmp(data, "txgain")) {
06843       ast_mutex_lock(&p->lock);
06844       snprintf(buf, len, "%f", p->txgain);
06845       ast_mutex_unlock(&p->lock);
06846    } else if (!strcasecmp(data, "dahdi_channel")) {
06847       ast_mutex_lock(&p->lock);
06848       snprintf(buf, len, "%d", p->channel);
06849       ast_mutex_unlock(&p->lock);
06850    } else if (!strcasecmp(data, "dahdi_span")) {
06851       ast_mutex_lock(&p->lock);
06852       snprintf(buf, len, "%d", p->span);
06853       ast_mutex_unlock(&p->lock);
06854    } else if (!strcasecmp(data, "dahdi_type")) {
06855       ast_mutex_lock(&p->lock);
06856       switch (p->sig) {
06857 #if defined(HAVE_OPENR2)
06858       case SIG_MFCR2:
06859          ast_copy_string(buf, "mfc/r2", len);
06860          break;
06861 #endif   /* defined(HAVE_OPENR2) */
06862 #if defined(HAVE_PRI)
06863       case SIG_PRI_LIB_HANDLE_CASES:
06864          ast_copy_string(buf, "pri", len);
06865          break;
06866 #endif   /* defined(HAVE_PRI) */
06867       case 0:
06868          ast_copy_string(buf, "pseudo", len);
06869          break;
06870 #if defined(HAVE_SS7)
06871       case SIG_SS7:
06872          ast_copy_string(buf, "ss7", len);
06873          break;
06874 #endif   /* defined(HAVE_SS7) */
06875       default:
06876          /* The only thing left is analog ports. */
06877          ast_copy_string(buf, "analog", len);
06878          break;
06879       }
06880       ast_mutex_unlock(&p->lock);
06881 #if defined(HAVE_PRI)
06882 #if defined(HAVE_PRI_REVERSE_CHARGE)
06883    } else if (!strcasecmp(data, "reversecharge")) {
06884       ast_mutex_lock(&p->lock);
06885       switch (p->sig) {
06886       case SIG_PRI_LIB_HANDLE_CASES:
06887          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06888          break;
06889       default:
06890          *buf = '\0';
06891          res = -1;
06892          break;
06893       }
06894       ast_mutex_unlock(&p->lock);
06895 #endif
06896 #if defined(HAVE_PRI_SETUP_KEYPAD)
06897    } else if (!strcasecmp(data, "keypad_digits")) {
06898       ast_mutex_lock(&p->lock);
06899       switch (p->sig) {
06900       case SIG_PRI_LIB_HANDLE_CASES:
06901          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06902             len);
06903          break;
06904       default:
06905          *buf = '\0';
06906          res = -1;
06907          break;
06908       }
06909       ast_mutex_unlock(&p->lock);
06910 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06911    } else if (!strcasecmp(data, "no_media_path")) {
06912       ast_mutex_lock(&p->lock);
06913       switch (p->sig) {
06914       case SIG_PRI_LIB_HANDLE_CASES:
06915          /*
06916           * TRUE if the call is on hold or is call waiting because
06917           * there is no media path available.
06918           */
06919          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06920          break;
06921       default:
06922          *buf = '\0';
06923          res = -1;
06924          break;
06925       }
06926       ast_mutex_unlock(&p->lock);
06927 #endif   /* defined(HAVE_PRI) */
06928    } else {
06929       *buf = '\0';
06930       res = -1;
06931    }
06932 
06933    return res;
06934 }
06935 
06936 
06937 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06938 {
06939    int res;
06940    char policy_str[21] = "";
06941 
06942    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06943       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06944       return 1;
06945    }
06946    if (*num_buffers < 0) {
06947       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06948       return -1;
06949    }
06950    if (!strcasecmp(policy_str, "full")) {
06951       *policy = DAHDI_POLICY_WHEN_FULL;
06952    } else if (!strcasecmp(policy_str, "immediate")) {
06953       *policy = DAHDI_POLICY_IMMEDIATE;
06954 #if defined(HAVE_DAHDI_HALF_FULL)
06955    } else if (!strcasecmp(policy_str, "half")) {
06956       *policy = DAHDI_POLICY_HALF_FULL;
06957 #endif
06958    } else {
06959       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06960       return -1;
06961    }
06962 
06963    return 0;
06964 }
06965 
06966 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06967 {
06968    struct dahdi_pvt *p = chan->tech_pvt;
06969    int res = 0;
06970 
06971    if (!strcasecmp(data, "buffers")) {
06972       int num_bufs, policy;
06973 
06974       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06975          struct dahdi_bufferinfo bi = {
06976             .txbufpolicy = policy,
06977             .rxbufpolicy = policy,
06978             .bufsize = p->bufsize,
06979             .numbufs = num_bufs,
06980          };
06981          int bpres;
06982 
06983          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06984             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06985          } else {
06986             p->bufferoverrideinuse = 1;
06987          }
06988       } else {
06989          res = -1;
06990       }
06991    } else if (!strcasecmp(data, "echocan_mode")) {
06992       if (!strcasecmp(value, "on")) {
06993          ast_mutex_lock(&p->lock);
06994          dahdi_enable_ec(p);
06995          ast_mutex_unlock(&p->lock);
06996       } else if (!strcasecmp(value, "off")) {
06997          ast_mutex_lock(&p->lock);
06998          dahdi_disable_ec(p);
06999          ast_mutex_unlock(&p->lock);
07000 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07001       } else if (!strcasecmp(value, "fax")) {
07002          int blah = 1;
07003 
07004          ast_mutex_lock(&p->lock);
07005          if (!p->echocanon) {
07006             dahdi_enable_ec(p);
07007          }
07008          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07009             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07010          }
07011          ast_mutex_unlock(&p->lock);
07012       } else if (!strcasecmp(value, "voice")) {
07013          int blah = 0;
07014 
07015          ast_mutex_lock(&p->lock);
07016          if (!p->echocanon) {
07017             dahdi_enable_ec(p);
07018          }
07019          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07020             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07021          }
07022          ast_mutex_unlock(&p->lock);
07023 #endif
07024       } else {
07025          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07026          res = -1;
07027       }
07028    } else {
07029       res = -1;
07030    }
07031 
07032    return res;
07033 }
07034 
07035 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07036 {
07037    /* Unlink a specific slave or all slaves/masters from a given master */
07038    int x;
07039    int hasslaves;
07040    if (!master)
07041       return;
07042    if (needlock) {
07043       ast_mutex_lock(&master->lock);
07044       if (slave) {
07045          while (ast_mutex_trylock(&slave->lock)) {
07046             DEADLOCK_AVOIDANCE(&master->lock);
07047          }
07048       }
07049    }
07050    hasslaves = 0;
07051    for (x = 0; x < MAX_SLAVES; x++) {
07052       if (master->slaves[x]) {
07053          if (!slave || (master->slaves[x] == slave)) {
07054             /* Take slave out of the conference */
07055             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07056             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07057             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07058             master->slaves[x]->master = NULL;
07059             master->slaves[x] = NULL;
07060          } else
07061             hasslaves = 1;
07062       }
07063       if (!hasslaves)
07064          master->inconference = 0;
07065    }
07066    if (!slave) {
07067       if (master->master) {
07068          /* Take master out of the conference */
07069          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07070          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07071          hasslaves = 0;
07072          for (x = 0; x < MAX_SLAVES; x++) {
07073             if (master->master->slaves[x] == master)
07074                master->master->slaves[x] = NULL;
07075             else if (master->master->slaves[x])
07076                hasslaves = 1;
07077          }
07078          if (!hasslaves)
07079             master->master->inconference = 0;
07080       }
07081       master->master = NULL;
07082    }
07083    update_conf(master);
07084    if (needlock) {
07085       if (slave)
07086          ast_mutex_unlock(&slave->lock);
07087       ast_mutex_unlock(&master->lock);
07088    }
07089 }
07090 
07091 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07092    int x;
07093    if (!slave || !master) {
07094       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07095       return;
07096    }
07097    for (x = 0; x < MAX_SLAVES; x++) {
07098       if (!master->slaves[x]) {
07099          master->slaves[x] = slave;
07100          break;
07101       }
07102    }
07103    if (x >= MAX_SLAVES) {
07104       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07105       master->slaves[MAX_SLAVES - 1] = slave;
07106    }
07107    if (slave->master)
07108       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07109    slave->master = master;
07110 
07111    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07112 }
07113 
07114 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)
07115 {
07116    struct ast_channel *who;
07117    struct dahdi_pvt *p0, *p1, *op0, *op1;
07118    struct dahdi_pvt *master = NULL, *slave = NULL;
07119    struct ast_frame *f;
07120    int inconf = 0;
07121    int nothingok = 1;
07122    int ofd0, ofd1;
07123    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07124    int os0 = -1, os1 = -1;
07125    int priority = 0;
07126    struct ast_channel *oc0, *oc1;
07127    enum ast_bridge_result res;
07128 #ifdef PRI_2BCT
07129    int triedtopribridge = 0;
07130    q931_call *q931c0;
07131    q931_call *q931c1;
07132 #endif
07133 
07134    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07135       There is code below to handle it properly until DTMF is actually seen,
07136       but due to currently unresolved issues it's ignored...
07137    */
07138 
07139    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07140       return AST_BRIDGE_FAILED_NOWARN;
07141 
07142    ast_channel_lock(c0);
07143    while (ast_channel_trylock(c1)) {
07144       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07145    }
07146 
07147    p0 = c0->tech_pvt;
07148    p1 = c1->tech_pvt;
07149    /* cant do pseudo-channels here */
07150    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07151       ast_channel_unlock(c0);
07152       ast_channel_unlock(c1);
07153       return AST_BRIDGE_FAILED_NOWARN;
07154    }
07155 
07156    oi0 = dahdi_get_index(c0, p0, 0);
07157    oi1 = dahdi_get_index(c1, p1, 0);
07158    if ((oi0 < 0) || (oi1 < 0)) {
07159       ast_channel_unlock(c0);
07160       ast_channel_unlock(c1);
07161       return AST_BRIDGE_FAILED;
07162    }
07163 
07164    op0 = p0 = c0->tech_pvt;
07165    op1 = p1 = c1->tech_pvt;
07166    ofd0 = c0->fds[0];
07167    ofd1 = c1->fds[0];
07168    oc0 = p0->owner;
07169    oc1 = p1->owner;
07170 
07171    if (ast_mutex_trylock(&p0->lock)) {
07172       /* Don't block, due to potential for deadlock */
07173       ast_channel_unlock(c0);
07174       ast_channel_unlock(c1);
07175       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07176       return AST_BRIDGE_RETRY;
07177    }
07178    if (ast_mutex_trylock(&p1->lock)) {
07179       /* Don't block, due to potential for deadlock */
07180       ast_mutex_unlock(&p0->lock);
07181       ast_channel_unlock(c0);
07182       ast_channel_unlock(c1);
07183       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07184       return AST_BRIDGE_RETRY;
07185    }
07186 
07187    if ((p0->callwaiting && p0->callwaitingcallerid)
07188       || (p1->callwaiting && p1->callwaitingcallerid)) {
07189       /*
07190        * Call Waiting Caller ID requires DTMF detection to know if it
07191        * can send the CID spill.
07192        *
07193        * For now, don't attempt to native bridge if either channel
07194        * needs DTMF detection.  There is code below to handle it
07195        * properly until DTMF is actually seen, but due to currently
07196        * unresolved issues it's ignored...
07197        */
07198       ast_mutex_unlock(&p0->lock);
07199       ast_mutex_unlock(&p1->lock);
07200       ast_channel_unlock(c0);
07201       ast_channel_unlock(c1);
07202       return AST_BRIDGE_FAILED_NOWARN;
07203    }
07204 
07205 #if defined(HAVE_PRI)
07206    if ((dahdi_sig_pri_lib_handles(p0->sig)
07207          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07208       || (dahdi_sig_pri_lib_handles(p1->sig)
07209          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07210       /*
07211        * PRI nobch channels (hold and call waiting) are equivalent to
07212        * pseudo channels and cannot be done here.
07213        */
07214       ast_mutex_unlock(&p0->lock);
07215       ast_mutex_unlock(&p1->lock);
07216       ast_channel_unlock(c0);
07217       ast_channel_unlock(c1);
07218       return AST_BRIDGE_FAILED_NOWARN;
07219    }
07220 #endif   /* defined(HAVE_PRI) */
07221 
07222    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07223       if (p0->owner && p1->owner) {
07224          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07225          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07226             master = p0;
07227             slave = p1;
07228             inconf = 1;
07229          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07230             master = p1;
07231             slave = p0;
07232             inconf = 1;
07233          } else {
07234             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07235             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07236                p0->channel,
07237                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07238                p0->subs[SUB_REAL].inthreeway, p0->channel,
07239                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07240                p1->subs[SUB_REAL].inthreeway);
07241          }
07242          nothingok = 0;
07243       }
07244    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07245       if (p1->subs[SUB_THREEWAY].inthreeway) {
07246          master = p1;
07247          slave = p0;
07248          nothingok = 0;
07249       }
07250    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07251       if (p0->subs[SUB_THREEWAY].inthreeway) {
07252          master = p0;
07253          slave = p1;
07254          nothingok = 0;
07255       }
07256    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07257       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07258          don't put us in anything */
07259       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07260          master = p1;
07261          slave = p0;
07262          nothingok = 0;
07263       }
07264    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07265       /* Same as previous */
07266       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07267          master = p0;
07268          slave = p1;
07269          nothingok = 0;
07270       }
07271    }
07272    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07273       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07274    if (master && slave) {
07275       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07276          in an active threeway call with a channel that is ringing, we should
07277          indicate ringing. */
07278       if ((oi1 == SUB_THREEWAY) &&
07279          p1->subs[SUB_THREEWAY].inthreeway &&
07280          p1->subs[SUB_REAL].owner &&
07281          p1->subs[SUB_REAL].inthreeway &&
07282          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07283          ast_debug(1,
07284             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07285             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07286          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07287          os1 = p1->subs[SUB_REAL].owner->_state;
07288       } else {
07289          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07290             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07291          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07292       }
07293       if ((oi0 == SUB_THREEWAY) &&
07294          p0->subs[SUB_THREEWAY].inthreeway &&
07295          p0->subs[SUB_REAL].owner &&
07296          p0->subs[SUB_REAL].inthreeway &&
07297          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07298          ast_debug(1,
07299             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07300             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07301          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07302          os0 = p0->subs[SUB_REAL].owner->_state;
07303       } else {
07304          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07305             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07306          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07307       }
07308       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07309          if (!p0->echocanbridged || !p1->echocanbridged) {
07310             /* Disable echo cancellation if appropriate */
07311             dahdi_disable_ec(p0);
07312             dahdi_disable_ec(p1);
07313          }
07314       }
07315       dahdi_link(slave, master);
07316       master->inconference = inconf;
07317    } else if (!nothingok)
07318       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07319 
07320    update_conf(p0);
07321    update_conf(p1);
07322    t0 = p0->subs[SUB_REAL].inthreeway;
07323    t1 = p1->subs[SUB_REAL].inthreeway;
07324 
07325    ast_mutex_unlock(&p0->lock);
07326    ast_mutex_unlock(&p1->lock);
07327 
07328    ast_channel_unlock(c0);
07329    ast_channel_unlock(c1);
07330 
07331    /* Native bridge failed */
07332    if ((!master || !slave) && !nothingok) {
07333       dahdi_enable_ec(p0);
07334       dahdi_enable_ec(p1);
07335       return AST_BRIDGE_FAILED;
07336    }
07337 
07338    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07339 
07340    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07341       disable_dtmf_detect(op0);
07342 
07343    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07344       disable_dtmf_detect(op1);
07345 
07346    for (;;) {
07347       struct ast_channel *c0_priority[2] = {c0, c1};
07348       struct ast_channel *c1_priority[2] = {c1, c0};
07349 
07350       /* Here's our main loop...  Start by locking things, looking for private parts,
07351          and then balking if anything is wrong */
07352 
07353       ast_channel_lock(c0);
07354       while (ast_channel_trylock(c1)) {
07355          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07356       }
07357 
07358       p0 = c0->tech_pvt;
07359       p1 = c1->tech_pvt;
07360 
07361       if (op0 == p0)
07362          i0 = dahdi_get_index(c0, p0, 1);
07363       if (op1 == p1)
07364          i1 = dahdi_get_index(c1, p1, 1);
07365 
07366       ast_channel_unlock(c0);
07367       ast_channel_unlock(c1);
07368 
07369       if (!timeoutms ||
07370          (op0 != p0) ||
07371          (op1 != p1) ||
07372          (ofd0 != c0->fds[0]) ||
07373          (ofd1 != c1->fds[0]) ||
07374          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07375          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07376          (oc0 != p0->owner) ||
07377          (oc1 != p1->owner) ||
07378          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07379          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07380          (oi0 != i0) ||
07381          (oi1 != i1)) {
07382          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07383             op0->channel, oi0, op1->channel, oi1);
07384          res = AST_BRIDGE_RETRY;
07385          goto return_from_bridge;
07386       }
07387 
07388 #ifdef PRI_2BCT
07389       if (!triedtopribridge) {
07390          triedtopribridge = 1;
07391          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07392             ast_mutex_lock(&p0->pri->lock);
07393             switch (p0->sig) {
07394             case SIG_PRI_LIB_HANDLE_CASES:
07395                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07396                break;
07397             default:
07398                q931c0 = NULL;
07399                break;
07400             }
07401             switch (p1->sig) {
07402             case SIG_PRI_LIB_HANDLE_CASES:
07403                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07404                break;
07405             default:
07406                q931c1 = NULL;
07407                break;
07408             }
07409             if (q931c0 && q931c1) {
07410                pri_channel_bridge(q931c0, q931c1);
07411             }
07412             ast_mutex_unlock(&p0->pri->lock);
07413          }
07414       }
07415 #endif
07416 
07417       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07418       if (!who) {
07419          ast_debug(1, "Ooh, empty read...\n");
07420          continue;
07421       }
07422       f = ast_read(who);
07423       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07424          *fo = f;
07425          *rc = who;
07426          res = AST_BRIDGE_COMPLETE;
07427          goto return_from_bridge;
07428       }
07429       if (f->frametype == AST_FRAME_DTMF) {
07430          if ((who == c0) && p0->pulsedial) {
07431             ast_write(c1, f);
07432          } else if ((who == c1) && p1->pulsedial) {
07433             ast_write(c0, f);
07434          } else {
07435             *fo = f;
07436             *rc = who;
07437             res = AST_BRIDGE_COMPLETE;
07438             goto return_from_bridge;
07439          }
07440       }
07441       ast_frfree(f);
07442 
07443       /* Swap who gets priority */
07444       priority = !priority;
07445    }
07446 
07447 return_from_bridge:
07448    if (op0 == p0)
07449       dahdi_enable_ec(p0);
07450 
07451    if (op1 == p1)
07452       dahdi_enable_ec(p1);
07453 
07454    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07455       enable_dtmf_detect(op0);
07456 
07457    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07458       enable_dtmf_detect(op1);
07459 
07460    dahdi_unlink(slave, master, 1);
07461 
07462    return res;
07463 }
07464 
07465 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07466 {
07467    struct dahdi_pvt *p = newchan->tech_pvt;
07468    int x;
07469 
07470    ast_mutex_lock(&p->lock);
07471 
07472    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07473    if (p->owner == oldchan) {
07474       p->owner = newchan;
07475    }
07476    for (x = 0; x < 3; x++) {
07477       if (p->subs[x].owner == oldchan) {
07478          if (!x) {
07479             dahdi_unlink(NULL, p, 0);
07480          }
07481          p->subs[x].owner = newchan;
07482       }
07483    }
07484    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07485       analog_fixup(oldchan, newchan, p->sig_pvt);
07486 #if defined(HAVE_PRI)
07487    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07488       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07489 #endif   /* defined(HAVE_PRI) */
07490 #if defined(HAVE_SS7)
07491    } else if (p->sig == SIG_SS7) {
07492       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07493 #endif   /* defined(HAVE_SS7) */
07494    }
07495    update_conf(p);
07496 
07497    ast_mutex_unlock(&p->lock);
07498 
07499    if (newchan->_state == AST_STATE_RINGING) {
07500       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07501    }
07502    return 0;
07503 }
07504 
07505 static int dahdi_ring_phone(struct dahdi_pvt *p)
07506 {
07507    int x;
07508    int res;
07509    /* Make sure our transmit state is on hook */
07510    x = 0;
07511    x = DAHDI_ONHOOK;
07512    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07513    do {
07514       x = DAHDI_RING;
07515       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07516       if (res) {
07517          switch (errno) {
07518          case EBUSY:
07519          case EINTR:
07520             /* Wait just in case */
07521             usleep(10000);
07522             continue;
07523          case EINPROGRESS:
07524             res = 0;
07525             break;
07526          default:
07527             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07528             res = 0;
07529          }
07530       }
07531    } while (res);
07532    return res;
07533 }
07534 
07535 static void *analog_ss_thread(void *data);
07536 
07537 static int attempt_transfer(struct dahdi_pvt *p)
07538 {
07539    /* In order to transfer, we need at least one of the channels to
07540       actually be in a call bridge.  We can't conference two applications
07541       together (but then, why would we want to?) */
07542    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07543       /* The three-way person we're about to transfer to could still be in MOH, so
07544          stop if now if appropriate */
07545       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07546          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07547       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07548          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07549       }
07550       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07551          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07552       }
07553        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07554          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07555                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07556          return -1;
07557       }
07558       /* Orphan the channel after releasing the lock */
07559       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07560       unalloc_sub(p, SUB_THREEWAY);
07561    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07562       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07563       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07564          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07565       }
07566       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07567          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07568       }
07569       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07570          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07571                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07572          return -1;
07573       }
07574       /* Three-way is now the REAL */
07575       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07576       ast_channel_unlock(p->subs[SUB_REAL].owner);
07577       unalloc_sub(p, SUB_THREEWAY);
07578       /* Tell the caller not to hangup */
07579       return 1;
07580    } else {
07581       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07582          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07583       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07584       return -1;
07585    }
07586    return 0;
07587 }
07588 
07589 static int check_for_conference(struct dahdi_pvt *p)
07590 {
07591    struct dahdi_confinfo ci;
07592    /* Fine if we already have a master, etc */
07593    if (p->master || (p->confno > -1))
07594       return 0;
07595    memset(&ci, 0, sizeof(ci));
07596    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07597       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07598       return 0;
07599    }
07600    /* If we have no master and don't have a confno, then
07601       if we're in a conference, it's probably a MeetMe room or
07602       some such, so don't let us 3-way out! */
07603    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07604       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07605       return 1;
07606    }
07607    return 0;
07608 }
07609 
07610 /*! Checks channel for alarms
07611  * \param p a channel to check for alarms.
07612  * \returns the alarms on the span to which the channel belongs, or alarms on
07613  *          the channel if no span alarms.
07614  */
07615 static int get_alarms(struct dahdi_pvt *p)
07616 {
07617    int res;
07618    struct dahdi_spaninfo zi;
07619    struct dahdi_params params;
07620 
07621    memset(&zi, 0, sizeof(zi));
07622    zi.spanno = p->span;
07623 
07624    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07625       if (zi.alarms != DAHDI_ALARM_NONE)
07626          return zi.alarms;
07627    } else {
07628       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07629       return 0;
07630    }
07631 
07632    /* No alarms on the span. Check for channel alarms. */
07633    memset(&params, 0, sizeof(params));
07634    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07635       return params.chan_alarms;
07636 
07637    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07638 
07639    return DAHDI_ALARM_NONE;
07640 }
07641 
07642 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07643 {
07644    struct dahdi_pvt *p = ast->tech_pvt;
07645    struct ast_frame *f = *dest;
07646 
07647    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07648       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07649       f->subclass.integer, f->subclass.integer, ast->name);
07650 
07651    if (p->confirmanswer) {
07652       if (f->frametype == AST_FRAME_DTMF_END) {
07653          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07654          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07655             of a DTMF digit */
07656          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07657          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07658          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07659          p->confirmanswer = 0;
07660       } else {
07661          p->subs[idx].f.frametype = AST_FRAME_NULL;
07662          p->subs[idx].f.subclass.integer = 0;
07663       }
07664       *dest = &p->subs[idx].f;
07665    } else if (p->callwaitcas) {
07666       if (f->frametype == AST_FRAME_DTMF_END) {
07667          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07668             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07669             ast_free(p->cidspill);
07670             p->cidspill = NULL;
07671             send_cwcidspill(p);
07672          }
07673          p->callwaitcas = 0;
07674       }
07675       p->subs[idx].f.frametype = AST_FRAME_NULL;
07676       p->subs[idx].f.subclass.integer = 0;
07677       *dest = &p->subs[idx].f;
07678    } else if (f->subclass.integer == 'f') {
07679       if (f->frametype == AST_FRAME_DTMF_END) {
07680          /* Fax tone -- Handle and return NULL */
07681          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07682             /* If faxbuffers are configured, use them for the fax transmission */
07683             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07684                struct dahdi_bufferinfo bi = {
07685                   .txbufpolicy = p->faxbuf_policy,
07686                   .bufsize = p->bufsize,
07687                   .numbufs = p->faxbuf_no
07688                };
07689                int res;
07690 
07691                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07692                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07693                } else {
07694                   p->bufferoverrideinuse = 1;
07695                }
07696             }
07697             p->faxhandled = 1;
07698             if (p->dsp) {
07699                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07700                ast_dsp_set_features(p->dsp, p->dsp_features);
07701                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07702             }
07703             if (strcmp(ast->exten, "fax")) {
07704                const char *target_context = S_OR(ast->macrocontext, ast->context);
07705 
07706                /* We need to unlock 'ast' here because ast_exists_extension has the
07707                 * potential to start autoservice on the channel. Such action is prone
07708                 * to deadlock.
07709                 */
07710                ast_mutex_unlock(&p->lock);
07711                ast_channel_unlock(ast);
07712                if (ast_exists_extension(ast, target_context, "fax", 1,
07713                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07714                   ast_channel_lock(ast);
07715                   ast_mutex_lock(&p->lock);
07716                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07717                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07718                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07719                   if (ast_async_goto(ast, target_context, "fax", 1))
07720                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07721                } else {
07722                   ast_channel_lock(ast);
07723                   ast_mutex_lock(&p->lock);
07724                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07725                }
07726             } else {
07727                ast_debug(1, "Already in a fax extension, not redirecting\n");
07728             }
07729          } else {
07730             ast_debug(1, "Fax already handled\n");
07731          }
07732          dahdi_confmute(p, 0);
07733       }
07734       p->subs[idx].f.frametype = AST_FRAME_NULL;
07735       p->subs[idx].f.subclass.integer = 0;
07736       *dest = &p->subs[idx].f;
07737    }
07738 }
07739 
07740 static void handle_alarms(struct dahdi_pvt *p, int alms)
07741 {
07742    const char *alarm_str = alarm2str(alms);
07743 
07744    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07745       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07746       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07747                  "Alarm: %s\r\n"
07748                  "Channel: %d\r\n",
07749                  alarm_str, p->channel);
07750    }
07751 
07752    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07753       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07754       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07755                  "Alarm: %s\r\n"
07756                  "Span: %d\r\n",
07757                  alarm_str, p->span);
07758    }
07759 }
07760 
07761 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07762 {
07763    int res, x;
07764    int idx, mysig;
07765    char *c;
07766    struct dahdi_pvt *p = ast->tech_pvt;
07767    pthread_t threadid;
07768    struct ast_channel *chan;
07769    struct ast_frame *f;
07770 
07771    idx = dahdi_get_index(ast, p, 0);
07772    mysig = p->sig;
07773    if (p->outsigmod > -1)
07774       mysig = p->outsigmod;
07775    p->subs[idx].f.frametype = AST_FRAME_NULL;
07776    p->subs[idx].f.subclass.integer = 0;
07777    p->subs[idx].f.datalen = 0;
07778    p->subs[idx].f.samples = 0;
07779    p->subs[idx].f.mallocd = 0;
07780    p->subs[idx].f.offset = 0;
07781    p->subs[idx].f.src = "dahdi_handle_event";
07782    p->subs[idx].f.data.ptr = NULL;
07783    f = &p->subs[idx].f;
07784 
07785    if (idx < 0)
07786       return &p->subs[idx].f;
07787    if (p->fake_event) {
07788       res = p->fake_event;
07789       p->fake_event = 0;
07790    } else
07791       res = dahdi_get_event(p->subs[idx].dfd);
07792 
07793    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07794 
07795    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07796       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07797       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07798 #if defined(HAVE_PRI)
07799       if (dahdi_sig_pri_lib_handles(p->sig)
07800          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07801          && p->pri
07802          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07803          /* absorb event */
07804       } else
07805 #endif   /* defined(HAVE_PRI) */
07806       {
07807          /* Unmute conference */
07808          dahdi_confmute(p, 0);
07809          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07810          p->subs[idx].f.subclass.integer = res & 0xff;
07811          dahdi_handle_dtmf(ast, idx, &f);
07812       }
07813       return f;
07814    }
07815 
07816    if (res & DAHDI_EVENT_DTMFDOWN) {
07817       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07818 #if defined(HAVE_PRI)
07819       if (dahdi_sig_pri_lib_handles(p->sig)
07820          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07821          && p->pri
07822          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07823          /* absorb event */
07824       } else
07825 #endif   /* defined(HAVE_PRI) */
07826       {
07827          /* Mute conference */
07828          dahdi_confmute(p, 1);
07829          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07830          p->subs[idx].f.subclass.integer = res & 0xff;
07831          dahdi_handle_dtmf(ast, idx, &f);
07832       }
07833       return &p->subs[idx].f;
07834    }
07835 
07836    switch (res) {
07837    case DAHDI_EVENT_EC_DISABLED:
07838       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07839       p->echocanon = 0;
07840       break;
07841 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07842    case DAHDI_EVENT_TX_CED_DETECTED:
07843       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07844       break;
07845    case DAHDI_EVENT_RX_CED_DETECTED:
07846       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07847       break;
07848    case DAHDI_EVENT_EC_NLP_DISABLED:
07849       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07850       break;
07851    case DAHDI_EVENT_EC_NLP_ENABLED:
07852       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07853       break;
07854 #endif
07855    case DAHDI_EVENT_BITSCHANGED:
07856 #ifdef HAVE_OPENR2
07857       if (p->sig != SIG_MFCR2) {
07858          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07859       } else {
07860          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07861          openr2_chan_handle_cas(p->r2chan);
07862       }
07863 #else
07864       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07865 #endif
07866    case DAHDI_EVENT_PULSE_START:
07867       /* Stop tone if there's a pulse start and the PBX isn't started */
07868       if (!ast->pbx)
07869          tone_zone_play_tone(p->subs[idx].dfd, -1);
07870       break;
07871    case DAHDI_EVENT_DIALCOMPLETE:
07872 #ifdef HAVE_OPENR2
07873       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07874          /* we don't need to do anything for this event for R2 signaling
07875             if the call is being setup */
07876          break;
07877       }
07878 #endif
07879       if (p->inalarm) break;
07880       if ((p->radio || (p->oprmode < 0))) break;
07881       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07882          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07883          return NULL;
07884       }
07885       if (!x) { /* if not still dialing in driver */
07886          dahdi_enable_ec(p);
07887          if (p->echobreak) {
07888             dahdi_train_ec(p);
07889             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07890             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07891             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07892             p->echobreak = 0;
07893          } else {
07894             p->dialing = 0;
07895             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07896                /* if thru with dialing after offhook */
07897                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07898                   ast_setstate(ast, AST_STATE_UP);
07899                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07900                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07901                   break;
07902                } else { /* if to state wait for offhook to dial rest */
07903                   /* we now wait for off hook */
07904                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07905                }
07906             }
07907             if (ast->_state == AST_STATE_DIALING) {
07908                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07909                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07910                } else if (p->confirmanswer || (!p->dialednone
07911                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07912                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07913                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07914                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07915                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07916                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07917                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07918                      || (mysig == SIG_SF_FEATB)))) {
07919                   ast_setstate(ast, AST_STATE_RINGING);
07920                } else if (!p->answeronpolarityswitch) {
07921                   ast_setstate(ast, AST_STATE_UP);
07922                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07923                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07924                   /* If aops=0 and hops=1, this is necessary */
07925                   p->polarity = POLARITY_REV;
07926                } else {
07927                   /* Start clean, so we can catch the change to REV polarity when party answers */
07928                   p->polarity = POLARITY_IDLE;
07929                }
07930             }
07931          }
07932       }
07933       break;
07934    case DAHDI_EVENT_ALARM:
07935       switch (p->sig) {
07936 #if defined(HAVE_PRI)
07937       case SIG_PRI_LIB_HANDLE_CASES:
07938          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07939          break;
07940 #endif   /* defined(HAVE_PRI) */
07941 #if defined(HAVE_SS7)
07942       case SIG_SS7:
07943          sig_ss7_set_alarm(p->sig_pvt, 1);
07944          break;
07945 #endif   /* defined(HAVE_SS7) */
07946       default:
07947          p->inalarm = 1;
07948          break;
07949       }
07950       res = get_alarms(p);
07951       handle_alarms(p, res);
07952 #ifdef HAVE_PRI
07953       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07954          /* fall through intentionally */
07955       } else {
07956          break;
07957       }
07958 #endif
07959 #if defined(HAVE_SS7)
07960       if (p->sig == SIG_SS7)
07961          break;
07962 #endif   /* defined(HAVE_SS7) */
07963 #ifdef HAVE_OPENR2
07964       if (p->sig == SIG_MFCR2)
07965          break;
07966 #endif
07967    case DAHDI_EVENT_ONHOOK:
07968       if (p->radio) {
07969          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07970          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07971          break;
07972       }
07973       if (p->oprmode < 0)
07974       {
07975          if (p->oprmode != -1) break;
07976          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07977          {
07978             /* Make sure it starts ringing */
07979             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07980             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07981             save_conference(p->oprpeer);
07982             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07983          }
07984          break;
07985       }
07986       switch (p->sig) {
07987       case SIG_FXOLS:
07988       case SIG_FXOGS:
07989       case SIG_FXOKS:
07990          /* Check for some special conditions regarding call waiting */
07991          if (idx == SUB_REAL) {
07992             /* The normal line was hung up */
07993             if (p->subs[SUB_CALLWAIT].owner) {
07994                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
07995                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07996                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07997                unalloc_sub(p, SUB_CALLWAIT);
07998 #if 0
07999                p->subs[idx].needanswer = 0;
08000                p->subs[idx].needringing = 0;
08001 #endif
08002                p->callwaitingrepeat = 0;
08003                p->cidcwexpire = 0;
08004                p->cid_suppress_expire = 0;
08005                p->owner = NULL;
08006                /* Don't start streaming audio yet if the incoming call isn't up yet */
08007                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08008                   p->dialing = 1;
08009                dahdi_ring_phone(p);
08010             } else if (p->subs[SUB_THREEWAY].owner) {
08011                unsigned int mssinceflash;
08012                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08013                   the private structure -- not especially easy or clean */
08014                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08015                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08016                   DLA_UNLOCK(&p->lock);
08017                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08018                   /* We can grab ast and p in that order, without worry.  We should make sure
08019                      nothing seriously bad has happened though like some sort of bizarre double
08020                      masquerade! */
08021                   DLA_LOCK(&p->lock);
08022                   if (p->owner != ast) {
08023                      ast_log(LOG_WARNING, "This isn't good...\n");
08024                      return NULL;
08025                   }
08026                }
08027                if (!p->subs[SUB_THREEWAY].owner) {
08028                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08029                   return NULL;
08030                }
08031                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08032                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08033                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08034                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08035                      hanging up.  Hangup both channels now */
08036                   if (p->subs[SUB_THREEWAY].owner)
08037                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08038                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08039                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08040                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08041                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08042                   if (p->transfer) {
08043                      /* In any case this isn't a threeway call anymore */
08044                      p->subs[SUB_REAL].inthreeway = 0;
08045                      p->subs[SUB_THREEWAY].inthreeway = 0;
08046                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08047                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08048                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08049                         /* Swap subs and dis-own channel */
08050                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08051                         p->owner = NULL;
08052                         /* Ring the phone */
08053                         dahdi_ring_phone(p);
08054                      } else {
08055                         if ((res = attempt_transfer(p)) < 0) {
08056                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08057                            if (p->subs[SUB_THREEWAY].owner)
08058                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08059                         } else if (res) {
08060                            /* Don't actually hang up at this point */
08061                            if (p->subs[SUB_THREEWAY].owner)
08062                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08063                            break;
08064                         }
08065                      }
08066                   } else {
08067                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08068                      if (p->subs[SUB_THREEWAY].owner)
08069                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08070                   }
08071                } else {
08072                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08073                   /* Swap subs and dis-own channel */
08074                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08075                   p->owner = NULL;
08076                   /* Ring the phone */
08077                   dahdi_ring_phone(p);
08078                }
08079             }
08080          } else {
08081             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08082          }
08083          /* Fall through */
08084       default:
08085          dahdi_disable_ec(p);
08086          return NULL;
08087       }
08088       break;
08089    case DAHDI_EVENT_RINGOFFHOOK:
08090       if (p->inalarm) break;
08091       if (p->oprmode < 0)
08092       {
08093          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08094          {
08095             /* Make sure it stops ringing */
08096             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08097             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08098             restore_conference(p->oprpeer);
08099          }
08100          break;
08101       }
08102       if (p->radio)
08103       {
08104          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08105          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08106          break;
08107       }
08108       /* for E911, its supposed to wait for offhook then dial
08109          the second half of the dial string */
08110       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08111          c = strchr(p->dialdest, '/');
08112          if (c)
08113             c++;
08114          else
08115             c = p->dialdest;
08116          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08117          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08118          if (strlen(p->dop.dialstr) > 4) {
08119             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08120             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08121             p->echorest[sizeof(p->echorest) - 1] = '\0';
08122             p->echobreak = 1;
08123             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08124          } else
08125             p->echobreak = 0;
08126          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08127             int saveerr = errno;
08128 
08129             x = DAHDI_ONHOOK;
08130             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08131             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08132             return NULL;
08133             }
08134          p->dialing = 1;
08135          return &p->subs[idx].f;
08136       }
08137       switch (p->sig) {
08138       case SIG_FXOLS:
08139       case SIG_FXOGS:
08140       case SIG_FXOKS:
08141          switch (ast->_state) {
08142          case AST_STATE_RINGING:
08143             dahdi_enable_ec(p);
08144             dahdi_train_ec(p);
08145             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08146             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08147             /* Make sure it stops ringing */
08148             p->subs[SUB_REAL].needringing = 0;
08149             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08150             ast_debug(1, "channel %d answered\n", p->channel);
08151 
08152             /* Cancel any running CallerID spill */
08153             ast_free(p->cidspill);
08154             p->cidspill = NULL;
08155             restore_conference(p);
08156 
08157             p->dialing = 0;
08158             p->callwaitcas = 0;
08159             if (p->confirmanswer) {
08160                /* Ignore answer if "confirm answer" is enabled */
08161                p->subs[idx].f.frametype = AST_FRAME_NULL;
08162                p->subs[idx].f.subclass.integer = 0;
08163             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08164                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08165                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08166                if (res < 0) {
08167                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08168                   p->dop.dialstr[0] = '\0';
08169                   return NULL;
08170                } else {
08171                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08172                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08173                   p->subs[idx].f.subclass.integer = 0;
08174                   p->dialing = 1;
08175                }
08176                p->dop.dialstr[0] = '\0';
08177                ast_setstate(ast, AST_STATE_DIALING);
08178             } else
08179                ast_setstate(ast, AST_STATE_UP);
08180             return &p->subs[idx].f;
08181          case AST_STATE_DOWN:
08182             ast_setstate(ast, AST_STATE_RING);
08183             ast->rings = 1;
08184             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08185             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08186             ast_debug(1, "channel %d picked up\n", p->channel);
08187             return &p->subs[idx].f;
08188          case AST_STATE_UP:
08189             /* Make sure it stops ringing */
08190             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08191             /* Okay -- probably call waiting*/
08192             if (ast_bridged_channel(p->owner))
08193                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08194             p->subs[idx].needunhold = 1;
08195             break;
08196          case AST_STATE_RESERVED:
08197             /* Start up dialtone */
08198             if (has_voicemail(p))
08199                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08200             else
08201                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08202             break;
08203          default:
08204             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08205          }
08206          break;
08207       case SIG_FXSLS:
08208       case SIG_FXSGS:
08209       case SIG_FXSKS:
08210          if (ast->_state == AST_STATE_RING) {
08211             p->ringt = p->ringt_base;
08212          }
08213 
08214          /* If we get a ring then we cannot be in
08215           * reversed polarity. So we reset to idle */
08216          ast_debug(1, "Setting IDLE polarity due "
08217             "to ring. Old polarity was %d\n",
08218             p->polarity);
08219          p->polarity = POLARITY_IDLE;
08220 
08221          /* Fall through */
08222       case SIG_EM:
08223       case SIG_EM_E1:
08224       case SIG_EMWINK:
08225       case SIG_FEATD:
08226       case SIG_FEATDMF:
08227       case SIG_FEATDMF_TA:
08228       case SIG_E911:
08229       case SIG_FGC_CAMA:
08230       case SIG_FGC_CAMAMF:
08231       case SIG_FEATB:
08232       case SIG_SF:
08233       case SIG_SFWINK:
08234       case SIG_SF_FEATD:
08235       case SIG_SF_FEATDMF:
08236       case SIG_SF_FEATB:
08237          if (ast->_state == AST_STATE_PRERING)
08238             ast_setstate(ast, AST_STATE_RING);
08239          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08240             ast_debug(1, "Ring detected\n");
08241             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08242             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08243          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08244             ast_debug(1, "Line answered\n");
08245             if (p->confirmanswer) {
08246                p->subs[idx].f.frametype = AST_FRAME_NULL;
08247                p->subs[idx].f.subclass.integer = 0;
08248             } else {
08249                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08250                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08251                ast_setstate(ast, AST_STATE_UP);
08252             }
08253          } else if (ast->_state != AST_STATE_RING)
08254             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08255          break;
08256       default:
08257          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08258       }
08259       break;
08260    case DAHDI_EVENT_RINGBEGIN:
08261       switch (p->sig) {
08262       case SIG_FXSLS:
08263       case SIG_FXSGS:
08264       case SIG_FXSKS:
08265          if (ast->_state == AST_STATE_RING) {
08266             p->ringt = p->ringt_base;
08267          }
08268          break;
08269       }
08270       break;
08271    case DAHDI_EVENT_RINGERON:
08272       break;
08273    case DAHDI_EVENT_NOALARM:
08274       switch (p->sig) {
08275 #if defined(HAVE_PRI)
08276       case SIG_PRI_LIB_HANDLE_CASES:
08277          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08278          break;
08279 #endif   /* defined(HAVE_PRI) */
08280 #if defined(HAVE_SS7)
08281       case SIG_SS7:
08282          sig_ss7_set_alarm(p->sig_pvt, 0);
08283          break;
08284 #endif   /* defined(HAVE_SS7) */
08285       default:
08286          p->inalarm = 0;
08287          break;
08288       }
08289       handle_clear_alarms(p);
08290       break;
08291    case DAHDI_EVENT_WINKFLASH:
08292       if (p->inalarm) break;
08293       if (p->radio) break;
08294       if (p->oprmode < 0) break;
08295       if (p->oprmode > 1)
08296       {
08297          struct dahdi_params par;
08298 
08299          memset(&par, 0, sizeof(par));
08300          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08301          {
08302             if (!par.rxisoffhook)
08303             {
08304                /* Make sure it stops ringing */
08305                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08306                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08307                save_conference(p);
08308                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08309             }
08310          }
08311          break;
08312       }
08313       /* Remember last time we got a flash-hook */
08314       p->flashtime = ast_tvnow();
08315       switch (mysig) {
08316       case SIG_FXOLS:
08317       case SIG_FXOGS:
08318       case SIG_FXOKS:
08319          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08320             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08321 
08322          /* Cancel any running CallerID spill */
08323          ast_free(p->cidspill);
08324          p->cidspill = NULL;
08325          restore_conference(p);
08326          p->callwaitcas = 0;
08327 
08328          if (idx != SUB_REAL) {
08329             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08330             goto winkflashdone;
08331          }
08332 
08333          if (p->subs[SUB_CALLWAIT].owner) {
08334             /* Swap to call-wait */
08335             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08336             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08337             p->owner = p->subs[SUB_REAL].owner;
08338             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08339             if (p->owner->_state == AST_STATE_RINGING) {
08340                ast_setstate(p->owner, AST_STATE_UP);
08341                p->subs[SUB_REAL].needanswer = 1;
08342             }
08343             p->callwaitingrepeat = 0;
08344             p->cidcwexpire = 0;
08345             p->cid_suppress_expire = 0;
08346             /* Start music on hold if appropriate */
08347             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08348                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08349                   S_OR(p->mohsuggest, NULL),
08350                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08351             }
08352             p->subs[SUB_CALLWAIT].needhold = 1;
08353             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08354                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08355                   S_OR(p->mohsuggest, NULL),
08356                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08357             }
08358             p->subs[SUB_REAL].needunhold = 1;
08359          } else if (!p->subs[SUB_THREEWAY].owner) {
08360             if (!p->threewaycalling) {
08361                /* Just send a flash if no 3-way calling */
08362                p->subs[SUB_REAL].needflash = 1;
08363                goto winkflashdone;
08364             } else if (!check_for_conference(p)) {
08365                char cid_num[256];
08366                char cid_name[256];
08367 
08368                cid_num[0] = 0;
08369                cid_name[0] = 0;
08370                if (p->dahditrcallerid && p->owner) {
08371                   if (p->owner->caller.id.number.valid
08372                      && p->owner->caller.id.number.str) {
08373                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08374                         sizeof(cid_num));
08375                   }
08376                   if (p->owner->caller.id.name.valid
08377                      && p->owner->caller.id.name.str) {
08378                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08379                         sizeof(cid_name));
08380                   }
08381                }
08382                /* XXX This section needs much more error checking!!! XXX */
08383                /* Start a 3-way call if feasible */
08384                if (!((ast->pbx) ||
08385                   (ast->_state == AST_STATE_UP) ||
08386                   (ast->_state == AST_STATE_RING))) {
08387                   ast_debug(1, "Flash when call not up or ringing\n");
08388                   goto winkflashdone;
08389                }
08390                if (alloc_sub(p, SUB_THREEWAY)) {
08391                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08392                   goto winkflashdone;
08393                }
08394                /* Make new channel */
08395                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08396                if (p->dahditrcallerid) {
08397                   if (!p->origcid_num)
08398                      p->origcid_num = ast_strdup(p->cid_num);
08399                   if (!p->origcid_name)
08400                      p->origcid_name = ast_strdup(p->cid_name);
08401                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08402                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08403                }
08404                /* Swap things around between the three-way and real call */
08405                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08406                /* Disable echo canceller for better dialing */
08407                dahdi_disable_ec(p);
08408                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08409                if (res)
08410                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08411                p->owner = chan;
08412                if (!chan) {
08413                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08414                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08415                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08416                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08417                   dahdi_enable_ec(p);
08418                   ast_hangup(chan);
08419                } else {
08420                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08421 
08422                   /* Start music on hold if appropriate */
08423                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08424                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08425                         S_OR(p->mohsuggest, NULL),
08426                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08427                   }
08428                   p->subs[SUB_THREEWAY].needhold = 1;
08429                }
08430             }
08431          } else {
08432             /* Already have a 3 way call */
08433             if (p->subs[SUB_THREEWAY].inthreeway) {
08434                /* Call is already up, drop the last person */
08435                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08436                /* If the primary call isn't answered yet, use it */
08437                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08438                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08439                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08440                   p->owner = p->subs[SUB_REAL].owner;
08441                }
08442                /* Drop the last call and stop the conference */
08443                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08444                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08445                p->subs[SUB_REAL].inthreeway = 0;
08446                p->subs[SUB_THREEWAY].inthreeway = 0;
08447             } else {
08448                /* Lets see what we're up to */
08449                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08450                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08451                   int otherindex = SUB_THREEWAY;
08452 
08453                   ast_verb(3, "Building conference call with %s and %s\n",
08454                      p->subs[SUB_THREEWAY].owner->name,
08455                      p->subs[SUB_REAL].owner->name);
08456                   /* Put them in the threeway, and flip */
08457                   p->subs[SUB_THREEWAY].inthreeway = 1;
08458                   p->subs[SUB_REAL].inthreeway = 1;
08459                   if (ast->_state == AST_STATE_UP) {
08460                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08461                      otherindex = SUB_REAL;
08462                   }
08463                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08464                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08465                   p->subs[otherindex].needunhold = 1;
08466                   p->owner = p->subs[SUB_REAL].owner;
08467                } else {
08468                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08469                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08470                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08471                   p->owner = p->subs[SUB_REAL].owner;
08472                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08473                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08474                   p->subs[SUB_REAL].needunhold = 1;
08475                   dahdi_enable_ec(p);
08476                }
08477             }
08478          }
08479 winkflashdone:
08480          update_conf(p);
08481          break;
08482       case SIG_EM:
08483       case SIG_EM_E1:
08484       case SIG_FEATD:
08485       case SIG_SF:
08486       case SIG_SFWINK:
08487       case SIG_SF_FEATD:
08488       case SIG_FXSLS:
08489       case SIG_FXSGS:
08490          if (p->dialing)
08491             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08492          else
08493             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08494          break;
08495       case SIG_FEATDMF_TA:
08496          switch (p->whichwink) {
08497          case 0:
08498             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08499                S_COR(p->owner->caller.ani.number.valid,
08500                   p->owner->caller.ani.number.str, ""));
08501             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08502                p->owner->caller.ani2,
08503                S_COR(p->owner->caller.ani.number.valid,
08504                   p->owner->caller.ani.number.str, ""));
08505             break;
08506          case 1:
08507             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08508             break;
08509          case 2:
08510             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08511             return NULL;
08512          }
08513          p->whichwink++;
08514          /* Fall through */
08515       case SIG_FEATDMF:
08516       case SIG_E911:
08517       case SIG_FGC_CAMAMF:
08518       case SIG_FGC_CAMA:
08519       case SIG_FEATB:
08520       case SIG_SF_FEATDMF:
08521       case SIG_SF_FEATB:
08522       case SIG_EMWINK:
08523          /* FGD MF and EMWINK *Must* wait for wink */
08524          if (!ast_strlen_zero(p->dop.dialstr)) {
08525             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08526             if (res < 0) {
08527                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08528                p->dop.dialstr[0] = '\0';
08529                return NULL;
08530             } else
08531                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08532          }
08533          p->dop.dialstr[0] = '\0';
08534          break;
08535       default:
08536          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08537       }
08538       break;
08539    case DAHDI_EVENT_HOOKCOMPLETE:
08540       if (p->inalarm) break;
08541       if ((p->radio || (p->oprmode < 0))) break;
08542       if (p->waitingfordt.tv_sec) break;
08543       switch (mysig) {
08544       case SIG_FXSLS:  /* only interesting for FXS */
08545       case SIG_FXSGS:
08546       case SIG_FXSKS:
08547       case SIG_EM:
08548       case SIG_EM_E1:
08549       case SIG_EMWINK:
08550       case SIG_FEATD:
08551       case SIG_SF:
08552       case SIG_SFWINK:
08553       case SIG_SF_FEATD:
08554          if (!ast_strlen_zero(p->dop.dialstr)) {
08555             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08556             if (res < 0) {
08557                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08558                p->dop.dialstr[0] = '\0';
08559                return NULL;
08560             } else
08561                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08562          }
08563          p->dop.dialstr[0] = '\0';
08564          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08565          break;
08566       case SIG_FEATDMF:
08567       case SIG_FEATDMF_TA:
08568       case SIG_E911:
08569       case SIG_FGC_CAMA:
08570       case SIG_FGC_CAMAMF:
08571       case SIG_FEATB:
08572       case SIG_SF_FEATDMF:
08573       case SIG_SF_FEATB:
08574          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08575          break;
08576       default:
08577          break;
08578       }
08579       break;
08580    case DAHDI_EVENT_POLARITY:
08581       /*
08582        * If we get a Polarity Switch event, check to see
08583        * if we should change the polarity state and
08584        * mark the channel as UP or if this is an indication
08585        * of remote end disconnect.
08586        */
08587       if (p->polarity == POLARITY_IDLE) {
08588          p->polarity = POLARITY_REV;
08589          if (p->answeronpolarityswitch &&
08590             ((ast->_state == AST_STATE_DIALING) ||
08591             (ast->_state == AST_STATE_RINGING))) {
08592             ast_debug(1, "Answering on polarity switch!\n");
08593             ast_setstate(p->owner, AST_STATE_UP);
08594             if (p->hanguponpolarityswitch) {
08595                p->polaritydelaytv = ast_tvnow();
08596             }
08597          } else
08598             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08599       }
08600       /* Removed else statement from here as it was preventing hangups from ever happening*/
08601       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08602       if (p->hanguponpolarityswitch &&
08603          (p->polarityonanswerdelay > 0) &&
08604          (p->polarity == POLARITY_REV) &&
08605          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08606          /* Added log_debug information below to provide a better indication of what is going on */
08607          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08608 
08609          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08610             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08611             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08612             p->polarity = POLARITY_IDLE;
08613          } else
08614             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08615 
08616       } else {
08617          p->polarity = POLARITY_IDLE;
08618          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08619       }
08620       /* Added more log_debug information below to provide a better indication of what is going on */
08621       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08622       break;
08623    default:
08624       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08625    }
08626    return &p->subs[idx].f;
08627 }
08628 
08629 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08630 {
08631    int res;
08632    int idx;
08633    struct ast_frame *f;
08634    int usedindex = -1;
08635    struct dahdi_pvt *p = ast->tech_pvt;
08636 
08637    idx = dahdi_get_index(ast, p, 1);
08638 
08639    p->subs[idx].f.frametype = AST_FRAME_NULL;
08640    p->subs[idx].f.datalen = 0;
08641    p->subs[idx].f.samples = 0;
08642    p->subs[idx].f.mallocd = 0;
08643    p->subs[idx].f.offset = 0;
08644    p->subs[idx].f.subclass.integer = 0;
08645    p->subs[idx].f.delivery = ast_tv(0,0);
08646    p->subs[idx].f.src = "dahdi_exception";
08647    p->subs[idx].f.data.ptr = NULL;
08648 
08649 
08650    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08651       /* If nobody owns us, absorb the event appropriately, otherwise
08652          we loop indefinitely.  This occurs when, during call waiting, the
08653          other end hangs up our channel so that it no longer exists, but we
08654          have neither FLASH'd nor ONHOOK'd to signify our desire to
08655          change to the other channel. */
08656       if (p->fake_event) {
08657          res = p->fake_event;
08658          p->fake_event = 0;
08659       } else
08660          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08661       /* Switch to real if there is one and this isn't something really silly... */
08662       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08663          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08664          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08665          p->owner = p->subs[SUB_REAL].owner;
08666          if (p->owner && ast_bridged_channel(p->owner))
08667             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08668          p->subs[SUB_REAL].needunhold = 1;
08669       }
08670       switch (res) {
08671       case DAHDI_EVENT_ONHOOK:
08672          dahdi_disable_ec(p);
08673          if (p->owner) {
08674             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08675             dahdi_ring_phone(p);
08676             p->callwaitingrepeat = 0;
08677             p->cidcwexpire = 0;
08678             p->cid_suppress_expire = 0;
08679          } else
08680             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08681          update_conf(p);
08682          break;
08683       case DAHDI_EVENT_RINGOFFHOOK:
08684          dahdi_enable_ec(p);
08685          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08686          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08687             p->subs[SUB_REAL].needanswer = 1;
08688             p->dialing = 0;
08689          }
08690          break;
08691       case DAHDI_EVENT_HOOKCOMPLETE:
08692       case DAHDI_EVENT_RINGERON:
08693       case DAHDI_EVENT_RINGEROFF:
08694          /* Do nothing */
08695          break;
08696       case DAHDI_EVENT_WINKFLASH:
08697          p->flashtime = ast_tvnow();
08698          if (p->owner) {
08699             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08700             if (p->owner->_state != AST_STATE_UP) {
08701                /* Answer if necessary */
08702                usedindex = dahdi_get_index(p->owner, p, 0);
08703                if (usedindex > -1) {
08704                   p->subs[usedindex].needanswer = 1;
08705                }
08706                ast_setstate(p->owner, AST_STATE_UP);
08707             }
08708             p->callwaitingrepeat = 0;
08709             p->cidcwexpire = 0;
08710             p->cid_suppress_expire = 0;
08711             if (ast_bridged_channel(p->owner))
08712                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08713             p->subs[SUB_REAL].needunhold = 1;
08714          } else
08715             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08716          update_conf(p);
08717          break;
08718       default:
08719          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08720       }
08721       f = &p->subs[idx].f;
08722       return f;
08723    }
08724    if (!(p->radio || (p->oprmode < 0)))
08725       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08726    /* If it's not us, return NULL immediately */
08727    if (ast != p->owner) {
08728       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08729       f = &p->subs[idx].f;
08730       return f;
08731    }
08732    f = dahdi_handle_event(ast);
08733 
08734    /* tell the cdr this zap device hung up */
08735    if (f == NULL) {
08736       ast_set_hangupsource(ast, ast->name, 0);
08737    }
08738 
08739    return f;
08740 }
08741 
08742 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08743 {
08744    struct dahdi_pvt *p = ast->tech_pvt;
08745    struct ast_frame *f;
08746    ast_mutex_lock(&p->lock);
08747    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08748       struct analog_pvt *analog_p = p->sig_pvt;
08749       f = analog_exception(analog_p, ast);
08750    } else {
08751       f = __dahdi_exception(ast);
08752    }
08753    ast_mutex_unlock(&p->lock);
08754    return f;
08755 }
08756 
08757 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08758 {
08759    struct dahdi_pvt *p;
08760    int res;
08761    int idx;
08762    void *readbuf;
08763    struct ast_frame *f;
08764 
08765    /*
08766     * For analog channels, we must do deadlock avoidance because
08767     * analog ports can have more than one Asterisk channel using
08768     * the same private structure.
08769     */
08770    p = ast->tech_pvt;
08771    while (ast_mutex_trylock(&p->lock)) {
08772       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08773 
08774       /*
08775        * For PRI channels, we must refresh the private pointer because
08776        * the call could move to another B channel while the Asterisk
08777        * channel is unlocked.
08778        */
08779       p = ast->tech_pvt;
08780    }
08781 
08782    idx = dahdi_get_index(ast, p, 0);
08783 
08784    /* Hang up if we don't really exist */
08785    if (idx < 0)   {
08786       ast_log(LOG_WARNING, "We don't exist?\n");
08787       ast_mutex_unlock(&p->lock);
08788       return NULL;
08789    }
08790 
08791    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08792       ast_mutex_unlock(&p->lock);
08793       return NULL;
08794    }
08795 
08796    p->subs[idx].f.frametype = AST_FRAME_NULL;
08797    p->subs[idx].f.datalen = 0;
08798    p->subs[idx].f.samples = 0;
08799    p->subs[idx].f.mallocd = 0;
08800    p->subs[idx].f.offset = 0;
08801    p->subs[idx].f.subclass.integer = 0;
08802    p->subs[idx].f.delivery = ast_tv(0,0);
08803    p->subs[idx].f.src = "dahdi_read";
08804    p->subs[idx].f.data.ptr = NULL;
08805 
08806    /* make sure it sends initial key state as first frame */
08807    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08808    {
08809       struct dahdi_params ps;
08810 
08811       memset(&ps, 0, sizeof(ps));
08812       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08813          ast_mutex_unlock(&p->lock);
08814          return NULL;
08815       }
08816       p->firstradio = 1;
08817       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08818       if (ps.rxisoffhook)
08819       {
08820          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08821       }
08822       else
08823       {
08824          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08825       }
08826       ast_mutex_unlock(&p->lock);
08827       return &p->subs[idx].f;
08828    }
08829    if (p->ringt > 0) {
08830       if (!(--p->ringt)) {
08831          ast_mutex_unlock(&p->lock);
08832          return NULL;
08833       }
08834    }
08835 
08836 #ifdef HAVE_OPENR2
08837    if (p->mfcr2) {
08838       openr2_chan_process_event(p->r2chan);
08839       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08840          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08841          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08842           * now enqueue a progress frame to bridge the media up */
08843          if (p->mfcr2_call_accepted &&
08844              !p->mfcr2_progress && 
08845              ast->_state == AST_STATE_RINGING) {
08846             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08847             ast_queue_frame(p->owner, &f);
08848             p->mfcr2_progress = 1;
08849          }
08850       }
08851    }
08852 #endif
08853 
08854    if (p->subs[idx].needringing) {
08855       /* Send ringing frame if requested */
08856       p->subs[idx].needringing = 0;
08857       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08858       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08859       ast_setstate(ast, AST_STATE_RINGING);
08860       ast_mutex_unlock(&p->lock);
08861       return &p->subs[idx].f;
08862    }
08863 
08864    if (p->subs[idx].needbusy) {
08865       /* Send busy frame if requested */
08866       p->subs[idx].needbusy = 0;
08867       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08868       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08869       ast_mutex_unlock(&p->lock);
08870       return &p->subs[idx].f;
08871    }
08872 
08873    if (p->subs[idx].needcongestion) {
08874       /* Send congestion frame if requested */
08875       p->subs[idx].needcongestion = 0;
08876       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08877       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08878       ast_mutex_unlock(&p->lock);
08879       return &p->subs[idx].f;
08880    }
08881 
08882    if (p->subs[idx].needanswer) {
08883       /* Send answer frame if requested */
08884       p->subs[idx].needanswer = 0;
08885       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08886       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08887       ast_mutex_unlock(&p->lock);
08888       return &p->subs[idx].f;
08889    }
08890 #ifdef HAVE_OPENR2
08891    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08892       /* openr2 took care of reading and handling any event
08893         (needanswer, needbusy etc), if we continue we will read()
08894         twice, lets just return a null frame. This should only
08895         happen when openr2 is dialing out */
08896       ast_mutex_unlock(&p->lock);
08897       return &ast_null_frame;
08898    }
08899 #endif
08900 
08901    if (p->subs[idx].needflash) {
08902       /* Send answer frame if requested */
08903       p->subs[idx].needflash = 0;
08904       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08905       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08906       ast_mutex_unlock(&p->lock);
08907       return &p->subs[idx].f;
08908    }
08909 
08910    if (p->subs[idx].needhold) {
08911       /* Send answer frame if requested */
08912       p->subs[idx].needhold = 0;
08913       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08914       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08915       ast_mutex_unlock(&p->lock);
08916       ast_debug(1, "Sending hold on '%s'\n", ast->name);
08917       return &p->subs[idx].f;
08918    }
08919 
08920    if (p->subs[idx].needunhold) {
08921       /* Send answer frame if requested */
08922       p->subs[idx].needunhold = 0;
08923       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08924       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08925       ast_mutex_unlock(&p->lock);
08926       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08927       return &p->subs[idx].f;
08928    }
08929 
08930    /*
08931     * If we have a fake_event, fake an exception to handle it only
08932     * if this channel owns the private.
08933     */
08934    if (p->fake_event && p->owner == ast) {
08935       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08936          struct analog_pvt *analog_p = p->sig_pvt;
08937 
08938          f = analog_exception(analog_p, ast);
08939       } else {
08940          f = __dahdi_exception(ast);
08941       }
08942       ast_mutex_unlock(&p->lock);
08943       return f;
08944    }
08945 
08946    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08947       if (!p->subs[idx].linear) {
08948          p->subs[idx].linear = 1;
08949          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08950          if (res)
08951             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08952       }
08953    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08954       (ast->rawreadformat == AST_FORMAT_ALAW)) {
08955       if (p->subs[idx].linear) {
08956          p->subs[idx].linear = 0;
08957          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08958          if (res)
08959             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08960       }
08961    } else {
08962       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08963       ast_mutex_unlock(&p->lock);
08964       return NULL;
08965    }
08966    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08967    CHECK_BLOCKING(ast);
08968    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08969    ast_clear_flag(ast, AST_FLAG_BLOCKING);
08970    /* Check for hangup */
08971    if (res < 0) {
08972       f = NULL;
08973       if (res == -1) {
08974          if (errno == EAGAIN) {
08975             /* Return "NULL" frame if there is nobody there */
08976             ast_mutex_unlock(&p->lock);
08977             return &p->subs[idx].f;
08978          } else if (errno == ELAST) {
08979             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08980                struct analog_pvt *analog_p = p->sig_pvt;
08981                f = analog_exception(analog_p, ast);
08982             } else {
08983                f = __dahdi_exception(ast);
08984             }
08985          } else
08986             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08987       }
08988       ast_mutex_unlock(&p->lock);
08989       return f;
08990    }
08991    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08992       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08993       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08994          struct analog_pvt *analog_p = p->sig_pvt;
08995          f = analog_exception(analog_p, ast);
08996       } else {
08997          f = __dahdi_exception(ast);
08998       }
08999       ast_mutex_unlock(&p->lock);
09000       return f;
09001    }
09002    if (p->tdd) { /* if in TDD mode, see if we receive that */
09003       int c;
09004 
09005       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09006       if (c < 0) {
09007          ast_debug(1,"tdd_feed failed\n");
09008          ast_mutex_unlock(&p->lock);
09009          return NULL;
09010       }
09011       if (c) { /* if a char to return */
09012          p->subs[idx].f.subclass.integer = 0;
09013          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09014          p->subs[idx].f.mallocd = 0;
09015          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09016          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09017          p->subs[idx].f.datalen = 1;
09018          *((char *) p->subs[idx].f.data.ptr) = c;
09019          ast_mutex_unlock(&p->lock);
09020          return &p->subs[idx].f;
09021       }
09022    }
09023    if (idx == SUB_REAL) {
09024       /* Ensure the CW timers decrement only on a single subchannel */
09025       if (p->cidcwexpire) {
09026          if (!--p->cidcwexpire) {
09027             /* Expired CID/CW */
09028             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09029             restore_conference(p);
09030          }
09031       }
09032       if (p->cid_suppress_expire) {
09033          --p->cid_suppress_expire;
09034       }
09035       if (p->callwaitingrepeat) {
09036          if (!--p->callwaitingrepeat) {
09037             /* Expired, Repeat callwaiting tone */
09038             ++p->callwaitrings;
09039             dahdi_callwait(ast);
09040          }
09041       }
09042    }
09043    if (p->subs[idx].linear) {
09044       p->subs[idx].f.datalen = READ_SIZE * 2;
09045    } else
09046       p->subs[idx].f.datalen = READ_SIZE;
09047 
09048    /* Handle CallerID Transmission */
09049    if ((p->owner == ast) && p->cidspill) {
09050       send_callerid(p);
09051    }
09052 
09053    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09054    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09055    p->subs[idx].f.samples = READ_SIZE;
09056    p->subs[idx].f.mallocd = 0;
09057    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09058    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09059 #if 0
09060    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09061 #endif
09062    if (p->dialing ||  p->radio || /* Transmitting something */
09063       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09064       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09065       ) {
09066       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09067          don't send anything */
09068       p->subs[idx].f.frametype = AST_FRAME_NULL;
09069       p->subs[idx].f.subclass.integer = 0;
09070       p->subs[idx].f.samples = 0;
09071       p->subs[idx].f.mallocd = 0;
09072       p->subs[idx].f.offset = 0;
09073       p->subs[idx].f.data.ptr = NULL;
09074       p->subs[idx].f.datalen= 0;
09075    }
09076    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09077       /* Perform busy detection etc on the dahdi line */
09078       int mute;
09079 
09080       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09081 
09082       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09083       mute = ast_dsp_was_muted(p->dsp);
09084       if (p->muting != mute) {
09085          p->muting = mute;
09086          dahdi_confmute(p, mute);
09087       }
09088 
09089       if (f) {
09090          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09091             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09092                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09093                   a busy */
09094                f = NULL;
09095             }
09096          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09097             || f->frametype == AST_FRAME_DTMF_END) {
09098 #ifdef HAVE_PRI
09099             if (dahdi_sig_pri_lib_handles(p->sig)
09100                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09101                && p->pri
09102                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09103                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09104                /* Don't accept in-band DTMF when in overlap dial mode */
09105                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09106                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09107                   f->subclass.integer, f->subclass.integer, ast->name);
09108 
09109                f->frametype = AST_FRAME_NULL;
09110                f->subclass.integer = 0;
09111             }
09112 #endif
09113             /* DSP clears us of being pulse */
09114             p->pulsedial = 0;
09115          } else if (p->waitingfordt.tv_sec) {
09116             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09117                p->waitingfordt.tv_sec = 0;
09118                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09119                f=NULL;
09120             } else if (f->frametype == AST_FRAME_VOICE) {
09121                f->frametype = AST_FRAME_NULL;
09122                f->subclass.integer = 0;
09123                if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
09124                   p->waitingfordt.tv_sec = 0;
09125                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09126                   ast_dsp_set_features(p->dsp, p->dsp_features);
09127                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09128                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09129                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09130                      if (res < 0) {
09131                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09132                         p->dop.dialstr[0] = '\0';
09133                         ast_mutex_unlock(&p->lock);
09134                         return NULL;
09135                      } else {
09136                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09137                         p->dialing = 1;
09138                         p->dop.dialstr[0] = '\0';
09139                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09140                         ast_setstate(ast, AST_STATE_DIALING);
09141                      }
09142                   }
09143                }
09144             }
09145          }
09146       }
09147    } else
09148       f = &p->subs[idx].f;
09149 
09150    if (f) {
09151       switch (f->frametype) {
09152       case AST_FRAME_DTMF_BEGIN:
09153       case AST_FRAME_DTMF_END:
09154          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09155             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09156          } else {
09157             dahdi_handle_dtmf(ast, idx, &f);
09158          }
09159          break;
09160       case AST_FRAME_VOICE:
09161          if (p->cidspill || p->cid_suppress_expire) {
09162             /* We are/were sending a caller id spill.  Suppress any echo. */
09163             p->subs[idx].f.frametype = AST_FRAME_NULL;
09164             p->subs[idx].f.subclass.integer = 0;
09165             p->subs[idx].f.samples = 0;
09166             p->subs[idx].f.mallocd = 0;
09167             p->subs[idx].f.offset = 0;
09168             p->subs[idx].f.data.ptr = NULL;
09169             p->subs[idx].f.datalen= 0;
09170          }
09171          break;
09172       default:
09173          break;
09174       }
09175    }
09176 
09177    ast_mutex_unlock(&p->lock);
09178    return f;
09179 }
09180 
09181 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09182 {
09183    int sent=0;
09184    int size;
09185    int res;
09186    int fd;
09187    fd = p->subs[idx].dfd;
09188    while (len) {
09189       size = len;
09190       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09191          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09192       res = write(fd, buf, size);
09193       if (res != size) {
09194          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09195          return sent;
09196       }
09197       len -= size;
09198       buf += size;
09199    }
09200    return sent;
09201 }
09202 
09203 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09204 {
09205    struct dahdi_pvt *p = ast->tech_pvt;
09206    int res;
09207    int idx;
09208    idx = dahdi_get_index(ast, p, 0);
09209    if (idx < 0) {
09210       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09211       return -1;
09212    }
09213 
09214    /* Write a frame of (presumably voice) data */
09215    if (frame->frametype != AST_FRAME_VOICE) {
09216       if (frame->frametype != AST_FRAME_IMAGE)
09217          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09218       return 0;
09219    }
09220    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09221       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09222       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09223       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09224       return -1;
09225    }
09226    if (p->dialing) {
09227       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09228       return 0;
09229    }
09230    if (!p->owner) {
09231       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09232       return 0;
09233    }
09234    if (p->cidspill) {
09235       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09236          ast->name);
09237       return 0;
09238    }
09239    /* Return if it's not valid data */
09240    if (!frame->data.ptr || !frame->datalen)
09241       return 0;
09242 
09243    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09244       if (!p->subs[idx].linear) {
09245          p->subs[idx].linear = 1;
09246          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09247          if (res)
09248             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09249       }
09250       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09251    } else {
09252       /* x-law already */
09253       if (p->subs[idx].linear) {
09254          p->subs[idx].linear = 0;
09255          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09256          if (res)
09257             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09258       }
09259       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09260    }
09261    if (res < 0) {
09262       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09263       return -1;
09264    }
09265    return 0;
09266 }
09267 
09268 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09269 {
09270    struct dahdi_pvt *p = chan->tech_pvt;
09271    int res=-1;
09272    int idx;
09273    int func = DAHDI_FLASH;
09274 
09275    ast_mutex_lock(&p->lock);
09276    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09277    switch (p->sig) {
09278 #if defined(HAVE_PRI)
09279    case SIG_PRI_LIB_HANDLE_CASES:
09280       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09281       ast_mutex_unlock(&p->lock);
09282       return res;
09283 #endif   /* defined(HAVE_PRI) */
09284 #if defined(HAVE_SS7)
09285    case SIG_SS7:
09286       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09287       ast_mutex_unlock(&p->lock);
09288       return res;
09289 #endif   /* defined(HAVE_SS7) */
09290    default:
09291       break;
09292    }
09293 #ifdef HAVE_OPENR2
09294    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09295       ast_mutex_unlock(&p->lock);
09296       /* if this is an R2 call and the call is not yet accepted, we don't want the
09297          tone indications to mess up with the MF tones */
09298       return 0;
09299    }
09300 #endif
09301    idx = dahdi_get_index(chan, p, 0);
09302    if (idx == SUB_REAL) {
09303       switch (condition) {
09304       case AST_CONTROL_BUSY:
09305          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09306          break;
09307       case AST_CONTROL_RINGING:
09308          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09309 
09310          if (chan->_state != AST_STATE_UP) {
09311             if ((chan->_state != AST_STATE_RING) ||
09312                ((p->sig != SIG_FXSKS) &&
09313              (p->sig != SIG_FXSLS) &&
09314              (p->sig != SIG_FXSGS)))
09315             ast_setstate(chan, AST_STATE_RINGING);
09316          }
09317          break;
09318       case AST_CONTROL_PROCEEDING:
09319          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09320          /* don't continue in ast_indicate */
09321          res = 0;
09322          break;
09323       case AST_CONTROL_PROGRESS:
09324          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09325          /* don't continue in ast_indicate */
09326          res = 0;
09327          break;
09328       case AST_CONTROL_CONGESTION:
09329          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09330          switch (chan->hangupcause) {
09331          case AST_CAUSE_USER_BUSY:
09332          case AST_CAUSE_NORMAL_CLEARING:
09333          case 0:/* Cause has not been set. */
09334             /* Supply a more appropriate cause. */
09335             chan->hangupcause = AST_CAUSE_CONGESTION;
09336             break;
09337          default:
09338             break;
09339          }
09340          break;
09341       case AST_CONTROL_HOLD:
09342          ast_moh_start(chan, data, p->mohinterpret);
09343          break;
09344       case AST_CONTROL_UNHOLD:
09345          ast_moh_stop(chan);
09346          break;
09347       case AST_CONTROL_RADIO_KEY:
09348          if (p->radio)
09349             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09350          res = 0;
09351          break;
09352       case AST_CONTROL_RADIO_UNKEY:
09353          if (p->radio)
09354             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09355          res = 0;
09356          break;
09357       case AST_CONTROL_FLASH:
09358          /* flash hookswitch */
09359          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09360             /* Clear out the dial buffer */
09361             p->dop.dialstr[0] = '\0';
09362             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09363                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09364                   chan->name, strerror(errno));
09365             } else
09366                res = 0;
09367          } else
09368             res = 0;
09369          break;
09370       case AST_CONTROL_SRCUPDATE:
09371          res = 0;
09372          break;
09373       case -1:
09374          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09375          break;
09376       }
09377    } else {
09378       res = 0;
09379    }
09380    ast_mutex_unlock(&p->lock);
09381    return res;
09382 }
09383 
09384 #if defined(HAVE_PRI)
09385 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09386 #else
09387 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09388 #endif   /* defined(HAVE_PRI) */
09389 {
09390    struct ast_str *chan_name;
09391    int x, y;
09392 
09393    /* Create the new channel name tail. */
09394    if (!(chan_name = ast_str_create(32))) {
09395       return NULL;
09396    }
09397    if (i->channel == CHAN_PSEUDO) {
09398       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09399 #if defined(HAVE_PRI)
09400    } else if (i->pri) {
09401       ast_mutex_lock(&i->pri->lock);
09402       y = ++i->pri->new_chan_seq;
09403       if (is_outgoing) {
09404          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09405          address[0] = '\0';
09406       } else if (ast_strlen_zero(i->cid_subaddr)) {
09407          /* Put in caller-id number only since there is no subaddress. */
09408          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09409       } else {
09410          /* Put in caller-id number and subaddress. */
09411          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09412             i->cid_subaddr, y);
09413       }
09414       ast_mutex_unlock(&i->pri->lock);
09415 #endif   /* defined(HAVE_PRI) */
09416    } else {
09417       y = 1;
09418       do {
09419          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09420          for (x = 0; x < 3; ++x) {
09421             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09422                i->subs[x].owner->name + 6)) {
09423                break;
09424             }
09425          }
09426          ++y;
09427       } while (x < 3);
09428    }
09429    return chan_name;
09430 }
09431 
09432 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09433 {
09434    struct ast_channel *tmp;
09435    format_t deflaw;
09436    int x;
09437    int features;
09438    struct ast_str *chan_name;
09439    struct ast_variable *v;
09440    char *dashptr;
09441    char device_name[AST_CHANNEL_NAME];
09442 
09443    if (i->subs[idx].owner) {
09444       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09445       return NULL;
09446    }
09447 
09448 #if defined(HAVE_PRI)
09449    /*
09450     * The dnid has been stuffed with the called-number[:subaddress]
09451     * by dahdi_request() for outgoing calls.
09452     */
09453    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09454 #else
09455    chan_name = create_channel_name(i);
09456 #endif   /* defined(HAVE_PRI) */
09457    if (!chan_name) {
09458       return NULL;
09459    }
09460 
09461    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09462    ast_free(chan_name);
09463    if (!tmp)
09464       return NULL;
09465    tmp->tech = &dahdi_tech;
09466 #if defined(HAVE_PRI)
09467    if (i->pri) {
09468       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09469    }
09470 #endif   /* defined(HAVE_PRI) */
09471    ast_channel_cc_params_init(tmp, i->cc_params);
09472    if (law) {
09473       i->law = law;
09474       if (law == DAHDI_LAW_ALAW) {
09475          deflaw = AST_FORMAT_ALAW;
09476       } else {
09477          deflaw = AST_FORMAT_ULAW;
09478       }
09479    } else {
09480       switch (i->sig) {
09481       case SIG_PRI_LIB_HANDLE_CASES:
09482          /* Make sure companding law is known. */
09483          i->law = (i->law_default == DAHDI_LAW_ALAW)
09484             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09485          break;
09486       default:
09487          i->law = i->law_default;
09488          break;
09489       }
09490       if (i->law_default == DAHDI_LAW_ALAW) {
09491          deflaw = AST_FORMAT_ALAW;
09492       } else {
09493          deflaw = AST_FORMAT_ULAW;
09494       }
09495    }
09496    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09497    tmp->nativeformats = deflaw;
09498    /* Start out assuming ulaw since it's smaller :) */
09499    tmp->rawreadformat = deflaw;
09500    tmp->readformat = deflaw;
09501    tmp->rawwriteformat = deflaw;
09502    tmp->writeformat = deflaw;
09503    i->subs[idx].linear = 0;
09504    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09505    features = 0;
09506    if (idx == SUB_REAL) {
09507       if (i->busydetect && CANBUSYDETECT(i))
09508          features |= DSP_FEATURE_BUSY_DETECT;
09509       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09510          features |= DSP_FEATURE_CALL_PROGRESS;
09511       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09512          features |= DSP_FEATURE_WAITDIALTONE;
09513       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09514          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09515          features |= DSP_FEATURE_FAX_DETECT;
09516       }
09517       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09518       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09519          i->hardwaredtmf = 0;
09520          features |= DSP_FEATURE_DIGIT_DETECT;
09521       } else if (NEED_MFDETECT(i)) {
09522          i->hardwaredtmf = 1;
09523          features |= DSP_FEATURE_DIGIT_DETECT;
09524       }
09525    }
09526    if (features) {
09527       if (i->dsp) {
09528          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09529       } else {
09530          if (i->channel != CHAN_PSEUDO)
09531             i->dsp = ast_dsp_new();
09532          else
09533             i->dsp = NULL;
09534          if (i->dsp) {
09535             i->dsp_features = features;
09536 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09537             /* We cannot do progress detection until receive PROGRESS message */
09538             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09539                /* Remember requested DSP features, don't treat
09540                   talking as ANSWER */
09541                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09542                features = 0;
09543             }
09544 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09545             ast_dsp_set_features(i->dsp, features);
09546             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09547             if (!ast_strlen_zero(progzone))
09548                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09549             if (i->busydetect && CANBUSYDETECT(i)) {
09550                ast_dsp_set_busy_count(i->dsp, i->busycount);
09551                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09552             }
09553          }
09554       }
09555    }
09556 
09557    if (state == AST_STATE_RING)
09558       tmp->rings = 1;
09559    tmp->tech_pvt = i;
09560    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09561       /* Only FXO signalled stuff can be picked up */
09562       tmp->callgroup = i->callgroup;
09563       tmp->pickupgroup = i->pickupgroup;
09564    }
09565    if (!ast_strlen_zero(i->parkinglot))
09566       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09567    if (!ast_strlen_zero(i->language))
09568       ast_string_field_set(tmp, language, i->language);
09569    if (!i->owner)
09570       i->owner = tmp;
09571    if (!ast_strlen_zero(i->accountcode))
09572       ast_string_field_set(tmp, accountcode, i->accountcode);
09573    if (i->amaflags)
09574       tmp->amaflags = i->amaflags;
09575    i->subs[idx].owner = tmp;
09576    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09577    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09578       ast_string_field_set(tmp, call_forward, i->call_forward);
09579    }
09580    /* If we've been told "no ADSI" then enforce it */
09581    if (!i->adsi)
09582       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09583    if (!ast_strlen_zero(i->exten))
09584       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09585    if (!ast_strlen_zero(i->rdnis)) {
09586       tmp->redirecting.from.number.valid = 1;
09587       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09588    }
09589    if (!ast_strlen_zero(i->dnid)) {
09590       tmp->dialed.number.str = ast_strdup(i->dnid);
09591    }
09592 
09593    /* Don't use ast_set_callerid() here because it will
09594     * generate a needless NewCallerID event */
09595 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09596    if (!ast_strlen_zero(i->cid_ani)) {
09597       tmp->caller.ani.number.valid = 1;
09598       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09599    } else if (!ast_strlen_zero(i->cid_num)) {
09600       tmp->caller.ani.number.valid = 1;
09601       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09602    }
09603 #else
09604    if (!ast_strlen_zero(i->cid_num)) {
09605       tmp->caller.ani.number.valid = 1;
09606       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09607    }
09608 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09609    tmp->caller.id.name.presentation = i->callingpres;
09610    tmp->caller.id.number.presentation = i->callingpres;
09611    tmp->caller.id.number.plan = i->cid_ton;
09612    tmp->caller.ani2 = i->cid_ani2;
09613    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09614    /* clear the fake event in case we posted one before we had ast_channel */
09615    i->fake_event = 0;
09616    /* Assure there is no confmute on this channel */
09617    dahdi_confmute(i, 0);
09618    i->muting = 0;
09619    /* Configure the new channel jb */
09620    ast_jb_configure(tmp, &global_jbconf);
09621 
09622    /* Set initial device state */
09623    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09624    dashptr = strrchr(device_name, '-');
09625    if (dashptr) {
09626       *dashptr = '\0';
09627    }
09628    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09629 
09630    for (v = i->vars ; v ; v = v->next)
09631       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09632 
09633    ast_module_ref(ast_module_info->self);
09634 
09635    dahdi_ami_channel_event(i, tmp);
09636    if (startpbx) {
09637 #ifdef HAVE_OPENR2
09638       if (i->mfcr2call) {
09639          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09640       }
09641 #endif
09642       if (ast_pbx_start(tmp)) {
09643          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09644          ast_hangup(tmp);
09645          return NULL;
09646       }
09647    }
09648    return tmp;
09649 }
09650 
09651 
09652 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09653 {
09654    char c;
09655 
09656    *str = 0; /* start with empty output buffer */
09657    for (;;)
09658    {
09659       /* Wait for the first digit (up to specified ms). */
09660       c = ast_waitfordigit(chan, ms);
09661       /* if timeout, hangup or error, return as such */
09662       if (c < 1)
09663          return c;
09664       *str++ = c;
09665       *str = 0;
09666       if (strchr(term, c))
09667          return 1;
09668    }
09669 }
09670 
09671 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09672 {
09673    int j;
09674    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09675    for (;;)
09676    {
09677       /* set bits of interest */
09678       j = DAHDI_IOMUX_SIGEVENT;
09679       /* wait for some happening */
09680       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09681       /* exit loop if we have it */
09682       if (j & DAHDI_IOMUX_SIGEVENT) break;
09683    }
09684    /* get the event info */
09685    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09686    return 0;
09687 }
09688 
09689 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09690  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09691  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09692  *
09693  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09694  * DAHDI channel). Use this to enable or disable it.
09695  *
09696  * \bug the use of the word "channel" for those dahdichans is really confusing.
09697  */
09698 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09699 {
09700    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09701       return analog_dnd(dahdichan->sig_pvt, flag);
09702    }
09703 
09704    if (flag == -1) {
09705       return dahdichan->dnd;
09706    }
09707 
09708    /* Do not disturb */
09709    dahdichan->dnd = flag;
09710    ast_verb(3, "%s DND on channel %d\n",
09711          flag? "Enabled" : "Disabled",
09712          dahdichan->channel);
09713    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09714          "Channel: DAHDI/%d\r\n"
09715          "Status: %s\r\n", dahdichan->channel,
09716          flag? "enabled" : "disabled");
09717 
09718    return 0;
09719 }
09720 
09721 static int canmatch_featurecode(const char *exten)
09722 {
09723    int extlen = strlen(exten);
09724    const char *pickup_ext;
09725    if (!extlen) {
09726       return 1;
09727    }
09728    pickup_ext = ast_pickup_ext();
09729    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09730       return 1;
09731    }
09732    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09733    if (exten[0] == '*' && extlen < 3) {
09734       if (extlen == 1) {
09735          return 1;
09736       }
09737       /* "*0" should be processed before it gets here */
09738       switch (exten[1]) {
09739       case '6':
09740       case '7':
09741       case '8':
09742          return 1;
09743       }
09744    }
09745    return 0;
09746 }
09747 
09748 static void *analog_ss_thread(void *data)
09749 {
09750    struct ast_channel *chan = data;
09751    struct dahdi_pvt *p = chan->tech_pvt;
09752    char exten[AST_MAX_EXTENSION] = "";
09753    char exten2[AST_MAX_EXTENSION] = "";
09754    unsigned char buf[256];
09755    char dtmfcid[300];
09756    char dtmfbuf[300];
09757    struct callerid_state *cs = NULL;
09758    char *name = NULL, *number = NULL;
09759    int distMatches;
09760    int curRingData[3];
09761    int receivedRingT;
09762    int counter1;
09763    int counter;
09764    int samples = 0;
09765    struct ast_smdi_md_message *smdi_msg = NULL;
09766    int flags = 0;
09767    int i;
09768    int timeout;
09769    int getforward = 0;
09770    char *s1, *s2;
09771    int len = 0;
09772    int res;
09773    int idx;
09774 
09775    ast_mutex_lock(&ss_thread_lock);
09776    ss_thread_count++;
09777    ast_mutex_unlock(&ss_thread_lock);
09778    /* in the bizarre case where the channel has become a zombie before we
09779       even get started here, abort safely
09780    */
09781    if (!p) {
09782       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09783       ast_hangup(chan);
09784       goto quit;
09785    }
09786    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09787    idx = dahdi_get_index(chan, p, 1);
09788    if (idx < 0) {
09789       ast_log(LOG_WARNING, "Huh?\n");
09790       ast_hangup(chan);
09791       goto quit;
09792    }
09793    if (p->dsp)
09794       ast_dsp_digitreset(p->dsp);
09795    switch (p->sig) {
09796    case SIG_FEATD:
09797    case SIG_FEATDMF:
09798    case SIG_FEATDMF_TA:
09799    case SIG_E911:
09800    case SIG_FGC_CAMAMF:
09801    case SIG_FEATB:
09802    case SIG_EMWINK:
09803    case SIG_SF_FEATD:
09804    case SIG_SF_FEATDMF:
09805    case SIG_SF_FEATB:
09806    case SIG_SFWINK:
09807       if (dahdi_wink(p, idx))
09808          goto quit;
09809       /* Fall through */
09810    case SIG_EM:
09811    case SIG_EM_E1:
09812    case SIG_SF:
09813    case SIG_FGC_CAMA:
09814       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09815       if (p->dsp)
09816          ast_dsp_digitreset(p->dsp);
09817       /* set digit mode appropriately */
09818       if (p->dsp) {
09819          if (NEED_MFDETECT(p))
09820             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09821          else
09822             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09823       }
09824       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09825       /* Wait for the first digit only if immediate=no */
09826       if (!p->immediate)
09827          /* Wait for the first digit (up to 5 seconds). */
09828          res = ast_waitfordigit(chan, 5000);
09829       else
09830          res = 0;
09831       if (res > 0) {
09832          /* save first char */
09833          dtmfbuf[0] = res;
09834          switch (p->sig) {
09835          case SIG_FEATD:
09836          case SIG_SF_FEATD:
09837             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09838             if (res > 0)
09839                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09840             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09841             break;
09842          case SIG_FEATDMF_TA:
09843             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09844             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09845             if (dahdi_wink(p, idx)) goto quit;
09846             dtmfbuf[0] = 0;
09847             /* Wait for the first digit (up to 5 seconds). */
09848             res = ast_waitfordigit(chan, 5000);
09849             if (res <= 0) break;
09850             dtmfbuf[0] = res;
09851             /* fall through intentionally */
09852          case SIG_FEATDMF:
09853          case SIG_E911:
09854          case SIG_FGC_CAMAMF:
09855          case SIG_SF_FEATDMF:
09856             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09857             /* if international caca, do it again to get real ANO */
09858             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09859             {
09860                if (dahdi_wink(p, idx)) goto quit;
09861                dtmfbuf[0] = 0;
09862                /* Wait for the first digit (up to 5 seconds). */
09863                res = ast_waitfordigit(chan, 5000);
09864                if (res <= 0) break;
09865                dtmfbuf[0] = res;
09866                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09867             }
09868             if (res > 0) {
09869                /* if E911, take off hook */
09870                if (p->sig == SIG_E911)
09871                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09872                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09873             }
09874             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09875             break;
09876          case SIG_FEATB:
09877          case SIG_SF_FEATB:
09878             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09879             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09880             break;
09881          case SIG_EMWINK:
09882             /* if we received a '*', we are actually receiving Feature Group D
09883                dial syntax, so use that mode; otherwise, fall through to normal
09884                mode
09885             */
09886             if (res == '*') {
09887                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09888                if (res > 0)
09889                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09890                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09891                break;
09892             }
09893          default:
09894             /* If we got the first digit, get the rest */
09895             len = 1;
09896             dtmfbuf[len] = '\0';
09897             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09898                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09899                   timeout = matchdigittimeout;
09900                } else {
09901                   timeout = gendigittimeout;
09902                }
09903                res = ast_waitfordigit(chan, timeout);
09904                if (res < 0) {
09905                   ast_debug(1, "waitfordigit returned < 0...\n");
09906                   ast_hangup(chan);
09907                   goto quit;
09908                } else if (res) {
09909                   dtmfbuf[len++] = res;
09910                   dtmfbuf[len] = '\0';
09911                } else {
09912                   break;
09913                }
09914             }
09915             break;
09916          }
09917       }
09918       if (res == -1) {
09919          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09920          ast_hangup(chan);
09921          goto quit;
09922       } else if (res < 0) {
09923          ast_debug(1, "Got hung up before digits finished\n");
09924          ast_hangup(chan);
09925          goto quit;
09926       }
09927 
09928       if (p->sig == SIG_FGC_CAMA) {
09929          char anibuf[100];
09930 
09931          if (ast_safe_sleep(chan,1000) == -1) {
09932             ast_hangup(chan);
09933             goto quit;
09934          }
09935          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09936          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09937          res = my_getsigstr(chan, anibuf, "#", 10000);
09938          if ((res > 0) && (strlen(anibuf) > 2)) {
09939             if (anibuf[strlen(anibuf) - 1] == '#')
09940                anibuf[strlen(anibuf) - 1] = 0;
09941             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09942          }
09943          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09944       }
09945 
09946       ast_copy_string(exten, dtmfbuf, sizeof(exten));
09947       if (ast_strlen_zero(exten))
09948          ast_copy_string(exten, "s", sizeof(exten));
09949       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09950          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
09951          if (exten[0] == '*') {
09952             char *stringp=NULL;
09953             ast_copy_string(exten2, exten, sizeof(exten2));
09954             /* Parse out extension and callerid */
09955             stringp=exten2 +1;
09956             s1 = strsep(&stringp, "*");
09957             s2 = strsep(&stringp, "*");
09958             if (s2) {
09959                if (!ast_strlen_zero(p->cid_num))
09960                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09961                else
09962                   ast_set_callerid(chan, s1, NULL, s1);
09963                ast_copy_string(exten, s2, sizeof(exten));
09964             } else
09965                ast_copy_string(exten, s1, sizeof(exten));
09966          } else if (p->sig == SIG_FEATD)
09967             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09968       }
09969       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09970          if (exten[0] == '*') {
09971             char *stringp=NULL;
09972             ast_copy_string(exten2, exten, sizeof(exten2));
09973             /* Parse out extension and callerid */
09974             stringp=exten2 +1;
09975             s1 = strsep(&stringp, "#");
09976             s2 = strsep(&stringp, "#");
09977             if (s2) {
09978                if (!ast_strlen_zero(p->cid_num))
09979                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09980                else
09981                   if (*(s1 + 2))
09982                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09983                ast_copy_string(exten, s2 + 1, sizeof(exten));
09984             } else
09985                ast_copy_string(exten, s1 + 2, sizeof(exten));
09986          } else
09987             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09988       }
09989       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09990          if (exten[0] == '*') {
09991             char *stringp=NULL;
09992             ast_copy_string(exten2, exten, sizeof(exten2));
09993             /* Parse out extension and callerid */
09994             stringp=exten2 +1;
09995             s1 = strsep(&stringp, "#");
09996             s2 = strsep(&stringp, "#");
09997             if (s2 && (*(s2 + 1) == '0')) {
09998                if (*(s2 + 2))
09999                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10000             }
10001             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10002             else ast_copy_string(exten, "911", sizeof(exten));
10003          } else
10004             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10005       }
10006       if (p->sig == SIG_FEATB) {
10007          if (exten[0] == '*') {
10008             char *stringp=NULL;
10009             ast_copy_string(exten2, exten, sizeof(exten2));
10010             /* Parse out extension and callerid */
10011             stringp=exten2 +1;
10012             s1 = strsep(&stringp, "#");
10013             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10014          } else
10015             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10016       }
10017       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10018          dahdi_wink(p, idx);
10019          /* some switches require a minimum guard time between
10020             the last FGD wink and something that answers
10021             immediately. This ensures it */
10022          if (ast_safe_sleep(chan, 100)) {
10023             ast_hangup(chan);
10024             goto quit;
10025          }
10026       }
10027       dahdi_enable_ec(p);
10028       if (NEED_MFDETECT(p)) {
10029          if (p->dsp) {
10030             if (!p->hardwaredtmf)
10031                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10032             else {
10033                ast_dsp_free(p->dsp);
10034                p->dsp = NULL;
10035             }
10036          }
10037       }
10038 
10039       if (ast_exists_extension(chan, chan->context, exten, 1,
10040          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10041          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10042          if (p->dsp) ast_dsp_digitreset(p->dsp);
10043          res = ast_pbx_run(chan);
10044          if (res) {
10045             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10046             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10047          }
10048          goto quit;
10049       } else {
10050          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10051          sleep(2);
10052          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10053          if (res < 0)
10054             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10055          else
10056             sleep(1);
10057          res = ast_streamfile(chan, "ss-noservice", chan->language);
10058          if (res >= 0)
10059             ast_waitstream(chan, "");
10060          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10061          ast_hangup(chan);
10062          goto quit;
10063       }
10064       break;
10065    case SIG_FXOLS:
10066    case SIG_FXOGS:
10067    case SIG_FXOKS:
10068       /* Read the first digit */
10069       timeout = firstdigittimeout;
10070       /* If starting a threeway call, never timeout on the first digit so someone
10071          can use flash-hook as a "hold" feature */
10072       if (p->subs[SUB_THREEWAY].owner)
10073          timeout = 999999;
10074       while (len < AST_MAX_EXTENSION-1) {
10075          /* Read digit unless it's supposed to be immediate, in which case the
10076             only answer is 's' */
10077          if (p->immediate)
10078             res = 's';
10079          else
10080             res = ast_waitfordigit(chan, timeout);
10081          timeout = 0;
10082          if (res < 0) {
10083             ast_debug(1, "waitfordigit returned < 0...\n");
10084             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10085             ast_hangup(chan);
10086             goto quit;
10087          } else if (res) {
10088             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10089             exten[len++]=res;
10090             exten[len] = '\0';
10091          }
10092          if (!ast_ignore_pattern(chan->context, exten))
10093             tone_zone_play_tone(p->subs[idx].dfd, -1);
10094          else
10095             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10096          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10097             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10098                if (getforward) {
10099                   /* Record this as the forwarding extension */
10100                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10101                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10102                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10103                   if (res)
10104                      break;
10105                   usleep(500000);
10106                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10107                   sleep(1);
10108                   memset(exten, 0, sizeof(exten));
10109                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10110                   len = 0;
10111                   getforward = 0;
10112                } else {
10113                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10114                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10115                   if (!ast_strlen_zero(p->cid_num)) {
10116                      if (!p->hidecallerid)
10117                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10118                      else
10119                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10120                   }
10121                   if (!ast_strlen_zero(p->cid_name)) {
10122                      if (!p->hidecallerid)
10123                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10124                   }
10125                   ast_setstate(chan, AST_STATE_RING);
10126                   dahdi_enable_ec(p);
10127                   res = ast_pbx_run(chan);
10128                   if (res) {
10129                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10130                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10131                   }
10132                   goto quit;
10133                }
10134             } else {
10135                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10136                   so just set the timeout to matchdigittimeout and wait some more */
10137                timeout = matchdigittimeout;
10138             }
10139          } else if (res == 0) {
10140             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10141             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10142             dahdi_wait_event(p->subs[idx].dfd);
10143             ast_hangup(chan);
10144             goto quit;
10145          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10146             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10147             /* Disable call waiting if enabled */
10148             p->callwaiting = 0;
10149             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10150             if (res) {
10151                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10152                   chan->name, strerror(errno));
10153             }
10154             len = 0;
10155             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10156             memset(exten, 0, sizeof(exten));
10157             timeout = firstdigittimeout;
10158 
10159          } else if (!strcmp(exten,ast_pickup_ext())) {
10160             /* Scan all channels and see if there are any
10161              * ringing channels that have call groups
10162              * that equal this channels pickup group
10163              */
10164             if (idx == SUB_REAL) {
10165                /* Switch us from Third call to Call Wait */
10166                if (p->subs[SUB_THREEWAY].owner) {
10167                   /* If you make a threeway call and the *8# a call, it should actually
10168                      look like a callwait */
10169                   alloc_sub(p, SUB_CALLWAIT);
10170                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10171                   unalloc_sub(p, SUB_THREEWAY);
10172                }
10173                dahdi_enable_ec(p);
10174                if (ast_pickup_call(chan)) {
10175                   ast_debug(1, "No call pickup possible...\n");
10176                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10177                   dahdi_wait_event(p->subs[idx].dfd);
10178                }
10179                ast_hangup(chan);
10180                goto quit;
10181             } else {
10182                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10183                ast_hangup(chan);
10184                goto quit;
10185             }
10186 
10187          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10188             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10189             /* Disable Caller*ID if enabled */
10190             p->hidecallerid = 1;
10191             ast_party_number_free(&chan->caller.id.number);
10192             ast_party_number_init(&chan->caller.id.number);
10193             ast_party_name_free(&chan->caller.id.name);
10194             ast_party_name_init(&chan->caller.id.name);
10195             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10196             if (res) {
10197                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10198                   chan->name, strerror(errno));
10199             }
10200             len = 0;
10201             memset(exten, 0, sizeof(exten));
10202             timeout = firstdigittimeout;
10203          } else if (p->callreturn && !strcmp(exten, "*69")) {
10204             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10205             break;
10206          } else if (!strcmp(exten, "*78")) {
10207             dahdi_dnd(p, 1);
10208             /* Do not disturb */
10209             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10210             getforward = 0;
10211             memset(exten, 0, sizeof(exten));
10212             len = 0;
10213          } else if (!strcmp(exten, "*79")) {
10214             dahdi_dnd(p, 0);
10215             /* Do not disturb */
10216             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10217             getforward = 0;
10218             memset(exten, 0, sizeof(exten));
10219             len = 0;
10220          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10221             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10222             getforward = 1;
10223             memset(exten, 0, sizeof(exten));
10224             len = 0;
10225          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10226             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10227             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10228             memset(p->call_forward, 0, sizeof(p->call_forward));
10229             getforward = 0;
10230             memset(exten, 0, sizeof(exten));
10231             len = 0;
10232          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10233                   p->subs[SUB_THREEWAY].owner &&
10234                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10235             /* This is a three way call, the main call being a real channel,
10236                and we're parking the first call. */
10237             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10238             ast_verb(3, "Parking call to '%s'\n", chan->name);
10239             break;
10240          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10241             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10242             /* Enable Caller*ID if enabled */
10243             p->hidecallerid = 0;
10244             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10245             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10246             if (res) {
10247                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10248                   chan->name, strerror(errno));
10249             }
10250             len = 0;
10251             memset(exten, 0, sizeof(exten));
10252             timeout = firstdigittimeout;
10253          } else if (!strcmp(exten, "*0")) {
10254             struct ast_channel *nbridge =
10255                p->subs[SUB_THREEWAY].owner;
10256             struct dahdi_pvt *pbridge = NULL;
10257             /* set up the private struct of the bridged one, if any */
10258             if (nbridge && ast_bridged_channel(nbridge))
10259                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10260             if (nbridge && pbridge &&
10261                (nbridge->tech == &dahdi_tech) &&
10262                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10263                ISTRUNK(pbridge)) {
10264                int func = DAHDI_FLASH;
10265                /* Clear out the dial buffer */
10266                p->dop.dialstr[0] = '\0';
10267                /* flash hookswitch */
10268                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10269                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10270                      nbridge->name, strerror(errno));
10271                }
10272                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10273                unalloc_sub(p, SUB_THREEWAY);
10274                p->owner = p->subs[SUB_REAL].owner;
10275                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10276                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10277                ast_hangup(chan);
10278                goto quit;
10279             } else {
10280                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10281                dahdi_wait_event(p->subs[idx].dfd);
10282                tone_zone_play_tone(p->subs[idx].dfd, -1);
10283                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10284                unalloc_sub(p, SUB_THREEWAY);
10285                p->owner = p->subs[SUB_REAL].owner;
10286                ast_hangup(chan);
10287                goto quit;
10288             }
10289          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10290             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10291             && !canmatch_featurecode(exten)) {
10292             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10293                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10294                chan->context);
10295             break;
10296          }
10297          if (!timeout)
10298             timeout = gendigittimeout;
10299          if (len && !ast_ignore_pattern(chan->context, exten))
10300             tone_zone_play_tone(p->subs[idx].dfd, -1);
10301       }
10302       break;
10303    case SIG_FXSLS:
10304    case SIG_FXSGS:
10305    case SIG_FXSKS:
10306       /* check for SMDI messages */
10307       if (p->use_smdi && p->smdi_iface) {
10308          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10309 
10310          if (smdi_msg != NULL) {
10311             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10312 
10313             if (smdi_msg->type == 'B')
10314                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10315             else if (smdi_msg->type == 'N')
10316                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10317 
10318             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10319          } else {
10320             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10321          }
10322       }
10323 
10324       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10325          number = smdi_msg->calling_st;
10326 
10327       /* If we want caller id, we're in a prering state due to a polarity reversal
10328        * and we're set to use a polarity reversal to trigger the start of caller id,
10329        * grab the caller id and wait for ringing to start... */
10330       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10331                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10332          /* If set to use DTMF CID signalling, listen for DTMF */
10333          if (p->cid_signalling == CID_SIG_DTMF) {
10334             int k = 0;
10335             cs = NULL;
10336             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10337             dahdi_setlinear(p->subs[idx].dfd, 0);
10338             /*
10339              * We are the only party interested in the Rx stream since
10340              * we have not answered yet.  We don't need or even want DTMF
10341              * emulation.  The DTMF digits can come so fast that emulation
10342              * can drop some of them.
10343              */
10344             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10345             res = 4000;/* This is a typical OFF time between rings. */
10346             for (;;) {
10347                struct ast_frame *f;
10348                res = ast_waitfor(chan, res);
10349                if (res <= 0) {
10350                   /*
10351                    * We do not need to restore the dahdi_setlinear()
10352                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10353                    * are hanging up the channel.
10354                    */
10355                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10356                      "Exiting simple switch\n");
10357                   ast_hangup(chan);
10358                   goto quit;
10359                }
10360                f = ast_read(chan);
10361                if (!f)
10362                   break;
10363                if (f->frametype == AST_FRAME_DTMF) {
10364                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10365                      dtmfbuf[k++] = f->subclass.integer;
10366                   }
10367                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10368                   res = 4000;/* This is a typical OFF time between rings. */
10369                }
10370                ast_frfree(f);
10371                if (chan->_state == AST_STATE_RING ||
10372                   chan->_state == AST_STATE_RINGING)
10373                   break; /* Got ring */
10374             }
10375             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10376             dtmfbuf[k] = '\0';
10377             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10378             /* Got cid and ring. */
10379             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10380             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10381             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10382             /* If first byte is NULL, we have no cid */
10383             if (!ast_strlen_zero(dtmfcid))
10384                number = dtmfcid;
10385             else
10386                number = NULL;
10387          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10388          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10389             cs = callerid_new(p->cid_signalling);
10390             if (cs) {
10391                samples = 0;
10392 #if 1
10393                bump_gains(p);
10394 #endif
10395                /* Take out of linear mode for Caller*ID processing */
10396                dahdi_setlinear(p->subs[idx].dfd, 0);
10397 
10398                /* First we wait and listen for the Caller*ID */
10399                for (;;) {
10400                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10401                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10402                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10403                      callerid_free(cs);
10404                      ast_hangup(chan);
10405                      goto quit;
10406                   }
10407                   if (i & DAHDI_IOMUX_SIGEVENT) {
10408                      res = dahdi_get_event(p->subs[idx].dfd);
10409                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10410                      if (res == DAHDI_EVENT_NOALARM) {
10411                         p->inalarm = 0;
10412                      }
10413 
10414                      if (p->cid_signalling == CID_SIG_V23_JP) {
10415                         if (res == DAHDI_EVENT_RINGBEGIN) {
10416                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10417                            usleep(1);
10418                         }
10419                      } else {
10420                         res = 0;
10421                         break;
10422                      }
10423                   } else if (i & DAHDI_IOMUX_READ) {
10424                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10425                      if (res < 0) {
10426                         if (errno != ELAST) {
10427                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10428                            callerid_free(cs);
10429                            ast_hangup(chan);
10430                            goto quit;
10431                         }
10432                         break;
10433                      }
10434                      samples += res;
10435 
10436                      if (p->cid_signalling == CID_SIG_V23_JP) {
10437                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10438                      } else {
10439                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10440                      }
10441                      if (res < 0) {
10442                         /*
10443                          * The previous diagnostic message output likely
10444                          * explains why it failed.
10445                          */
10446                         ast_log(LOG_WARNING,
10447                            "Failed to decode CallerID on channel '%s'\n",
10448                            chan->name);
10449                         break;
10450                      } else if (res)
10451                         break;
10452                      else if (samples > (8000 * 10))
10453                         break;
10454                   }
10455                }
10456                if (res == 1) {
10457                   callerid_get(cs, &name, &number, &flags);
10458                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10459                }
10460 
10461                if (p->cid_signalling == CID_SIG_V23_JP) {
10462                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10463                   usleep(1);
10464                }
10465 
10466                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10467                res = 4000;/* This is a typical OFF time between rings. */
10468                for (;;) {
10469                   struct ast_frame *f;
10470                   res = ast_waitfor(chan, res);
10471                   if (res <= 0) {
10472                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10473                         "Exiting simple switch\n");
10474                      ast_hangup(chan);
10475                      goto quit;
10476                   }
10477                   if (!(f = ast_read(chan))) {
10478                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10479                      ast_hangup(chan);
10480                      goto quit;
10481                   }
10482                   ast_frfree(f);
10483                   if (chan->_state == AST_STATE_RING ||
10484                      chan->_state == AST_STATE_RINGING)
10485                      break; /* Got ring */
10486                }
10487 
10488                /* We must have a ring by now, so, if configured, lets try to listen for
10489                 * distinctive ringing */
10490                if (p->usedistinctiveringdetection) {
10491                   len = 0;
10492                   distMatches = 0;
10493                   /* Clear the current ring data array so we don't have old data in it. */
10494                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10495                      curRingData[receivedRingT] = 0;
10496                   receivedRingT = 0;
10497                   counter = 0;
10498                   counter1 = 0;
10499                   /* Check to see if context is what it should be, if not set to be. */
10500                   if (strcmp(p->context,p->defcontext) != 0) {
10501                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10502                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10503                   }
10504 
10505                   for (;;) {
10506                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10507                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10508                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10509                         callerid_free(cs);
10510                         ast_hangup(chan);
10511                         goto quit;
10512                      }
10513                      if (i & DAHDI_IOMUX_SIGEVENT) {
10514                         res = dahdi_get_event(p->subs[idx].dfd);
10515                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10516                         if (res == DAHDI_EVENT_NOALARM) {
10517                            p->inalarm = 0;
10518                         }
10519                         res = 0;
10520                         /* Let us detect distinctive ring */
10521 
10522                         curRingData[receivedRingT] = p->ringt;
10523 
10524                         if (p->ringt < p->ringt_base/2)
10525                            break;
10526                         /* Increment the ringT counter so we can match it against
10527                            values in chan_dahdi.conf for distinctive ring */
10528                         if (++receivedRingT == ARRAY_LEN(curRingData))
10529                            break;
10530                      } else if (i & DAHDI_IOMUX_READ) {
10531                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10532                         if (res < 0) {
10533                            if (errno != ELAST) {
10534                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10535                               callerid_free(cs);
10536                               ast_hangup(chan);
10537                               goto quit;
10538                            }
10539                            break;
10540                         }
10541                         if (p->ringt > 0) {
10542                            if (!(--p->ringt)) {
10543                               res = -1;
10544                               break;
10545                            }
10546                         }
10547                      }
10548                   }
10549                      /* this only shows up if you have n of the dring patterns filled in */
10550                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10551                   for (counter = 0; counter < 3; counter++) {
10552                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10553                      channel */
10554                      distMatches = 0;
10555                      for (counter1 = 0; counter1 < 3; counter1++) {
10556                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10557                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10558                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10559                            curRingData[counter1]);
10560                            distMatches++;
10561                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10562                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10563                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10564                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10565                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10566                            distMatches++;
10567                         }
10568                      }
10569 
10570                      if (distMatches == 3) {
10571                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10572                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10573                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10574                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10575                         break;
10576                      }
10577                   }
10578                }
10579                /* Restore linear mode (if appropriate) for Caller*ID processing */
10580                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10581 #if 1
10582                restore_gains(p);
10583 #endif
10584             } else
10585                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10586          } else {
10587             ast_log(LOG_WARNING, "Channel %s in prering "
10588                "state, but I have nothing to do. "
10589                "Terminating simple switch, should be "
10590                "restarted by the actual ring.\n",
10591                chan->name);
10592             ast_hangup(chan);
10593             goto quit;
10594          }
10595       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10596          if (p->cid_signalling == CID_SIG_DTMF) {
10597             int k = 0;
10598             cs = NULL;
10599             dahdi_setlinear(p->subs[idx].dfd, 0);
10600             res = 2000;
10601             for (;;) {
10602                struct ast_frame *f;
10603                res = ast_waitfor(chan, res);
10604                if (res <= 0) {
10605                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10606                      "Exiting simple switch\n");
10607                   ast_hangup(chan);
10608                   return NULL;
10609                }
10610                f = ast_read(chan);
10611                if (f->frametype == AST_FRAME_DTMF) {
10612                   dtmfbuf[k++] = f->subclass.integer;
10613                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10614                   res = 2000;
10615                }
10616                ast_frfree(f);
10617 
10618                if (p->ringt_base == p->ringt)
10619                   break;
10620             }
10621             dtmfbuf[k] = '\0';
10622             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10623             /* Got cid and ring. */
10624             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10625             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10626                dtmfcid, flags);
10627             /* If first byte is NULL, we have no cid */
10628             if (!ast_strlen_zero(dtmfcid))
10629                number = dtmfcid;
10630             else
10631                number = NULL;
10632             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10633          } else {
10634             /* FSK Bell202 callerID */
10635             cs = callerid_new(p->cid_signalling);
10636             if (cs) {
10637 #if 1
10638                bump_gains(p);
10639 #endif
10640                samples = 0;
10641                len = 0;
10642                distMatches = 0;
10643                /* Clear the current ring data array so we don't have old data in it. */
10644                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10645                   curRingData[receivedRingT] = 0;
10646                receivedRingT = 0;
10647                counter = 0;
10648                counter1 = 0;
10649                /* Check to see if context is what it should be, if not set to be. */
10650                if (strcmp(p->context,p->defcontext) != 0) {
10651                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10652                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10653                }
10654 
10655                /* Take out of linear mode for Caller*ID processing */
10656                dahdi_setlinear(p->subs[idx].dfd, 0);
10657                for (;;) {
10658                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10659                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10660                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10661                      callerid_free(cs);
10662                      ast_hangup(chan);
10663                      goto quit;
10664                   }
10665                   if (i & DAHDI_IOMUX_SIGEVENT) {
10666                      res = dahdi_get_event(p->subs[idx].dfd);
10667                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10668                      if (res == DAHDI_EVENT_NOALARM) {
10669                         p->inalarm = 0;
10670                      }
10671                      /* If we get a PR event, they hung up while processing calerid */
10672                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10673                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10674                         p->polarity = POLARITY_IDLE;
10675                         callerid_free(cs);
10676                         ast_hangup(chan);
10677                         goto quit;
10678                      }
10679                      res = 0;
10680                      /* Let us detect callerid when the telco uses distinctive ring */
10681 
10682                      curRingData[receivedRingT] = p->ringt;
10683 
10684                      if (p->ringt < p->ringt_base/2)
10685                         break;
10686                      /* Increment the ringT counter so we can match it against
10687                         values in chan_dahdi.conf for distinctive ring */
10688                      if (++receivedRingT == ARRAY_LEN(curRingData))
10689                         break;
10690                   } else if (i & DAHDI_IOMUX_READ) {
10691                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10692                      if (res < 0) {
10693                         if (errno != ELAST) {
10694                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10695                            callerid_free(cs);
10696                            ast_hangup(chan);
10697                            goto quit;
10698                         }
10699                         break;
10700                      }
10701                      if (p->ringt > 0) {
10702                         if (!(--p->ringt)) {
10703                            res = -1;
10704                            break;
10705                         }
10706                      }
10707                      samples += res;
10708                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10709                      if (res < 0) {
10710                         /*
10711                          * The previous diagnostic message output likely
10712                          * explains why it failed.
10713                          */
10714                         ast_log(LOG_WARNING,
10715                            "Failed to decode CallerID on channel '%s'\n",
10716                            chan->name);
10717                         break;
10718                      } else if (res)
10719                         break;
10720                      else if (samples > (8000 * 10))
10721                         break;
10722                   }
10723                }
10724                if (res == 1) {
10725                   callerid_get(cs, &name, &number, &flags);
10726                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10727                }
10728                if (distinctiveringaftercid == 1) {
10729                   /* Clear the current ring data array so we don't have old data in it. */
10730                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10731                      curRingData[receivedRingT] = 0;
10732                   }
10733                   receivedRingT = 0;
10734                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10735                   for (;;) {
10736                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10737                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10738                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10739                         callerid_free(cs);
10740                         ast_hangup(chan);
10741                         goto quit;
10742                      }
10743                      if (i & DAHDI_IOMUX_SIGEVENT) {
10744                         res = dahdi_get_event(p->subs[idx].dfd);
10745                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10746                         if (res == DAHDI_EVENT_NOALARM) {
10747                            p->inalarm = 0;
10748                         }
10749                         res = 0;
10750                         /* Let us detect callerid when the telco uses distinctive ring */
10751 
10752                         curRingData[receivedRingT] = p->ringt;
10753 
10754                         if (p->ringt < p->ringt_base/2)
10755                            break;
10756                         /* Increment the ringT counter so we can match it against
10757                            values in chan_dahdi.conf for distinctive ring */
10758                         if (++receivedRingT == ARRAY_LEN(curRingData))
10759                            break;
10760                      } else if (i & DAHDI_IOMUX_READ) {
10761                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10762                         if (res < 0) {
10763                            if (errno != ELAST) {
10764                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10765                               callerid_free(cs);
10766                               ast_hangup(chan);
10767                               goto quit;
10768                            }
10769                            break;
10770                         }
10771                         if (p->ringt > 0) {
10772                            if (!(--p->ringt)) {
10773                               res = -1;
10774                               break;
10775                            }
10776                         }
10777                      }
10778                   }
10779                }
10780                if (p->usedistinctiveringdetection) {
10781                   /* this only shows up if you have n of the dring patterns filled in */
10782                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10783 
10784                   for (counter = 0; counter < 3; counter++) {
10785                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10786                      channel */
10787                      /* this only shows up if you have n of the dring patterns filled in */
10788                      ast_verb(3, "Checking %d,%d,%d\n",
10789                            p->drings.ringnum[counter].ring[0],
10790                            p->drings.ringnum[counter].ring[1],
10791                            p->drings.ringnum[counter].ring[2]);
10792                      distMatches = 0;
10793                      for (counter1 = 0; counter1 < 3; counter1++) {
10794                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10795                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10796                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10797                            curRingData[counter1]);
10798                            distMatches++;
10799                         }
10800                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10801                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10802                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10803                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10804                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10805                            distMatches++;
10806                         }
10807                      }
10808                      if (distMatches == 3) {
10809                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10810                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10811                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10812                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10813                         break;
10814                      }
10815                   }
10816                }
10817                /* Restore linear mode (if appropriate) for Caller*ID processing */
10818                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10819 #if 1
10820                restore_gains(p);
10821 #endif
10822                if (res < 0) {
10823                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10824                }
10825             } else
10826                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10827          }
10828       } else
10829          cs = NULL;
10830 
10831       if (number)
10832          ast_shrink_phone_number(number);
10833       ast_set_callerid(chan, number, name, number);
10834 
10835       if (smdi_msg)
10836          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10837 
10838       if (cs)
10839          callerid_free(cs);
10840 
10841       my_handle_notify_message(chan, p, flags, -1);
10842 
10843       ast_setstate(chan, AST_STATE_RING);
10844       chan->rings = 1;
10845       p->ringt = p->ringt_base;
10846       res = ast_pbx_run(chan);
10847       if (res) {
10848          ast_hangup(chan);
10849          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10850       }
10851       goto quit;
10852    default:
10853       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10854       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10855       if (res < 0)
10856             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10857    }
10858    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10859    if (res < 0)
10860          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10861    ast_hangup(chan);
10862 quit:
10863    ast_mutex_lock(&ss_thread_lock);
10864    ss_thread_count--;
10865    ast_cond_signal(&ss_thread_complete);
10866    ast_mutex_unlock(&ss_thread_lock);
10867    return NULL;
10868 }
10869 
10870 struct mwi_thread_data {
10871    struct dahdi_pvt *pvt;
10872    unsigned char buf[READ_SIZE];
10873    size_t len;
10874 };
10875 
10876 static int calc_energy(const unsigned char *buf, int len, format_t law)
10877 {
10878    int x;
10879    int sum = 0;
10880 
10881    if (!len)
10882       return 0;
10883 
10884    for (x = 0; x < len; x++)
10885       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10886 
10887    return sum / len;
10888 }
10889 
10890 static void *mwi_thread(void *data)
10891 {
10892    struct mwi_thread_data *mtd = data;
10893    struct callerid_state *cs;
10894    pthread_t threadid;
10895    int samples = 0;
10896    char *name, *number;
10897    int flags;
10898    int i, res;
10899    unsigned int spill_done = 0;
10900    int spill_result = -1;
10901 
10902    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10903       mtd->pvt->mwimonitoractive = 0;
10904 
10905       return NULL;
10906    }
10907 
10908    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10909 
10910    bump_gains(mtd->pvt);
10911 
10912    for (;;) {
10913       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10914       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10915          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10916          goto quit;
10917       }
10918 
10919       if (i & DAHDI_IOMUX_SIGEVENT) {
10920          struct ast_channel *chan;
10921 
10922          /* If we get an event, screen out events that we do not act on.
10923           * Otherwise, cancel and go to the simple switch to let it deal with it.
10924           */
10925          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10926 
10927          switch (res) {
10928          case DAHDI_EVENT_NEONMWI_ACTIVE:
10929          case DAHDI_EVENT_NEONMWI_INACTIVE:
10930          case DAHDI_EVENT_NONE:
10931          case DAHDI_EVENT_BITSCHANGED:
10932             break;
10933          case DAHDI_EVENT_NOALARM:
10934             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10935                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10936 
10937                analog_p->inalarm = 0;
10938             }
10939             mtd->pvt->inalarm = 0;
10940             handle_clear_alarms(mtd->pvt);
10941             break;
10942          case DAHDI_EVENT_ALARM:
10943             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10944                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10945 
10946                analog_p->inalarm = 1;
10947             }
10948             mtd->pvt->inalarm = 1;
10949             res = get_alarms(mtd->pvt);
10950             handle_alarms(mtd->pvt, res);
10951             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
10952          default:
10953             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
10954             callerid_free(cs);
10955 
10956             restore_gains(mtd->pvt);
10957             mtd->pvt->ringt = mtd->pvt->ringt_base;
10958 
10959             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10960                int result;
10961                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10962                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10963                } else {
10964                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10965                }
10966                if (result) {
10967                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10968                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10969                   if (res < 0)
10970                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10971                   ast_hangup(chan);
10972                   goto quit;
10973                }
10974                goto quit_no_clean;
10975 
10976             } else {
10977                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10978             }
10979          }
10980       } else if (i & DAHDI_IOMUX_READ) {
10981          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10982             if (errno != ELAST) {
10983                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10984                goto quit;
10985             }
10986             break;
10987          }
10988          samples += res;
10989          if (!spill_done) {
10990             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10991                /*
10992                 * The previous diagnostic message output likely
10993                 * explains why it failed.
10994                 */
10995                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10996                break;
10997             } else if (spill_result) {
10998                spill_done = 1;
10999             }
11000          } else {
11001             /* keep reading data until the energy level drops below the threshold
11002                so we don't get another 'trigger' on the remaining carrier signal
11003             */
11004             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11005                break;
11006          }
11007          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11008             break;
11009       }
11010    }
11011 
11012    if (spill_result == 1) {
11013       callerid_get(cs, &name, &number, &flags);
11014       if (flags & CID_MSGWAITING) {
11015          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11016          notify_message(mtd->pvt->mailbox, 1);
11017       } else if (flags & CID_NOMSGWAITING) {
11018          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11019          notify_message(mtd->pvt->mailbox, 0);
11020       } else {
11021          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11022       }
11023    }
11024 
11025 
11026 quit:
11027    callerid_free(cs);
11028 
11029    restore_gains(mtd->pvt);
11030 
11031 quit_no_clean:
11032    mtd->pvt->mwimonitoractive = 0;
11033 
11034    ast_free(mtd);
11035 
11036    return NULL;
11037 }
11038 
11039 /*
11040 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11041 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11042 * that are sent out via FXS port on voicemail state change.  The execution of
11043 * the mwi send is state driven and can either generate a ring pulse prior to
11044 * sending the fsk spill or simply send an fsk spill.
11045 */
11046 static int mwi_send_init(struct dahdi_pvt * pvt)
11047 {
11048    int x;
11049 
11050 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11051    /* Determine how this spill is to be sent */
11052    if (pvt->mwisend_rpas) {
11053       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11054       pvt->mwisendactive = 1;
11055    } else if (pvt->mwisend_fsk) {
11056       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11057       pvt->mwisendactive = 1;
11058    } else {
11059       pvt->mwisendactive = 0;
11060       return 0;
11061    }
11062 #else
11063    if (mwisend_rpas) {
11064       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11065    } else {
11066       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11067    }
11068    pvt->mwisendactive = 1;
11069 #endif
11070 
11071    if (pvt->cidspill) {
11072       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11073       ast_free(pvt->cidspill);
11074       pvt->cidspill = NULL;
11075       pvt->cidpos = 0;
11076       pvt->cidlen = 0;
11077    }
11078    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11079    if (!pvt->cidspill) {
11080       pvt->mwisendactive = 0;
11081       return -1;
11082    }
11083    x = DAHDI_FLUSH_BOTH;
11084    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11085    x = 3000;
11086    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11087 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11088    if (pvt->mwisend_fsk) {
11089 #endif
11090       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11091                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11092       pvt->cidpos = 0;
11093 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11094    }
11095 #endif
11096    return 0;
11097 }
11098 
11099 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11100 {
11101    struct timeval    now;
11102    int         res;
11103 
11104    /* sanity check to catch if this had been interrupted previously
11105    *  i.e. state says there is more to do but there is no spill allocated
11106    */
11107    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11108       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11109    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11110       /* Normal processing -- Perform mwi send action */
11111       switch ( pvt->mwisend_data.mwisend_current) {
11112       case MWI_SEND_SA:
11113          /* Send the Ring Pulse Signal Alert */
11114          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11115          if (res) {
11116             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11117             goto quit;
11118          }
11119          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11120          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11121          break;
11122       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11123          break;
11124       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11125 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11126          if (pvt->mwisend_fsk) {
11127 #endif
11128             gettimeofday(&now, NULL);
11129             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11130                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11131             }
11132 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11133          } else { /* support for mwisendtype=nofsk */
11134             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11135          }
11136 #endif
11137          break;
11138       case MWI_SEND_SPILL:
11139          /* We read some number of bytes.  Write an equal amount of data */
11140          if(0 < num_read) {
11141             if (num_read > pvt->cidlen - pvt->cidpos)
11142                num_read = pvt->cidlen - pvt->cidpos;
11143             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11144             if (res > 0) {
11145                pvt->cidpos += res;
11146                if (pvt->cidpos >= pvt->cidlen) {
11147                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11148                }
11149             } else {
11150                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11151                goto quit;
11152             }
11153          }
11154          break;
11155       case MWI_SEND_CLEANUP:
11156          /* For now, do nothing */
11157          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11158          break;
11159       default:
11160          /* Should not get here, punt*/
11161          goto quit;
11162       }
11163    }
11164 
11165    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11166       if (pvt->cidspill) {
11167          ast_free(pvt->cidspill);
11168          pvt->cidspill = NULL;
11169          pvt->cidpos = 0;
11170          pvt->cidlen = 0;
11171       }
11172       pvt->mwisendactive = 0;
11173    }
11174    return 0;
11175 quit:
11176    if (pvt->cidspill) {
11177       ast_free(pvt->cidspill);
11178       pvt->cidspill = NULL;
11179       pvt->cidpos = 0;
11180       pvt->cidlen = 0;
11181    }
11182    pvt->mwisendactive = 0;
11183    return -1;
11184 }
11185 
11186 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11187 {
11188    int handled = 0;
11189 
11190    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11191       switch (event) {
11192       case DAHDI_EVENT_RINGEROFF:
11193          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11194             handled = 1;
11195 
11196             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11197                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11198                ast_free(pvt->cidspill);
11199                pvt->cidspill = NULL;
11200                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11201                pvt->mwisendactive = 0;
11202             } else {
11203                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11204                gettimeofday(&pvt->mwisend_data.pause, NULL);
11205             }
11206          }
11207          break;
11208       /* Going off hook, I need to punt this spill */
11209       case DAHDI_EVENT_RINGOFFHOOK:
11210          if (pvt->cidspill) {
11211             ast_free(pvt->cidspill);
11212             pvt->cidspill = NULL;
11213             pvt->cidpos = 0;
11214             pvt->cidlen = 0;
11215          }
11216          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11217          pvt->mwisendactive = 0;
11218          break;
11219       case DAHDI_EVENT_RINGERON:
11220       case DAHDI_EVENT_HOOKCOMPLETE:
11221          break;
11222       default:
11223          break;
11224       }
11225    }
11226    return handled;
11227 }
11228 
11229 /* destroy a DAHDI channel, identified by its number */
11230 static int dahdi_destroy_channel_bynum(int channel)
11231 {
11232    struct dahdi_pvt *cur;
11233 
11234    ast_mutex_lock(&iflock);
11235    for (cur = iflist; cur; cur = cur->next) {
11236       if (cur->channel == channel) {
11237          int x = DAHDI_FLASH;
11238 
11239          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11240          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11241 
11242          destroy_channel(cur, 1);
11243          ast_mutex_unlock(&iflock);
11244          ast_module_unref(ast_module_info->self);
11245          return RESULT_SUCCESS;
11246       }
11247    }
11248    ast_mutex_unlock(&iflock);
11249    return RESULT_FAILURE;
11250 }
11251 
11252 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11253 {
11254    int res;
11255    pthread_t threadid;
11256    struct ast_channel *chan;
11257 
11258    /* Handle an event on a given channel for the monitor thread. */
11259 
11260    switch (event) {
11261    case DAHDI_EVENT_NONE:
11262    case DAHDI_EVENT_BITSCHANGED:
11263       break;
11264    case DAHDI_EVENT_WINKFLASH:
11265    case DAHDI_EVENT_RINGOFFHOOK:
11266       if (i->inalarm) break;
11267       if (i->radio) break;
11268       /* Got a ring/answer.  What kind of channel are we? */
11269       switch (i->sig) {
11270       case SIG_FXOLS:
11271       case SIG_FXOGS:
11272       case SIG_FXOKS:
11273          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11274          if (res && (errno == EBUSY))
11275             break;
11276 
11277          /* Cancel VMWI spill */
11278          ast_free(i->cidspill);
11279          i->cidspill = NULL;
11280          restore_conference(i);
11281 
11282          if (i->immediate) {
11283             dahdi_enable_ec(i);
11284             /* The channel is immediately up.  Start right away */
11285             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11286             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11287             if (!chan) {
11288                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11289                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11290                if (res < 0)
11291                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11292             }
11293          } else {
11294             /* Check for callerid, digits, etc */
11295             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11296             if (chan) {
11297                if (has_voicemail(i))
11298                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11299                else
11300                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11301                if (res < 0)
11302                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11303                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11304                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11305                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11306                   if (res < 0)
11307                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11308                   ast_hangup(chan);
11309                }
11310             } else
11311                ast_log(LOG_WARNING, "Unable to create channel\n");
11312          }
11313          break;
11314       case SIG_FXSLS:
11315       case SIG_FXSGS:
11316       case SIG_FXSKS:
11317             i->ringt = i->ringt_base;
11318             /* Fall through */
11319       case SIG_EMWINK:
11320       case SIG_FEATD:
11321       case SIG_FEATDMF:
11322       case SIG_FEATDMF_TA:
11323       case SIG_E911:
11324       case SIG_FGC_CAMA:
11325       case SIG_FGC_CAMAMF:
11326       case SIG_FEATB:
11327       case SIG_EM:
11328       case SIG_EM_E1:
11329       case SIG_SFWINK:
11330       case SIG_SF_FEATD:
11331       case SIG_SF_FEATDMF:
11332       case SIG_SF_FEATB:
11333       case SIG_SF:
11334          /* Check for callerid, digits, etc */
11335          if (i->cid_start == CID_START_POLARITY_IN) {
11336             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11337          } else {
11338             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11339          }
11340 
11341          if (!chan) {
11342             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11343          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11344             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11345             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11346             if (res < 0) {
11347                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11348             }
11349             ast_hangup(chan);
11350          }
11351          break;
11352       default:
11353          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11354          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11355          if (res < 0)
11356             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11357          return NULL;
11358       }
11359       break;
11360    case DAHDI_EVENT_NOALARM:
11361       switch (i->sig) {
11362 #if defined(HAVE_PRI)
11363       case SIG_PRI_LIB_HANDLE_CASES:
11364          ast_mutex_lock(&i->lock);
11365          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11366          ast_mutex_unlock(&i->lock);
11367          break;
11368 #endif   /* defined(HAVE_PRI) */
11369 #if defined(HAVE_SS7)
11370       case SIG_SS7:
11371          sig_ss7_set_alarm(i->sig_pvt, 0);
11372          break;
11373 #endif   /* defined(HAVE_SS7) */
11374       default:
11375          i->inalarm = 0;
11376          break;
11377       }
11378       handle_clear_alarms(i);
11379       break;
11380    case DAHDI_EVENT_ALARM:
11381       switch (i->sig) {
11382 #if defined(HAVE_PRI)
11383       case SIG_PRI_LIB_HANDLE_CASES:
11384          ast_mutex_lock(&i->lock);
11385          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11386          ast_mutex_unlock(&i->lock);
11387          break;
11388 #endif   /* defined(HAVE_PRI) */
11389 #if defined(HAVE_SS7)
11390       case SIG_SS7:
11391          sig_ss7_set_alarm(i->sig_pvt, 1);
11392          break;
11393 #endif   /* defined(HAVE_SS7) */
11394       default:
11395          i->inalarm = 1;
11396          break;
11397       }
11398       res = get_alarms(i);
11399       handle_alarms(i, res);
11400       /* fall thru intentionally */
11401    case DAHDI_EVENT_ONHOOK:
11402       if (i->radio)
11403          break;
11404       /* Back on hook.  Hang up. */
11405       switch (i->sig) {
11406       case SIG_FXOLS:
11407       case SIG_FXOGS:
11408       case SIG_FEATD:
11409       case SIG_FEATDMF:
11410       case SIG_FEATDMF_TA:
11411       case SIG_E911:
11412       case SIG_FGC_CAMA:
11413       case SIG_FGC_CAMAMF:
11414       case SIG_FEATB:
11415       case SIG_EM:
11416       case SIG_EM_E1:
11417       case SIG_EMWINK:
11418       case SIG_SF_FEATD:
11419       case SIG_SF_FEATDMF:
11420       case SIG_SF_FEATB:
11421       case SIG_SF:
11422       case SIG_SFWINK:
11423       case SIG_FXSLS:
11424       case SIG_FXSGS:
11425       case SIG_FXSKS:
11426       case SIG_FXOKS:
11427          dahdi_disable_ec(i);
11428          /* Diddle the battery for the zhone */
11429 #ifdef ZHONE_HACK
11430          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11431          usleep(1);
11432 #endif
11433          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11434          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11435          break;
11436       case SIG_SS7:
11437       case SIG_PRI_LIB_HANDLE_CASES:
11438          dahdi_disable_ec(i);
11439          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11440          break;
11441       default:
11442          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11443          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11444          return NULL;
11445       }
11446       break;
11447    case DAHDI_EVENT_POLARITY:
11448       switch (i->sig) {
11449       case SIG_FXSLS:
11450       case SIG_FXSKS:
11451       case SIG_FXSGS:
11452          /* We have already got a PR before the channel was
11453             created, but it wasn't handled. We need polarity
11454             to be REV for remote hangup detection to work.
11455             At least in Spain */
11456          if (i->hanguponpolarityswitch)
11457             i->polarity = POLARITY_REV;
11458          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11459             i->polarity = POLARITY_REV;
11460             ast_verb(2, "Starting post polarity "
11461                "CID detection on channel %d\n",
11462                i->channel);
11463             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11464             if (!chan) {
11465                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11466             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11467                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11468             }
11469          }
11470          break;
11471       default:
11472          ast_log(LOG_WARNING, "handle_init_event detected "
11473             "polarity reversal on non-FXO (SIG_FXS) "
11474             "interface %d\n", i->channel);
11475       }
11476       break;
11477    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11478       ast_log(LOG_NOTICE,
11479             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11480             i->channel);
11481       return i;
11482    case DAHDI_EVENT_NEONMWI_ACTIVE:
11483       if (i->mwimonitor_neon) {
11484          notify_message(i->mailbox, 1);
11485          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11486       }
11487       break;
11488    case DAHDI_EVENT_NEONMWI_INACTIVE:
11489       if (i->mwimonitor_neon) {
11490          notify_message(i->mailbox, 0);
11491          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11492       }
11493       break;
11494    }
11495    return NULL;
11496 }
11497 
11498 static void *do_monitor(void *data)
11499 {
11500    int count, res, res2, spoint, pollres=0;
11501    struct dahdi_pvt *i;
11502    struct dahdi_pvt *last = NULL;
11503    struct dahdi_pvt *doomed;
11504    time_t thispass = 0, lastpass = 0;
11505    int found;
11506    char buf[1024];
11507    struct pollfd *pfds=NULL;
11508    int lastalloc = -1;
11509    /* This thread monitors all the frame relay interfaces which are not yet in use
11510       (and thus do not have a separate thread) indefinitely */
11511    /* From here on out, we die whenever asked */
11512 #if 0
11513    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11514       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11515       return NULL;
11516    }
11517    ast_debug(1, "Monitor starting...\n");
11518 #endif
11519    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11520 
11521    for (;;) {
11522       /* Lock the interface list */
11523       ast_mutex_lock(&iflock);
11524       if (!pfds || (lastalloc != ifcount)) {
11525          if (pfds) {
11526             ast_free(pfds);
11527             pfds = NULL;
11528          }
11529          if (ifcount) {
11530             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11531                ast_mutex_unlock(&iflock);
11532                return NULL;
11533             }
11534          }
11535          lastalloc = ifcount;
11536       }
11537       /* Build the stuff we're going to poll on, that is the socket of every
11538          dahdi_pvt that does not have an associated owner channel */
11539       count = 0;
11540       for (i = iflist; i; i = i->next) {
11541          ast_mutex_lock(&i->lock);
11542          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11543             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11544                struct analog_pvt *p = i->sig_pvt;
11545 
11546                if (!p)
11547                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11548 
11549                if (!p->owner && !p->subs[SUB_REAL].owner) {
11550                   /* This needs to be watched, as it lacks an owner */
11551                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11552                   pfds[count].events = POLLPRI;
11553                   pfds[count].revents = 0;
11554                   /* Message waiting or r2 channels also get watched for reading */
11555                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11556                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11557                      pfds[count].events |= POLLIN;
11558                   }
11559                   count++;
11560                }
11561             } else {
11562                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11563                   /* This needs to be watched, as it lacks an owner */
11564                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11565                   pfds[count].events = POLLPRI;
11566                   pfds[count].revents = 0;
11567                   /* If we are monitoring for VMWI or sending CID, we need to
11568                      read from the channel as well */
11569                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11570                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11571                      pfds[count].events |= POLLIN;
11572                   }
11573                   count++;
11574                }
11575             }
11576          }
11577          ast_mutex_unlock(&i->lock);
11578       }
11579       /* Okay, now that we know what to do, release the interface lock */
11580       ast_mutex_unlock(&iflock);
11581 
11582       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11583       pthread_testcancel();
11584       /* Wait at least a second for something to happen */
11585       res = poll(pfds, count, 1000);
11586       pthread_testcancel();
11587       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11588 
11589       /* Okay, poll has finished.  Let's see what happened.  */
11590       if (res < 0) {
11591          if ((errno != EAGAIN) && (errno != EINTR))
11592             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11593          continue;
11594       }
11595       /* Alright, lock the interface list again, and let's look and see what has
11596          happened */
11597       ast_mutex_lock(&iflock);
11598       found = 0;
11599       spoint = 0;
11600       lastpass = thispass;
11601       thispass = time(NULL);
11602       doomed = NULL;
11603       for (i = iflist;; i = i->next) {
11604          if (doomed) {
11605             int res;
11606             res = dahdi_destroy_channel_bynum(doomed->channel);
11607             if (res != RESULT_SUCCESS) {
11608                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11609             }
11610             doomed = NULL;
11611          }
11612          if (!i) {
11613             break;
11614          }
11615 
11616          if (thispass != lastpass) {
11617             if (!found && ((i == last) || ((i == iflist) && !last))) {
11618                last = i;
11619                if (last) {
11620                   struct analog_pvt *analog_p = last->sig_pvt;
11621                   /* Only allow MWI to be initiated on a quiescent fxs port */
11622                   if (analog_p
11623                      && !last->mwisendactive
11624                      && (last->sig & __DAHDI_SIG_FXO)
11625                      && !analog_p->fxsoffhookstate
11626                      && !last->owner
11627                      && !ast_strlen_zero(last->mailbox)
11628                      && (thispass - analog_p->onhooktime > 3)) {
11629                      res = has_voicemail(last);
11630                      if (analog_p->msgstate != res) {
11631                         /* Set driver resources for signalling VMWI */
11632                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11633                         if (res2) {
11634                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11635                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11636                         }
11637                         /* If enabled for FSK spill then initiate it */
11638                         if (mwi_send_init(last)) {
11639                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11640                         }
11641                         analog_p->msgstate = res;
11642                         found ++;
11643                      }
11644                   }
11645                   last = last->next;
11646                }
11647             }
11648          }
11649          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11650             if (i->radio && !i->owner)
11651             {
11652                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11653                if (res)
11654                {
11655                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11656                   /* Don't hold iflock while handling init events */
11657                   ast_mutex_unlock(&iflock);
11658                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11659                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11660                   else
11661                      doomed = handle_init_event(i, res);
11662                   ast_mutex_lock(&iflock);
11663                }
11664                continue;
11665             }
11666             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11667             if (pollres & POLLIN) {
11668                if (i->owner || i->subs[SUB_REAL].owner) {
11669 #ifdef HAVE_PRI
11670                   if (!i->pri)
11671 #endif
11672                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11673                   continue;
11674                }
11675                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11676                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11677                   continue;
11678                }
11679                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11680                if (res > 0) {
11681                   if (i->mwimonitor_fsk) {
11682                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11683                         pthread_attr_t attr;
11684                         pthread_t threadid;
11685                         struct mwi_thread_data *mtd;
11686 
11687                         pthread_attr_init(&attr);
11688                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11689 
11690                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11691                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11692                            mtd->pvt = i;
11693                            memcpy(mtd->buf, buf, res);
11694                            mtd->len = res;
11695                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11696                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11697                               ast_free(mtd);
11698                            }
11699                            i->mwimonitoractive = 1;
11700                         }
11701                      }
11702                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11703                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11704                      int energy;
11705                      struct timeval now;
11706                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11707                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11708                      */
11709                      if (1 == i->dtmfcid_holdoff_state) {
11710                         gettimeofday(&i->dtmfcid_delay, NULL);
11711                         i->dtmfcid_holdoff_state = 2;
11712                      } else if (2 == i->dtmfcid_holdoff_state) {
11713                         gettimeofday(&now, NULL);
11714                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11715                            i->dtmfcid_holdoff_state = 0;
11716                         }
11717                      } else {
11718                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11719                         if (!i->mwisendactive && energy > dtmfcid_level) {
11720                            pthread_t threadid;
11721                            struct ast_channel *chan;
11722                            ast_mutex_unlock(&iflock);
11723                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11724                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11725                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11726                               i->dtmfcid_holdoff_state = 1;
11727                            } else {
11728                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11729                               if (!chan) {
11730                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11731                               } else {
11732                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11733                                  if (res) {
11734                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11735                                  } else {
11736                                     i->dtmfcid_holdoff_state = 1;
11737                                  }
11738                               }
11739                            }
11740                            ast_mutex_lock(&iflock);
11741                         }
11742                      }
11743                   }
11744                   if (i->mwisendactive) {
11745                      mwi_send_process_buffer(i, res);
11746                   }
11747                } else {
11748                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11749                }
11750             }
11751             if (pollres & POLLPRI) {
11752                if (i->owner || i->subs[SUB_REAL].owner) {
11753 #ifdef HAVE_PRI
11754                   if (!i->pri)
11755 #endif
11756                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11757                   continue;
11758                }
11759                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11760                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11761                /* Don't hold iflock while handling init events */
11762                ast_mutex_unlock(&iflock);
11763                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11764                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11765                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11766                   else
11767                      doomed = handle_init_event(i, res);
11768                }
11769                ast_mutex_lock(&iflock);
11770             }
11771          }
11772       }
11773       ast_mutex_unlock(&iflock);
11774    }
11775    /* Never reached */
11776    return NULL;
11777 
11778 }
11779 
11780 static int restart_monitor(void)
11781 {
11782    /* If we're supposed to be stopped -- stay stopped */
11783    if (monitor_thread == AST_PTHREADT_STOP)
11784       return 0;
11785    ast_mutex_lock(&monlock);
11786    if (monitor_thread == pthread_self()) {
11787       ast_mutex_unlock(&monlock);
11788       ast_log(LOG_WARNING, "Cannot kill myself\n");
11789       return -1;
11790    }
11791    if (monitor_thread != AST_PTHREADT_NULL) {
11792       /* Wake up the thread */
11793       pthread_kill(monitor_thread, SIGURG);
11794    } else {
11795       /* Start a new monitor */
11796       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11797          ast_mutex_unlock(&monlock);
11798          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11799          return -1;
11800       }
11801    }
11802    ast_mutex_unlock(&monlock);
11803    return 0;
11804 }
11805 
11806 #if defined(HAVE_PRI)
11807 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11808 {
11809    int x;
11810    int trunkgroup;
11811    /* Get appropriate trunk group if there is one */
11812    trunkgroup = pris[*span].mastertrunkgroup;
11813    if (trunkgroup) {
11814       /* Select a specific trunk group */
11815       for (x = 0; x < NUM_SPANS; x++) {
11816          if (pris[x].pri.trunkgroup == trunkgroup) {
11817             *span = x;
11818             return 0;
11819          }
11820       }
11821       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11822       *span = -1;
11823    } else {
11824       if (pris[*span].pri.trunkgroup) {
11825          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
11826          *span = -1;
11827       } else if (pris[*span].mastertrunkgroup) {
11828          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11829          *span = -1;
11830       } else {
11831          if (si->totalchans == 31) {
11832             /* E1 */
11833             pris[*span].dchannels[0] = 16 + offset;
11834          } else if (si->totalchans == 24) {
11835             /* T1 or J1 */
11836             pris[*span].dchannels[0] = 24 + offset;
11837          } else if (si->totalchans == 3) {
11838             /* BRI */
11839             pris[*span].dchannels[0] = 3 + offset;
11840          } else {
11841             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
11842             *span = -1;
11843             return 0;
11844          }
11845          pris[*span].pri.span = *span + 1;
11846       }
11847    }
11848    return 0;
11849 }
11850 #endif   /* defined(HAVE_PRI) */
11851 
11852 #if defined(HAVE_PRI)
11853 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11854 {
11855    struct dahdi_spaninfo si;
11856    struct dahdi_params p;
11857    int fd;
11858    int span;
11859    int ospan=0;
11860    int x,y;
11861    for (x = 0; x < NUM_SPANS; x++) {
11862       if (pris[x].pri.trunkgroup == trunkgroup) {
11863          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11864          return -1;
11865       }
11866    }
11867    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11868       if (!channels[y])
11869          break;
11870       memset(&si, 0, sizeof(si));
11871       memset(&p, 0, sizeof(p));
11872       fd = open("/dev/dahdi/channel", O_RDWR);
11873       if (fd < 0) {
11874          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11875          return -1;
11876       }
11877       x = channels[y];
11878       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11879          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11880          close(fd);
11881          return -1;
11882       }
11883       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11884          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11885          return -1;
11886       }
11887       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11888          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11889          close(fd);
11890          return -1;
11891       }
11892       span = p.spanno - 1;
11893       if (pris[span].pri.trunkgroup) {
11894          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11895          close(fd);
11896          return -1;
11897       }
11898       if (pris[span].pri.pvts[0]) {
11899          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11900          close(fd);
11901          return -1;
11902       }
11903       if (!y) {
11904          pris[span].pri.trunkgroup = trunkgroup;
11905          ospan = span;
11906       }
11907       pris[ospan].dchannels[y] = channels[y];
11908       pris[span].pri.span = span + 1;
11909       close(fd);
11910    }
11911    return 0;
11912 }
11913 #endif   /* defined(HAVE_PRI) */
11914 
11915 #if defined(HAVE_PRI)
11916 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11917 {
11918    if (pris[span].mastertrunkgroup) {
11919       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
11920       return -1;
11921    }
11922    pris[span].mastertrunkgroup = trunkgroup;
11923    pris[span].prilogicalspan = logicalspan;
11924    return 0;
11925 }
11926 #endif   /* defined(HAVE_PRI) */
11927 
11928 #if defined(HAVE_SS7)
11929 static unsigned int parse_pointcode(const char *pcstring)
11930 {
11931    unsigned int code1, code2, code3;
11932    int numvals;
11933 
11934    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11935    if (numvals == 1)
11936       return code1;
11937    if (numvals == 3)
11938       return (code1 << 16) | (code2 << 8) | code3;
11939 
11940    return 0;
11941 }
11942 #endif   /* defined(HAVE_SS7) */
11943 
11944 #if defined(HAVE_SS7)
11945 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11946 {
11947    if ((linkset < 0) || (linkset >= NUM_SPANS))
11948       return NULL;
11949    else
11950       return &linksets[linkset - 1];
11951 }
11952 #endif   /* defined(HAVE_SS7) */
11953 
11954 #ifdef HAVE_OPENR2
11955 static void dahdi_r2_destroy_links(void)
11956 {
11957    int i = 0;
11958    if (!r2links) {
11959       return;
11960    }
11961    for (; i < r2links_count; i++) {
11962       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11963          pthread_cancel(r2links[i]->r2master);
11964          pthread_join(r2links[i]->r2master, NULL);
11965          openr2_context_delete(r2links[i]->protocol_context);
11966       }
11967       ast_free(r2links[i]);
11968    }
11969    ast_free(r2links);
11970    r2links = NULL;
11971    r2links_count = 0;
11972 }
11973 
11974 #define R2_LINK_CAPACITY 10
11975 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11976 {
11977    struct dahdi_mfcr2 *new_r2link = NULL;
11978    struct dahdi_mfcr2 **new_r2links = NULL;
11979    /* this function is called just when starting up and no monitor threads have been launched,
11980       no need to lock monitored_count member */
11981    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11982       new_r2link = ast_calloc(1, sizeof(**r2links));
11983       if (!new_r2link) {
11984          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11985          return NULL;
11986       }
11987       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11988       if (!new_r2links) {
11989          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11990          ast_free(new_r2link);
11991          return NULL;
11992       }
11993       r2links = new_r2links;
11994       new_r2link->r2master = AST_PTHREADT_NULL;
11995       r2links[r2links_count] = new_r2link;
11996       r2links_count++;
11997       ast_log(LOG_DEBUG, "Created new R2 link!\n");
11998    }
11999    return r2links[r2links_count - 1];
12000 }
12001 
12002 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12003 {
12004    char tmplogdir[] = "/tmp";
12005    char logdir[OR2_MAX_PATH];
12006    int threshold = 0;
12007    int snres = 0;
12008    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12009          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12010          conf->mfcr2.max_dnis);
12011    if (!r2_link->protocol_context) {
12012       return -1;
12013    }
12014    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12015    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12016 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12017    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12018 #endif
12019    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12020    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12021    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12022    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12023    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12024    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12025       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12026          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12027       }
12028    } else {
12029       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12030       if (snres >= sizeof(logdir)) {
12031          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12032          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12033             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12034          }
12035       } else {
12036          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12037             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12038          }
12039       }
12040    }
12041    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12042       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12043          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12044       }
12045    }
12046    r2_link->monitored_count = 0;
12047    return 0;
12048 }
12049 #endif
12050 
12051 /* converts a DAHDI sigtype to signalling as can be configured from
12052  * chan_dahdi.conf.
12053  * While both have basically the same values, this will later be the
12054  * place to add filters and sanity checks
12055  */
12056 static int sigtype_to_signalling(int sigtype)
12057 {
12058    return sigtype;
12059 }
12060 
12061 /*!
12062  * \internal
12063  * \brief Get file name and channel number from (subdir,number)
12064  *
12065  * \param subdir name of the subdirectory under /dev/dahdi/
12066  * \param channel name of device file under /dev/dahdi/<subdir>/
12067  * \param path buffer to put file name in
12068  * \param pathlen maximal length of path
12069  *
12070  * \retval minor number of dahdi channel.
12071  * \retval -errno on error.
12072  */
12073 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12074 {
12075    struct stat stbuf;
12076    int      num;
12077 
12078    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12079    if (stat(path, &stbuf) < 0) {
12080       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12081       return -errno;
12082    }
12083    if (!S_ISCHR(stbuf.st_mode)) {
12084       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12085       return -EINVAL;
12086    }
12087    num = minor(stbuf.st_rdev);
12088    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12089    return num;
12090 
12091 }
12092 
12093 /*!
12094  * \internal
12095  * \brief Initialize/create a channel interface.
12096  *
12097  * \param channel Channel interface number to initialize/create.
12098  * \param conf Configuration parameters to initialize interface with.
12099  * \param reloading What we are doing now:
12100  * 0 - initial module load,
12101  * 1 - module reload,
12102  * 2 - module restart
12103  *
12104  * \retval Interface-pointer initialized/created
12105  * \retval NULL if error
12106  */
12107 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12108 {
12109    /* Make a dahdi_pvt structure for this interface */
12110    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12111    char fn[80];
12112    struct dahdi_bufferinfo bi;
12113 
12114    int res;
12115    int span = 0;
12116    int here = 0;/*!< TRUE if the channel interface already exists. */
12117    int x;
12118    struct analog_pvt *analog_p = NULL;
12119    struct dahdi_params p;
12120 #if defined(HAVE_PRI)
12121    struct dahdi_spaninfo si;
12122    struct sig_pri_chan *pri_chan = NULL;
12123 #endif   /* defined(HAVE_PRI) */
12124 #if defined(HAVE_SS7)
12125    struct sig_ss7_chan *ss7_chan = NULL;
12126 #endif   /* defined(HAVE_SS7) */
12127 
12128    /* Search channel interface list to see if it already exists. */
12129    for (tmp = iflist; tmp; tmp = tmp->next) {
12130       if (!tmp->destroy) {
12131          if (tmp->channel == channel) {
12132             /* The channel interface already exists. */
12133             here = 1;
12134             break;
12135          }
12136          if (tmp->channel > channel) {
12137             /* No way it can be in the sorted list. */
12138             tmp = NULL;
12139             break;
12140          }
12141       }
12142    }
12143 
12144    if (!here && reloading != 1) {
12145       tmp = ast_calloc(1, sizeof(*tmp));
12146       if (!tmp) {
12147          return NULL;
12148       }
12149       tmp->cc_params = ast_cc_config_params_init();
12150       if (!tmp->cc_params) {
12151          ast_free(tmp);
12152          return NULL;
12153       }
12154       ast_mutex_init(&tmp->lock);
12155       ifcount++;
12156       for (x = 0; x < 3; x++)
12157          tmp->subs[x].dfd = -1;
12158       tmp->channel = channel;
12159       tmp->priindication_oob = conf->chan.priindication_oob;
12160    }
12161 
12162    if (tmp) {
12163       int chan_sig = conf->chan.sig;
12164 
12165       /* If there are variables in tmp before it is updated to match the new config, clear them */
12166       if (reloading && tmp->vars) {
12167          ast_variables_destroy(tmp->vars);
12168          tmp->vars = NULL;
12169       }
12170 
12171 
12172       if (!here) {
12173          /* Can only get here if this is a new channel interface being created. */
12174          if ((channel != CHAN_PSEUDO)) {
12175             int count = 0;
12176 
12177             snprintf(fn, sizeof(fn), "%d", channel);
12178             /* Open non-blocking */
12179             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12180             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
12181                usleep(1);
12182                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12183                count++;
12184             }
12185             /* Allocate a DAHDI structure */
12186             if (tmp->subs[SUB_REAL].dfd < 0) {
12187                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
12188                destroy_dahdi_pvt(tmp);
12189                return NULL;
12190             }
12191             memset(&p, 0, sizeof(p));
12192             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12193             if (res < 0) {
12194                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12195                destroy_dahdi_pvt(tmp);
12196                return NULL;
12197             }
12198             if (conf->is_sig_auto)
12199                chan_sig = sigtype_to_signalling(p.sigtype);
12200             if (p.sigtype != (chan_sig & 0x3ffff)) {
12201                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
12202                destroy_dahdi_pvt(tmp);
12203                return NULL;
12204             }
12205             tmp->law_default = p.curlaw;
12206             tmp->law = p.curlaw;
12207             tmp->span = p.spanno;
12208             span = p.spanno - 1;
12209          } else {
12210             chan_sig = 0;
12211          }
12212          tmp->sig = chan_sig;
12213          tmp->outsigmod = conf->chan.outsigmod;
12214 
12215          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12216             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12217             if (!analog_p) {
12218                destroy_dahdi_pvt(tmp);
12219                return NULL;
12220             }
12221             tmp->sig_pvt = analog_p;
12222          }
12223 #if defined(HAVE_SS7)
12224          if (chan_sig == SIG_SS7) {
12225             struct dahdi_ss7 *ss7;
12226             int clear = 0;
12227 
12228             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12229                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12230                destroy_dahdi_pvt(tmp);
12231                return NULL;
12232             }
12233 
12234             ss7 = ss7_resolve_linkset(cur_linkset);
12235             if (!ss7) {
12236                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12237                destroy_dahdi_pvt(tmp);
12238                return NULL;
12239             }
12240             ss7->ss7.span = cur_linkset;
12241             if (cur_cicbeginswith < 0) {
12242                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12243                destroy_dahdi_pvt(tmp);
12244                return NULL;
12245             }
12246             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12247             if (!ss7_chan) {
12248                destroy_dahdi_pvt(tmp);
12249                return NULL;
12250             }
12251             tmp->sig_pvt = ss7_chan;
12252             tmp->ss7 = &ss7->ss7;
12253 
12254             ss7_chan->channel = tmp->channel;
12255             ss7_chan->cic = cur_cicbeginswith++;
12256 
12257             /* DB: Add CIC's DPC information */
12258             ss7_chan->dpc = cur_defaultdpc;
12259 
12260             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12261 
12262             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12263             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12264             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12265             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12266 
12267             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12268             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12269          }
12270 #endif   /* defined(HAVE_SS7) */
12271 #ifdef HAVE_OPENR2
12272          if (chan_sig == SIG_MFCR2) {
12273             struct dahdi_mfcr2 *r2_link;
12274             r2_link = dahdi_r2_get_link();
12275             if (!r2_link) {
12276                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12277                destroy_dahdi_pvt(tmp);
12278                return NULL;
12279             }
12280             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12281                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12282                destroy_dahdi_pvt(tmp);
12283                return NULL;
12284             }
12285             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12286                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12287                destroy_dahdi_pvt(tmp);
12288                return NULL;
12289             }
12290             r2_link->pvts[r2_link->numchans++] = tmp;
12291             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12292                                         tmp->subs[SUB_REAL].dfd,
12293                                         NULL, NULL);
12294             if (!tmp->r2chan) {
12295                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12296                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12297                destroy_dahdi_pvt(tmp);
12298                return NULL;
12299             }
12300             tmp->mfcr2 = r2_link;
12301             if (conf->mfcr2.call_files) {
12302                openr2_chan_enable_call_files(tmp->r2chan);
12303             }
12304             openr2_chan_set_client_data(tmp->r2chan, tmp);
12305             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12306             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12307             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12308             tmp->mfcr2_category = conf->mfcr2.category;
12309             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12310             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12311             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12312             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12313             tmp->mfcr2call = 0;
12314             tmp->mfcr2_dnis_index = 0;
12315             tmp->mfcr2_ani_index = 0;
12316             r2_link->monitored_count++;
12317          }
12318 #endif
12319 #ifdef HAVE_PRI
12320          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12321             int offset;
12322             int matchesdchan;
12323             int x,y;
12324             int myswitchtype = 0;
12325 
12326             offset = 0;
12327             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12328                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12329                destroy_dahdi_pvt(tmp);
12330                return NULL;
12331             }
12332             if (span >= NUM_SPANS) {
12333                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12334                destroy_dahdi_pvt(tmp);
12335                return NULL;
12336             } else {
12337                si.spanno = 0;
12338                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12339                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12340                   destroy_dahdi_pvt(tmp);
12341                   return NULL;
12342                }
12343                /* Store the logical span first based upon the real span */
12344                tmp->logicalspan = pris[span].prilogicalspan;
12345                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12346                if (span < 0) {
12347                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12348                   destroy_dahdi_pvt(tmp);
12349                   return NULL;
12350                }
12351                myswitchtype = conf->pri.pri.switchtype;
12352                /* Make sure this isn't a d-channel */
12353                matchesdchan=0;
12354                for (x = 0; x < NUM_SPANS; x++) {
12355                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12356                      if (pris[x].dchannels[y] == tmp->channel) {
12357                         matchesdchan = 1;
12358                         break;
12359                      }
12360                   }
12361                }
12362                if (!matchesdchan) {
12363                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12364                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12365                      destroy_dahdi_pvt(tmp);
12366                      return NULL;
12367                   }
12368                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12369                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12370                      destroy_dahdi_pvt(tmp);
12371                      return NULL;
12372                   }
12373                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12374                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12375                      destroy_dahdi_pvt(tmp);
12376                      return NULL;
12377                   }
12378                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12379                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12380                      destroy_dahdi_pvt(tmp);
12381                      return NULL;
12382                   }
12383                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12384                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12385                      destroy_dahdi_pvt(tmp);
12386                      return NULL;
12387                   }
12388                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12389                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12390                      destroy_dahdi_pvt(tmp);
12391                      return NULL;
12392                   }
12393                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12394                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12395                      destroy_dahdi_pvt(tmp);
12396                      return NULL;
12397                   }
12398                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12399                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12400                         pris[span].pri.trunkgroup);
12401                      destroy_dahdi_pvt(tmp);
12402                      return NULL;
12403                   }
12404 
12405                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12406                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12407                   if (!pri_chan) {
12408                      destroy_dahdi_pvt(tmp);
12409                      return NULL;
12410                   }
12411                   tmp->sig_pvt = pri_chan;
12412                   tmp->pri = &pris[span].pri;
12413 
12414                   tmp->priexclusive = conf->chan.priexclusive;
12415 
12416                   if (!tmp->pri->cc_params) {
12417                      tmp->pri->cc_params = ast_cc_config_params_init();
12418                      if (!tmp->pri->cc_params) {
12419                         destroy_dahdi_pvt(tmp);
12420                         return NULL;
12421                      }
12422                   }
12423                   ast_cc_copy_config_params(tmp->pri->cc_params,
12424                      conf->chan.cc_params);
12425 
12426                   pris[span].pri.sig = chan_sig;
12427                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12428                   pris[span].pri.switchtype = myswitchtype;
12429                   pris[span].pri.nsf = conf->pri.pri.nsf;
12430                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12431                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12432                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12433                   pris[span].pri.minunused = conf->pri.pri.minunused;
12434                   pris[span].pri.minidle = conf->pri.pri.minidle;
12435                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12436                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12437                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12438 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12439                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12440 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12441 #ifdef HAVE_PRI_INBANDDISCONNECT
12442                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12443 #endif
12444 #if defined(HAVE_PRI_CALL_HOLD)
12445                   pris[span].pri.hold_disconnect_transfer =
12446                      conf->pri.pri.hold_disconnect_transfer;
12447 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12448 #if defined(HAVE_PRI_CCSS)
12449                   pris[span].pri.cc_ptmp_recall_mode =
12450                      conf->pri.pri.cc_ptmp_recall_mode;
12451                   pris[span].pri.cc_qsig_signaling_link_req =
12452                      conf->pri.pri.cc_qsig_signaling_link_req;
12453                   pris[span].pri.cc_qsig_signaling_link_rsp =
12454                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12455 #endif   /* defined(HAVE_PRI_CCSS) */
12456 #if defined(HAVE_PRI_CALL_WAITING)
12457                   pris[span].pri.max_call_waiting_calls =
12458                      conf->pri.pri.max_call_waiting_calls;
12459                   pris[span].pri.allow_call_waiting_calls =
12460                      conf->pri.pri.allow_call_waiting_calls;
12461 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12462                   pris[span].pri.transfer = conf->chan.transfer;
12463                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12464 #if defined(HAVE_PRI_L2_PERSISTENCE)
12465                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12466 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12467 #if defined(HAVE_PRI_AOC_EVENTS)
12468                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12469                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12470 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12471                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12472                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12473                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12474 #if defined(HAVE_PRI_MWI)
12475                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12476                      conf->pri.pri.mwi_mailboxes,
12477                      sizeof(pris[span].pri.mwi_mailboxes));
12478 #endif   /* defined(HAVE_PRI_MWI) */
12479                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12480                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12481                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12482                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12483                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12484                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12485                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12486                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12487 
12488                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12489                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12490                   }
12491 
12492 #if defined(HAVE_PRI_CALL_WAITING)
12493                   /* Channel initial config parameters. */
12494                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12495                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12496                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12497                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12498                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12499                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12500                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12501                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12502                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12503                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12504 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12505                } else {
12506                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12507                   destroy_dahdi_pvt(tmp);
12508                   return NULL;
12509                }
12510             }
12511          }
12512 #endif
12513       } else {
12514          /* already exists in interface list */
12515          ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
12516          chan_sig = tmp->sig;
12517          if (tmp->subs[SUB_REAL].dfd > -1) {
12518             memset(&p, 0, sizeof(p));
12519             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12520          }
12521       }
12522       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12523       switch (chan_sig) {
12524       case SIG_FXSKS:
12525       case SIG_FXSLS:
12526       case SIG_EM:
12527       case SIG_EM_E1:
12528       case SIG_EMWINK:
12529       case SIG_FEATD:
12530       case SIG_FEATDMF:
12531       case SIG_FEATDMF_TA:
12532       case SIG_FEATB:
12533       case SIG_E911:
12534       case SIG_SF:
12535       case SIG_SFWINK:
12536       case SIG_FGC_CAMA:
12537       case SIG_FGC_CAMAMF:
12538       case SIG_SF_FEATD:
12539       case SIG_SF_FEATDMF:
12540       case SIG_SF_FEATB:
12541          p.starttime = 250;
12542          break;
12543       }
12544 
12545       if (tmp->radio) {
12546          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12547          p.channo = channel;
12548          p.rxwinktime = 1;
12549          p.rxflashtime = 1;
12550          p.starttime = 1;
12551          p.debouncetime = 5;
12552       } else {
12553          p.channo = channel;
12554          /* Override timing settings based on config file */
12555          if (conf->timing.prewinktime >= 0)
12556             p.prewinktime = conf->timing.prewinktime;
12557          if (conf->timing.preflashtime >= 0)
12558             p.preflashtime = conf->timing.preflashtime;
12559          if (conf->timing.winktime >= 0)
12560             p.winktime = conf->timing.winktime;
12561          if (conf->timing.flashtime >= 0)
12562             p.flashtime = conf->timing.flashtime;
12563          if (conf->timing.starttime >= 0)
12564             p.starttime = conf->timing.starttime;
12565          if (conf->timing.rxwinktime >= 0)
12566             p.rxwinktime = conf->timing.rxwinktime;
12567          if (conf->timing.rxflashtime >= 0)
12568             p.rxflashtime = conf->timing.rxflashtime;
12569          if (conf->timing.debouncetime >= 0)
12570             p.debouncetime = conf->timing.debouncetime;
12571       }
12572 
12573       /* don't set parms on a pseudo-channel */
12574       if (tmp->subs[SUB_REAL].dfd >= 0)
12575       {
12576          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12577          if (res < 0) {
12578             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12579             destroy_dahdi_pvt(tmp);
12580             return NULL;
12581          }
12582       }
12583 #if 1
12584       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12585          memset(&bi, 0, sizeof(bi));
12586          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12587          if (!res) {
12588             bi.txbufpolicy = conf->chan.buf_policy;
12589             bi.rxbufpolicy = conf->chan.buf_policy;
12590             bi.numbufs = conf->chan.buf_no;
12591             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12592             if (res < 0) {
12593                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12594             }
12595          } else {
12596             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12597          }
12598          tmp->buf_policy = conf->chan.buf_policy;
12599          tmp->buf_no = conf->chan.buf_no;
12600          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12601          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12602          tmp->faxbuf_no = conf->chan.faxbuf_no;
12603          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12604           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12605           * The reason the ioctl call above failed should to be determined before worrying about the
12606           * faxbuffer-related ioctl calls */
12607          tmp->bufsize = bi.bufsize;
12608       }
12609 #endif
12610       tmp->immediate = conf->chan.immediate;
12611       tmp->transfertobusy = conf->chan.transfertobusy;
12612       if (chan_sig & __DAHDI_SIG_FXS) {
12613          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12614          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12615          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12616       }
12617       tmp->ringt_base = ringt_base;
12618       tmp->firstradio = 0;
12619       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12620          tmp->permcallwaiting = conf->chan.callwaiting;
12621       else
12622          tmp->permcallwaiting = 0;
12623       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12624       tmp->destroy = 0;
12625       tmp->drings = conf->chan.drings;
12626 
12627       /* 10 is a nice default. */
12628       if (tmp->drings.ringnum[0].range == 0)
12629          tmp->drings.ringnum[0].range = 10;
12630       if (tmp->drings.ringnum[1].range == 0)
12631          tmp->drings.ringnum[1].range = 10;
12632       if (tmp->drings.ringnum[2].range == 0)
12633          tmp->drings.ringnum[2].range = 10;
12634 
12635       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12636       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12637       tmp->threewaycalling = conf->chan.threewaycalling;
12638       tmp->adsi = conf->chan.adsi;
12639       tmp->use_smdi = conf->chan.use_smdi;
12640       tmp->permhidecallerid = conf->chan.hidecallerid;
12641       tmp->hidecalleridname = conf->chan.hidecalleridname;
12642       tmp->callreturn = conf->chan.callreturn;
12643       tmp->echocancel = conf->chan.echocancel;
12644       tmp->echotraining = conf->chan.echotraining;
12645       tmp->pulse = conf->chan.pulse;
12646       if (tmp->echocancel.head.tap_length) {
12647          tmp->echocanbridged = conf->chan.echocanbridged;
12648       } else {
12649          if (conf->chan.echocanbridged)
12650             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12651          tmp->echocanbridged = 0;
12652       }
12653       tmp->busydetect = conf->chan.busydetect;
12654       tmp->busycount = conf->chan.busycount;
12655       tmp->busy_tonelength = conf->chan.busy_tonelength;
12656       tmp->busy_quietlength = conf->chan.busy_quietlength;
12657       tmp->callprogress = conf->chan.callprogress;
12658       tmp->waitfordialtone = conf->chan.waitfordialtone;
12659       tmp->cancallforward = conf->chan.cancallforward;
12660       tmp->dtmfrelax = conf->chan.dtmfrelax;
12661       tmp->callwaiting = tmp->permcallwaiting;
12662       tmp->hidecallerid = tmp->permhidecallerid;
12663       tmp->channel = channel;
12664       tmp->stripmsd = conf->chan.stripmsd;
12665       tmp->use_callerid = conf->chan.use_callerid;
12666       tmp->cid_signalling = conf->chan.cid_signalling;
12667       tmp->cid_start = conf->chan.cid_start;
12668       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12669       tmp->restrictcid = conf->chan.restrictcid;
12670       tmp->use_callingpres = conf->chan.use_callingpres;
12671       if (tmp->usedistinctiveringdetection) {
12672          if (!tmp->use_callerid) {
12673             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12674             tmp->use_callerid = 1;
12675          }
12676       }
12677 
12678       if (tmp->cid_signalling == CID_SIG_SMDI) {
12679          if (!tmp->use_smdi) {
12680             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12681             tmp->use_smdi = 1;
12682          }
12683       }
12684       if (tmp->use_smdi) {
12685          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12686          if (!(tmp->smdi_iface)) {
12687             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12688             tmp->use_smdi = 0;
12689          }
12690       }
12691 
12692       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12693       tmp->amaflags = conf->chan.amaflags;
12694       if (!here) {
12695          tmp->confno = -1;
12696          tmp->propconfno = -1;
12697       }
12698       tmp->canpark = conf->chan.canpark;
12699       tmp->transfer = conf->chan.transfer;
12700       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12701       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12702       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12703       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12704       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12705       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12706       tmp->cid_ton = 0;
12707       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12708          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12709          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12710       } else {
12711          tmp->cid_num[0] = '\0';
12712          tmp->cid_name[0] = '\0';
12713       }
12714 #if defined(HAVE_PRI)
12715       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12716          tmp->cid_tag[0] = '\0';
12717       } else
12718 #endif   /* defined(HAVE_PRI) */
12719       {
12720          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12721       }
12722       tmp->cid_subaddr[0] = '\0';
12723       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12724       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12725          char *mailbox, *context;
12726          mailbox = context = ast_strdupa(tmp->mailbox);
12727          strsep(&context, "@");
12728          if (ast_strlen_zero(context))
12729             context = "default";
12730          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12731             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12732             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12733             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12734             AST_EVENT_IE_END);
12735       }
12736 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12737       tmp->mwisend_setting = conf->chan.mwisend_setting;
12738       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12739       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12740 #endif
12741 
12742       tmp->group = conf->chan.group;
12743       tmp->callgroup = conf->chan.callgroup;
12744       tmp->pickupgroup= conf->chan.pickupgroup;
12745       if (conf->chan.vars) {
12746          struct ast_variable *v, *tmpvar;
12747                    for (v = conf->chan.vars ; v ; v = v->next) {
12748                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12749                                   tmpvar->next = tmp->vars;
12750                                    tmp->vars = tmpvar;
12751                            }
12752                   }
12753       }
12754       tmp->cid_rxgain = conf->chan.cid_rxgain;
12755       tmp->rxgain = conf->chan.rxgain;
12756       tmp->txgain = conf->chan.txgain;
12757       tmp->txdrc = conf->chan.txdrc;
12758       tmp->rxdrc = conf->chan.rxdrc;
12759       tmp->tonezone = conf->chan.tonezone;
12760       if (tmp->subs[SUB_REAL].dfd > -1) {
12761          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12762          if (tmp->dsp)
12763             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12764          update_conf(tmp);
12765          if (!here) {
12766             switch (chan_sig) {
12767             case SIG_PRI_LIB_HANDLE_CASES:
12768             case SIG_SS7:
12769             case SIG_MFCR2:
12770                break;
12771             default:
12772                /* Hang it up to be sure it's good */
12773                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12774                break;
12775             }
12776          }
12777          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12778 #ifdef HAVE_PRI
12779          memset(&si, 0, sizeof(si));
12780          if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12781             ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12782             destroy_dahdi_pvt(tmp);
12783             return NULL;
12784          }
12785 #endif
12786          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12787             /* the dchannel is down so put the channel in alarm */
12788             switch (tmp->sig) {
12789 #ifdef HAVE_PRI
12790             case SIG_PRI_LIB_HANDLE_CASES:
12791                sig_pri_set_alarm(tmp->sig_pvt, !si.alarms);
12792                break;
12793 #endif
12794 #if defined(HAVE_SS7)
12795             case SIG_SS7:
12796                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12797                break;
12798 #endif   /* defined(HAVE_SS7) */
12799             default:
12800                /* The only sig submodule left should be sig_analog. */
12801                analog_p = tmp->sig_pvt;
12802                if (analog_p) {
12803                   analog_p->inalarm = 1;
12804                }
12805                tmp->inalarm = 1;
12806                break;
12807             }
12808             handle_alarms(tmp, res);
12809          }
12810       }
12811 
12812       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12813       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12814       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12815       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12816       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12817 
12818       if (!here) {
12819          tmp->locallyblocked = 0;
12820          tmp->remotelyblocked = 0;
12821          switch (tmp->sig) {
12822 #if defined(HAVE_PRI)
12823          case SIG_PRI_LIB_HANDLE_CASES:
12824             tmp->inservice = 1;/* Inservice until actually implemented. */
12825 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12826             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12827             if (chan_sig == SIG_PRI) {
12828                char db_chan_name[20];
12829                char db_answer[5];
12830 
12831                /*
12832                 * Initialize the active out-of-service status
12833                 * and delete any record if the feature is not enabled.
12834                 */
12835                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12836                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12837                   unsigned *why;
12838 
12839                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12840                   if (tmp->pri->enable_service_message_support) {
12841                      char state;
12842 
12843                      sscanf(db_answer, "%1c:%30u", &state, why);
12844 
12845                      /* Ensure that only the implemented bits could be set.*/
12846                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12847                   }
12848                   if (!*why) {
12849                      ast_db_del(db_chan_name, SRVST_DBKEY);
12850                   }
12851                }
12852             }
12853 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12854             break;
12855 #endif   /* defined(HAVE_PRI) */
12856 #if defined(HAVE_SS7)
12857          case SIG_SS7:
12858             tmp->inservice = 0;
12859             break;
12860 #endif   /* defined(HAVE_SS7) */
12861          default:
12862              /* We default to in service on protocols that don't have a reset */
12863             tmp->inservice = 1;
12864             break;
12865          }
12866       }
12867 
12868       switch (tmp->sig) {
12869 #if defined(HAVE_PRI)
12870       case SIG_PRI_LIB_HANDLE_CASES:
12871          if (pri_chan) {
12872             pri_chan->channel = tmp->channel;
12873             pri_chan->hidecallerid = tmp->hidecallerid;
12874             pri_chan->hidecalleridname = tmp->hidecalleridname;
12875             pri_chan->immediate = tmp->immediate;
12876             pri_chan->inalarm = tmp->inalarm;
12877             pri_chan->priexclusive = tmp->priexclusive;
12878             pri_chan->priindication_oob = tmp->priindication_oob;
12879             pri_chan->use_callerid = tmp->use_callerid;
12880             pri_chan->use_callingpres = tmp->use_callingpres;
12881             ast_copy_string(pri_chan->context, tmp->context,
12882                sizeof(pri_chan->context));
12883             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12884                sizeof(pri_chan->mohinterpret));
12885             pri_chan->stripmsd = tmp->stripmsd;
12886          }
12887          break;
12888 #endif   /* defined(HAVE_PRI) */
12889 #if defined(HAVE_SS7)
12890       case SIG_SS7:
12891          if (ss7_chan) {
12892             ss7_chan->inalarm = tmp->inalarm;
12893 
12894             ss7_chan->stripmsd = tmp->stripmsd;
12895             ss7_chan->hidecallerid = tmp->hidecallerid;
12896             ss7_chan->use_callerid = tmp->use_callerid;
12897             ss7_chan->use_callingpres = tmp->use_callingpres;
12898             ss7_chan->immediate = tmp->immediate;
12899             ss7_chan->locallyblocked = tmp->locallyblocked;
12900             ss7_chan->remotelyblocked = tmp->remotelyblocked;
12901             ast_copy_string(ss7_chan->context, tmp->context,
12902                sizeof(ss7_chan->context));
12903             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12904                sizeof(ss7_chan->mohinterpret));
12905          }
12906          break;
12907 #endif   /* defined(HAVE_SS7) */
12908       default:
12909          /* The only sig submodule left should be sig_analog. */
12910          analog_p = tmp->sig_pvt;
12911          if (analog_p) {
12912             analog_p->channel = tmp->channel;
12913             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12914             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12915             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12916             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12917             analog_p->callreturn = conf->chan.callreturn;
12918             analog_p->cancallforward = conf->chan.cancallforward;
12919             analog_p->canpark = conf->chan.canpark;
12920             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12921             analog_p->immediate = conf->chan.immediate;
12922             analog_p->permhidecallerid = conf->chan.permhidecallerid;
12923             analog_p->pulse = conf->chan.pulse;
12924             analog_p->threewaycalling = conf->chan.threewaycalling;
12925             analog_p->transfer = conf->chan.transfer;
12926             analog_p->transfertobusy = conf->chan.transfertobusy;
12927             analog_p->use_callerid = tmp->use_callerid;
12928             analog_p->use_smdi = tmp->use_smdi;
12929             analog_p->smdi_iface = tmp->smdi_iface;
12930             analog_p->outsigmod = ANALOG_SIG_NONE;
12931             analog_p->echotraining = conf->chan.echotraining;
12932             analog_p->cid_signalling = conf->chan.cid_signalling;
12933             analog_p->stripmsd = conf->chan.stripmsd;
12934             switch (conf->chan.cid_start) {
12935             case CID_START_POLARITY:
12936                analog_p->cid_start = ANALOG_CID_START_POLARITY;
12937                break;
12938             case CID_START_POLARITY_IN:
12939                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12940                break;
12941             case CID_START_DTMF_NOALERT:
12942                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12943                break;
12944             default:
12945                analog_p->cid_start = ANALOG_CID_START_RING;
12946                break;
12947             }
12948             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12949             analog_p->ringt = conf->chan.ringt;
12950             analog_p->ringt_base = ringt_base;
12951             analog_p->chan_tech = &dahdi_tech;
12952             analog_p->onhooktime = time(NULL);
12953             if (chan_sig & __DAHDI_SIG_FXO) {
12954                memset(&p, 0, sizeof(p));
12955                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12956                if (!res) {
12957                   analog_p->fxsoffhookstate = p.rxisoffhook;
12958                }
12959 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12960                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12961 #endif
12962             }
12963             analog_p->msgstate = -1;
12964 
12965             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12966             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12967             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12968 
12969             analog_config_complete(analog_p);
12970          }
12971          break;
12972       }
12973 #if defined(HAVE_PRI)
12974       if (tmp->channel == CHAN_PSEUDO) {
12975          /*
12976           * Save off pseudo channel buffer policy values for dynamic creation of
12977           * no B channel interfaces.
12978           */
12979          dahdi_pseudo_parms.buf_no = tmp->buf_no;
12980          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12981          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12982          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12983       }
12984 #endif   /* defined(HAVE_PRI) */
12985    }
12986    if (tmp && !here) {
12987       /* Add the new channel interface to the sorted channel interface list. */
12988       dahdi_iflist_insert(tmp);
12989    }
12990    return tmp;
12991 }
12992 
12993 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12994 {
12995 #if defined(HAVE_PRI)
12996    if (0 < span) {
12997       /* The channel must be on the specified PRI span. */
12998       if (!p->pri || p->pri->span != span) {
12999          return 0;
13000       }
13001       if (!groupmatch && channelmatch == -1) {
13002          /* Match any group since it only needs to be on the PRI span. */
13003          *groupmatched = 1;
13004          return 1;
13005       }
13006    }
13007 #endif   /* defined(HAVE_PRI) */
13008    /* check group matching */
13009    if (groupmatch) {
13010       if ((p->group & groupmatch) != groupmatch)
13011          /* Doesn't match the specified group, try the next one */
13012          return 0;
13013       *groupmatched = 1;
13014    }
13015    /* Check to see if we have a channel match */
13016    if (channelmatch != -1) {
13017       if (p->channel != channelmatch)
13018          /* Doesn't match the specified channel, try the next one */
13019          return 0;
13020       *channelmatched = 1;
13021    }
13022 
13023    return 1;
13024 }
13025 
13026 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13027 {
13028    struct dahdi_pvt *p = *pvt;
13029 
13030    if (p->inalarm)
13031       return 0;
13032 
13033    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13034       return analog_available(p->sig_pvt);
13035 
13036    switch (p->sig) {
13037 #if defined(HAVE_PRI)
13038    case SIG_PRI_LIB_HANDLE_CASES:
13039       {
13040          struct sig_pri_chan *pvt_chan;
13041          int res;
13042 
13043          pvt_chan = p->sig_pvt;
13044          res = sig_pri_available(&pvt_chan, is_specific_channel);
13045          *pvt = pvt_chan->chan_pvt;
13046          return res;
13047       }
13048 #endif   /* defined(HAVE_PRI) */
13049 #if defined(HAVE_SS7)
13050    case SIG_SS7:
13051       return sig_ss7_available(p->sig_pvt);
13052 #endif   /* defined(HAVE_SS7) */
13053    default:
13054       break;
13055    }
13056 
13057    if (p->locallyblocked || p->remotelyblocked) {
13058       return 0;
13059    }
13060 
13061    /* If no owner definitely available */
13062    if (!p->owner) {
13063 #ifdef HAVE_OPENR2
13064       /* Trust MFC/R2 */
13065       if (p->mfcr2) {
13066          if (p->mfcr2call) {
13067             return 0;
13068          } else {
13069             return 1;
13070          }
13071       }
13072 #endif
13073       return 1;
13074    }
13075 
13076    return 0;
13077 }
13078 
13079 #if defined(HAVE_PRI)
13080 #if defined(HAVE_PRI_CALL_WAITING)
13081 /*!
13082  * \internal
13083  * \brief Init the private channel configuration using the span controller.
13084  * \since 1.8
13085  *
13086  * \param priv Channel to init the configuration.
13087  * \param pri sig_pri PRI control structure.
13088  *
13089  * \note Assumes the pri->lock is already obtained.
13090  *
13091  * \return Nothing
13092  */
13093 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13094 {
13095    struct dahdi_pvt *pvt = priv;
13096 
13097    pvt->stripmsd = pri->ch_cfg.stripmsd;
13098    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13099    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13100    pvt->immediate = pri->ch_cfg.immediate;
13101    pvt->priexclusive = pri->ch_cfg.priexclusive;
13102    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13103    pvt->use_callerid = pri->ch_cfg.use_callerid;
13104    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13105    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13106    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13107 }
13108 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13109 #endif   /* defined(HAVE_PRI) */
13110 
13111 #if defined(HAVE_PRI)
13112 /*!
13113  * \internal
13114  * \brief Create a no B channel interface.
13115  * \since 1.8
13116  *
13117  * \param pri sig_pri span controller to add interface.
13118  *
13119  * \note Assumes the pri->lock is already obtained.
13120  *
13121  * \retval array-index into private pointer array on success.
13122  * \retval -1 on error.
13123  */
13124 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13125 {
13126    int pvt_idx;
13127    int res;
13128    unsigned idx;
13129    struct dahdi_pvt *pvt;
13130    struct sig_pri_chan *chan;
13131    struct dahdi_bufferinfo bi;
13132 
13133    static int nobch_channel = CHAN_PSEUDO;
13134 
13135    /* Find spot in the private pointer array for new interface. */
13136    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13137       if (!pri->pvts[pvt_idx]) {
13138          break;
13139       }
13140    }
13141    if (pri->numchans == pvt_idx) {
13142       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13143          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13144          return -1;
13145       }
13146 
13147       /* Add new spot to the private pointer array. */
13148       pri->pvts[pvt_idx] = NULL;
13149       ++pri->numchans;
13150    }
13151 
13152    pvt = ast_calloc(1, sizeof(*pvt));
13153    if (!pvt) {
13154       return -1;
13155    }
13156    pvt->cc_params = ast_cc_config_params_init();
13157    if (!pvt->cc_params) {
13158       ast_free(pvt);
13159       return -1;
13160    }
13161    ast_mutex_init(&pvt->lock);
13162    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13163       pvt->subs[idx].dfd = -1;
13164    }
13165    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13166    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13167    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13168    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13169 
13170    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13171    if (!chan) {
13172       destroy_dahdi_pvt(pvt);
13173       return -1;
13174    }
13175    chan->no_b_channel = 1;
13176 
13177    /*
13178     * Pseudo channel companding law.
13179     * Needed for outgoing call waiting calls.
13180     * XXX May need to make this determined by switchtype or user option.
13181     */
13182    pvt->law_default = DAHDI_LAW_ALAW;
13183 
13184    pvt->sig = pri->sig;
13185    pvt->outsigmod = -1;
13186    pvt->pri = pri;
13187    pvt->sig_pvt = chan;
13188    pri->pvts[pvt_idx] = chan;
13189 
13190    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13191    if (pvt->subs[SUB_REAL].dfd < 0) {
13192       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13193          strerror(errno));
13194       destroy_dahdi_pvt(pvt);
13195       return -1;
13196    }
13197    memset(&bi, 0, sizeof(bi));
13198    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13199    if (!res) {
13200       pvt->bufsize = bi.bufsize;
13201       bi.txbufpolicy = pvt->buf_policy;
13202       bi.rxbufpolicy = pvt->buf_policy;
13203       bi.numbufs = pvt->buf_no;
13204       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13205       if (res < 0) {
13206          ast_log(LOG_WARNING,
13207             "Unable to set buffer policy on no B channel interface: %s\n",
13208             strerror(errno));
13209       }
13210    } else
13211       ast_log(LOG_WARNING,
13212          "Unable to check buffer policy on no B channel interface: %s\n",
13213          strerror(errno));
13214 
13215    --nobch_channel;
13216    if (CHAN_PSEUDO < nobch_channel) {
13217       nobch_channel = CHAN_PSEUDO - 1;
13218    }
13219    pvt->channel = nobch_channel;
13220    pvt->span = pri->span;
13221    chan->channel = pvt->channel;
13222 
13223    dahdi_nobch_insert(pri, pvt);
13224 
13225    return pvt_idx;
13226 }
13227 #endif   /* defined(HAVE_PRI) */
13228 
13229 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13230    structures; it makes no attempt to safely copy regular channel private
13231    structures that might contain reference-counted object pointers and other
13232    scary bits
13233 */
13234 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13235 {
13236    struct dahdi_pvt *p;
13237    struct dahdi_bufferinfo bi;
13238    int res;
13239 
13240    p = ast_malloc(sizeof(*p));
13241    if (!p) {
13242       return NULL;
13243    }
13244    *p = *src;
13245 
13246    /* Must deep copy the cc_params. */
13247    p->cc_params = ast_cc_config_params_init();
13248    if (!p->cc_params) {
13249       ast_free(p);
13250       return NULL;
13251    }
13252    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13253 
13254    p->which_iflist = DAHDI_IFLIST_NONE;
13255    p->next = NULL;
13256    p->prev = NULL;
13257    ast_mutex_init(&p->lock);
13258    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13259    if (p->subs[SUB_REAL].dfd < 0) {
13260       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13261       destroy_dahdi_pvt(p);
13262       return NULL;
13263    }
13264    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13265    if (!res) {
13266       bi.txbufpolicy = src->buf_policy;
13267       bi.rxbufpolicy = src->buf_policy;
13268       bi.numbufs = src->buf_no;
13269       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13270       if (res < 0) {
13271          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13272       }
13273    } else
13274       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13275    p->destroy = 1;
13276    dahdi_iflist_insert(p);
13277    return p;
13278 }
13279 
13280 struct dahdi_starting_point {
13281    /*! Group matching mask.  Zero if not specified. */
13282    ast_group_t groupmatch;
13283    /*! DAHDI channel to match with.  -1 if not specified. */
13284    int channelmatch;
13285    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13286    int rr_starting_point;
13287    /*! ISDN span where channels can be picked (Zero if not specified) */
13288    int span;
13289    /*! Analog channel distinctive ring cadance index. */
13290    int cadance;
13291    /*! Dialing option. c/r/d if present and valid. */
13292    char opt;
13293    /*! TRUE if to search the channel list backwards. */
13294    char backwards;
13295    /*! TRUE if search is done with round robin sequence. */
13296    char roundrobin;
13297 };
13298 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13299 {
13300    char *dest;
13301    char *s;
13302    int x;
13303    int res = 0;
13304    struct dahdi_pvt *p;
13305    char *subdir = NULL;
13306    AST_DECLARE_APP_ARGS(args,
13307       AST_APP_ARG(group);  /* channel/group token */
13308       //AST_APP_ARG(ext);  /* extension token */
13309       //AST_APP_ARG(opts); /* options token */
13310       AST_APP_ARG(other);  /* Any remining unused arguments */
13311    );
13312 
13313    /*
13314     * data is ---v
13315     * Dial(DAHDI/pseudo[/extension[/options]])
13316     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13317     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13318     * Dial(DAHDI/i<span>[/extension[/options]])
13319     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13320     *
13321     * i - ISDN span channel restriction.
13322     *     Used by CC to ensure that the CC recall goes out the same span.
13323     *     Also to make ISDN channel names dialable when the sequence number
13324     *     is stripped off.  (Used by DTMF attended transfer feature.)
13325     *
13326     * g - channel group allocation search forward
13327     * G - channel group allocation search backward
13328     * r - channel group allocation round robin search forward
13329     * R - channel group allocation round robin search backward
13330     *
13331     * c - Wait for DTMF digit to confirm answer
13332     * r<cadance#> - Set distintive ring cadance number
13333     * d - Force bearer capability for ISDN/SS7 call to digital.
13334     */
13335 
13336    if (data) {
13337       dest = ast_strdupa(data);
13338    } else {
13339       ast_log(LOG_WARNING, "Channel requested with no data\n");
13340       return NULL;
13341    }
13342    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13343    if (!args.argc || ast_strlen_zero(args.group)) {
13344       ast_log(LOG_WARNING, "No channel/group specified\n");
13345       return NULL;
13346    }
13347 
13348    /* Initialize the output parameters */
13349    memset(param, 0, sizeof(*param));
13350    param->channelmatch = -1;
13351 
13352    if (strchr(args.group, '!') != NULL) {
13353       char *prev = args.group;
13354       while ((s = strchr(prev, '!')) != NULL) {
13355          *s++ = '/';
13356          prev = s;
13357       }
13358       *(prev - 1) = '\0';
13359       subdir = args.group;
13360       args.group = prev;
13361    } else if (args.group[0] == 'i') {
13362       /* Extract the ISDN span channel restriction specifier. */
13363       res = sscanf(args.group + 1, "%30d", &x);
13364       if (res < 1) {
13365          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13366          return NULL;
13367       }
13368       param->span = x;
13369 
13370       /* Remove the ISDN span channel restriction specifier. */
13371       s = strchr(args.group, '-');
13372       if (!s) {
13373          /* Search all groups since we are ISDN span restricted. */
13374          return iflist;
13375       }
13376       args.group = s + 1;
13377       res = 0;
13378    }
13379    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13380       /* Retrieve the group number */
13381       s = args.group + 1;
13382       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13383       if (res < 1) {
13384          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13385          return NULL;
13386       }
13387       param->groupmatch = ((ast_group_t) 1 << x);
13388 
13389       if (toupper(args.group[0]) == 'G') {
13390          if (args.group[0] == 'G') {
13391             param->backwards = 1;
13392             p = ifend;
13393          } else
13394             p = iflist;
13395       } else {
13396          if (ARRAY_LEN(round_robin) <= x) {
13397             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13398                x, data);
13399             return NULL;
13400          }
13401          if (args.group[0] == 'R') {
13402             param->backwards = 1;
13403             p = round_robin[x] ? round_robin[x]->prev : ifend;
13404             if (!p)
13405                p = ifend;
13406          } else {
13407             p = round_robin[x] ? round_robin[x]->next : iflist;
13408             if (!p)
13409                p = iflist;
13410          }
13411          param->roundrobin = 1;
13412          param->rr_starting_point = x;
13413       }
13414    } else {
13415       s = args.group;
13416       if (!strcasecmp(s, "pseudo")) {
13417          /* Special case for pseudo */
13418          x = CHAN_PSEUDO;
13419          param->channelmatch = x;
13420       } else {
13421          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13422          if (res < 1) {
13423             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13424             return NULL;
13425          } else {
13426             param->channelmatch = x;
13427          }
13428       }
13429       if (subdir) {
13430          char path[PATH_MAX];
13431          struct stat stbuf;
13432 
13433          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13434                subdir, param->channelmatch);
13435          if (stat(path, &stbuf) < 0) {
13436             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13437                   path, strerror(errno));
13438             return NULL;
13439          }
13440          if (!S_ISCHR(stbuf.st_mode)) {
13441             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13442                   path);
13443             return NULL;
13444          }
13445          param->channelmatch = minor(stbuf.st_rdev);
13446       }
13447 
13448       p = iflist;
13449    }
13450 
13451    if (param->opt == 'r' && res < 3) {
13452       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13453       param->opt = '\0';
13454    }
13455 
13456    return p;
13457 }
13458 
13459 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13460 {
13461    int callwait = 0;
13462    struct dahdi_pvt *p;
13463    struct ast_channel *tmp = NULL;
13464    struct dahdi_pvt *exitpvt;
13465    int channelmatched = 0;
13466    int groupmatched = 0;
13467    int transcapdigital = 0;
13468    struct dahdi_starting_point start;
13469 
13470    ast_mutex_lock(&iflock);
13471    p = determine_starting_point(data, &start);
13472    if (!p) {
13473       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13474       ast_mutex_unlock(&iflock);
13475       return NULL;
13476    }
13477 
13478    /* Search for an unowned channel */
13479    exitpvt = p;
13480    while (p && !tmp) {
13481       if (start.roundrobin)
13482          round_robin[start.rr_starting_point] = p;
13483 
13484       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13485          && available(&p, channelmatched)) {
13486          ast_debug(1, "Using channel %d\n", p->channel);
13487 
13488          callwait = (p->owner != NULL);
13489 #ifdef HAVE_OPENR2
13490          if (p->mfcr2) {
13491             ast_mutex_lock(&p->lock);
13492             if (p->mfcr2call) {
13493                ast_mutex_unlock(&p->lock);
13494                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13495                goto next;
13496             }
13497             p->mfcr2call = 1;
13498             ast_mutex_unlock(&p->lock);
13499          }
13500 #endif
13501          if (p->channel == CHAN_PSEUDO) {
13502             p = duplicate_pseudo(p);
13503             if (!p) {
13504                break;
13505             }
13506          }
13507 
13508          p->distinctivering = 0;
13509          /* Make special notes */
13510          switch (start.opt) {
13511          case '\0':
13512             /* No option present. */
13513             break;
13514          case 'c':
13515             /* Confirm answer */
13516             p->confirmanswer = 1;
13517             break;
13518          case 'r':
13519             /* Distinctive ring */
13520             p->distinctivering = start.cadance;
13521             break;
13522          case 'd':
13523             /* If this is an ISDN call, make it digital */
13524             transcapdigital = AST_TRANS_CAP_DIGITAL;
13525             break;
13526          default:
13527             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13528             break;
13529          }
13530 
13531          p->outgoing = 1;
13532          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13533             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13534 #ifdef HAVE_PRI
13535          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13536             /*
13537              * We already have the B channel reserved for this call.  We
13538              * just need to make sure that dahdi_hangup() has completed
13539              * cleaning up before continuing.
13540              */
13541             ast_mutex_lock(&p->lock);
13542             ast_mutex_unlock(&p->lock);
13543 
13544             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13545                sizeof(p->dnid));
13546             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13547 #endif
13548 #if defined(HAVE_SS7)
13549          } else if (p->sig == SIG_SS7) {
13550             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13551 #endif   /* defined(HAVE_SS7) */
13552          } else {
13553             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13554          }
13555          if (!tmp) {
13556             p->outgoing = 0;
13557 #if defined(HAVE_PRI)
13558             switch (p->sig) {
13559             case SIG_PRI_LIB_HANDLE_CASES:
13560 #if defined(HAVE_PRI_CALL_WAITING)
13561                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13562                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13563                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13564                }
13565 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13566                /*
13567                 * This should be the last thing to clear when we are done with
13568                 * the channel.
13569                 */
13570                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13571                break;
13572             default:
13573                break;
13574             }
13575 #endif   /* defined(HAVE_PRI) */
13576          } else {
13577             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13578          }
13579          break;
13580       }
13581 #ifdef HAVE_OPENR2
13582 next:
13583 #endif
13584       if (start.backwards) {
13585          p = p->prev;
13586          if (!p)
13587             p = ifend;
13588       } else {
13589          p = p->next;
13590          if (!p)
13591             p = iflist;
13592       }
13593       /* stop when you roll to the one that we started from */
13594       if (p == exitpvt)
13595          break;
13596    }
13597    ast_mutex_unlock(&iflock);
13598    restart_monitor();
13599    if (cause && !tmp) {
13600       if (callwait || channelmatched) {
13601          *cause = AST_CAUSE_BUSY;
13602       } else if (groupmatched) {
13603          *cause = AST_CAUSE_CONGESTION;
13604       } else {
13605          /*
13606           * We did not match any channel requested.
13607           * Dialplan error requesting non-existant channel?
13608           */
13609       }
13610    }
13611 
13612    return tmp;
13613 }
13614 
13615 /*!
13616  * \internal
13617  * \brief Determine the device state for a given DAHDI device if we can.
13618  * \since 1.8
13619  *
13620  * \param data DAHDI device name after "DAHDI/".
13621  *
13622  * \retval device_state enum ast_device_state value.
13623  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13624  */
13625 static int dahdi_devicestate(void *data)
13626 {
13627 #if defined(HAVE_PRI)
13628    char *device;
13629    unsigned span;
13630    int res;
13631 
13632    device = data;
13633 
13634    if (*device != 'I') {
13635       /* The request is not for an ISDN span device. */
13636       return AST_DEVICE_UNKNOWN;
13637    }
13638    res = sscanf(device, "I%30u", &span);
13639    if (res != 1 || !span || NUM_SPANS < span) {
13640       /* Bad format for ISDN span device name. */
13641       return AST_DEVICE_UNKNOWN;
13642    }
13643    device = strchr(device, '/');
13644    if (!device) {
13645       /* Bad format for ISDN span device name. */
13646       return AST_DEVICE_UNKNOWN;
13647    }
13648 
13649    /*
13650     * Since there are currently no other span devstate's defined,
13651     * it must be congestion.
13652     */
13653 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13654    ++device;
13655    if (!strcmp(device, "congestion"))
13656 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13657    {
13658       return pris[span - 1].pri.congestion_devstate;
13659    }
13660 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13661    else if (!strcmp(device, "threshold")) {
13662       return pris[span - 1].pri.threshold_devstate;
13663    }
13664    return AST_DEVICE_UNKNOWN;
13665 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13666 #else
13667    return AST_DEVICE_UNKNOWN;
13668 #endif   /* defined(HAVE_PRI) */
13669 }
13670 
13671 /*!
13672  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13673  * \since 1.8
13674  *
13675  * \param inbound Incoming asterisk channel.
13676  * \param dest Same dial string passed to dahdi_request().
13677  * \param callback Callback into CC core to announce a busy channel available for CC.
13678  *
13679  * \details
13680  * This callback acts like a forked dial with all prongs of the fork busy.
13681  * Essentially, for each channel that could have taken the call, indicate that
13682  * it is busy.
13683  *
13684  * \retval 0 on success.
13685  * \retval -1 on error.
13686  */
13687 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13688 {
13689    struct dahdi_pvt *p;
13690    struct dahdi_pvt *exitpvt;
13691    struct dahdi_starting_point start;
13692    int groupmatched = 0;
13693    int channelmatched = 0;
13694 
13695    ast_mutex_lock(&iflock);
13696    p = determine_starting_point(dest, &start);
13697    if (!p) {
13698       ast_mutex_unlock(&iflock);
13699       return -1;
13700    }
13701    exitpvt = p;
13702    for (;;) {
13703       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13704          /* We found a potential match. call the callback */
13705          struct ast_str *device_name;
13706          char *dash;
13707          const char *monitor_type;
13708          char dialstring[AST_CHANNEL_NAME];
13709          char full_device_name[AST_CHANNEL_NAME];
13710 
13711          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13712          case AST_CC_MONITOR_NEVER:
13713             break;
13714          case AST_CC_MONITOR_NATIVE:
13715          case AST_CC_MONITOR_ALWAYS:
13716          case AST_CC_MONITOR_GENERIC:
13717 #if defined(HAVE_PRI)
13718             if (dahdi_sig_pri_lib_handles(p->sig)) {
13719                /*
13720                 * ISDN is in a trunk busy condition so we need to monitor
13721                 * the span congestion device state.
13722                 */
13723                snprintf(full_device_name, sizeof(full_device_name),
13724                   "DAHDI/I%d/congestion", p->pri->span);
13725             } else
13726 #endif   /* defined(HAVE_PRI) */
13727             {
13728 #if defined(HAVE_PRI)
13729                device_name = create_channel_name(p, 1, "");
13730 #else
13731                device_name = create_channel_name(p);
13732 #endif   /* defined(HAVE_PRI) */
13733                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13734                   device_name ? ast_str_buffer(device_name) : "");
13735                ast_free(device_name);
13736                /*
13737                 * The portion after the '-' in the channel name is either a random
13738                 * number, a sequence number, or a subchannel number. None are
13739                 * necessary so strip them off.
13740                 */
13741                dash = strrchr(full_device_name, '-');
13742                if (dash) {
13743                   *dash = '\0';
13744                }
13745             }
13746             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13747 
13748             /*
13749              * Analog can only do generic monitoring.
13750              * ISDN is in a trunk busy condition and any "device" is going
13751              * to be busy until a B channel becomes available.  The generic
13752              * monitor can do this task.
13753              */
13754             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13755             callback(inbound,
13756 #if defined(HAVE_PRI)
13757                p->pri ? p->pri->cc_params : p->cc_params,
13758 #else
13759                p->cc_params,
13760 #endif   /* defined(HAVE_PRI) */
13761                monitor_type, full_device_name, dialstring, NULL);
13762             break;
13763          }
13764       }
13765       p = start.backwards ? p->prev : p->next;
13766       if (!p) {
13767          p = start.backwards ? ifend : iflist;
13768       }
13769       if (p == exitpvt) {
13770          break;
13771       }
13772    }
13773    ast_mutex_unlock(&iflock);
13774    return 0;
13775 }
13776 
13777 #if defined(HAVE_SS7)
13778 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13779 {
13780    int i;
13781 
13782    if (ss7) {
13783       for (i = 0; i < NUM_SPANS; i++) {
13784          if (linksets[i].ss7.ss7 == ss7) {
13785             ast_verbose("[%d] %s", i + 1, s);
13786             return;
13787          }
13788       }
13789    }
13790    ast_verbose("%s", s);
13791 }
13792 #endif   /* defined(HAVE_SS7) */
13793 
13794 #if defined(HAVE_SS7)
13795 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13796 {
13797    int i;
13798 
13799    if (ss7) {
13800       for (i = 0; i < NUM_SPANS; i++) {
13801          if (linksets[i].ss7.ss7 == ss7) {
13802             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13803             return;
13804          }
13805       }
13806    }
13807    ast_log(LOG_ERROR, "%s", s);
13808 }
13809 #endif   /* defined(HAVE_SS7) */
13810 
13811 #if defined(HAVE_OPENR2)
13812 static void *mfcr2_monitor(void *data)
13813 {
13814    struct dahdi_mfcr2 *mfcr2 = data;
13815    /* we should be using pthread_key_create
13816       and allocate pollers dynamically.
13817       I think do_monitor() could be leaking, since it
13818       could be cancelled at any time and is not
13819       using thread keys, why?, */
13820    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13821    int res = 0;
13822    int i = 0;
13823    int oldstate = 0;
13824    int quit_loop = 0;
13825    int maxsleep = 20;
13826    int was_idle = 0;
13827    int pollsize = 0;
13828    /* now that we're ready to get calls, unblock our side and
13829       get current line state */
13830    for (i = 0; i < mfcr2->numchans; i++) {
13831       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13832       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13833    }
13834    while (1) {
13835       /* we trust here that the mfcr2 channel list will not ever change once
13836          the module is loaded */
13837       pollsize = 0;
13838       for (i = 0; i < mfcr2->numchans; i++) {
13839          pollers[i].revents = 0;
13840          pollers[i].events = 0;
13841          if (mfcr2->pvts[i]->owner) {
13842             continue;
13843          }
13844          if (!mfcr2->pvts[i]->r2chan) {
13845             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13846             quit_loop = 1;
13847             break;
13848          }
13849          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13850          pollers[i].events = POLLIN | POLLPRI;
13851          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13852          pollsize++;
13853       }
13854       if (quit_loop) {
13855          break;
13856       }
13857       if (pollsize == 0) {
13858          if (!was_idle) {
13859             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13860             was_idle = 1;
13861          }
13862          poll(NULL, 0, maxsleep);
13863          continue;
13864       }
13865       was_idle = 0;
13866       /* probably poll() is a valid cancel point, lets just be on the safe side
13867          by calling pthread_testcancel */
13868       pthread_testcancel();
13869       res = poll(pollers, mfcr2->numchans, maxsleep);
13870       pthread_testcancel();
13871       if ((res < 0) && (errno != EINTR)) {
13872          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13873          break;
13874       }
13875       /* do we want to allow to cancel while processing events? */
13876       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13877       for (i = 0; i < mfcr2->numchans; i++) {
13878          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13879             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13880          }
13881       }
13882       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13883    }
13884    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13885    return 0;
13886 }
13887 #endif /* HAVE_OPENR2 */
13888 
13889 #if defined(HAVE_PRI)
13890 #ifndef PRI_RESTART
13891 #error "Upgrade your libpri"
13892 #endif
13893 static void dahdi_pri_message(struct pri *pri, char *s)
13894 {
13895    int x;
13896    int y;
13897    int dchan = -1;
13898    int span = -1;
13899    int dchancount = 0;
13900 
13901    if (pri) {
13902       for (x = 0; x < NUM_SPANS; x++) {
13903          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13904             if (pris[x].pri.dchans[y]) {
13905                dchancount++;
13906             }
13907 
13908             if (pris[x].pri.dchans[y] == pri) {
13909                dchan = y;
13910             }
13911          }
13912          if (dchan >= 0) {
13913             span = x;
13914             break;
13915          }
13916          dchancount = 0;
13917       }
13918       if (-1 < span) {
13919          if (1 < dchancount) {
13920             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13921          } else {
13922             ast_verbose("PRI Span: %d %s", span + 1, s);
13923          }
13924       } else {
13925          ast_verbose("PRI Span: ? %s", s);
13926       }
13927    } else {
13928       ast_verbose("PRI Span: ? %s", s);
13929    }
13930 
13931    ast_mutex_lock(&pridebugfdlock);
13932 
13933    if (pridebugfd >= 0) {
13934       if (write(pridebugfd, s, strlen(s)) < 0) {
13935          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13936       }
13937    }
13938 
13939    ast_mutex_unlock(&pridebugfdlock);
13940 }
13941 #endif   /* defined(HAVE_PRI) */
13942 
13943 #if defined(HAVE_PRI)
13944 static void dahdi_pri_error(struct pri *pri, char *s)
13945 {
13946    int x;
13947    int y;
13948    int dchan = -1;
13949    int span = -1;
13950    int dchancount = 0;
13951 
13952    if (pri) {
13953       for (x = 0; x < NUM_SPANS; x++) {
13954          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13955             if (pris[x].pri.dchans[y]) {
13956                dchancount++;
13957             }
13958 
13959             if (pris[x].pri.dchans[y] == pri) {
13960                dchan = y;
13961             }
13962          }
13963          if (dchan >= 0) {
13964             span = x;
13965             break;
13966          }
13967          dchancount = 0;
13968       }
13969       if (-1 < span) {
13970          if (1 < dchancount) {
13971             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13972          } else {
13973             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
13974          }
13975       } else {
13976          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
13977       }
13978    } else {
13979       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
13980    }
13981 
13982    ast_mutex_lock(&pridebugfdlock);
13983 
13984    if (pridebugfd >= 0) {
13985       if (write(pridebugfd, s, strlen(s)) < 0) {
13986          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13987       }
13988    }
13989 
13990    ast_mutex_unlock(&pridebugfdlock);
13991 }
13992 #endif   /* defined(HAVE_PRI) */
13993 
13994 #if defined(HAVE_PRI)
13995 static int prepare_pri(struct dahdi_pri *pri)
13996 {
13997    int i, res, x;
13998    struct dahdi_params p;
13999    struct dahdi_bufferinfo bi;
14000    struct dahdi_spaninfo si;
14001 
14002    pri->pri.calls = &dahdi_pri_callbacks;
14003 
14004    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14005       if (!pri->dchannels[i])
14006          break;
14007       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14008       x = pri->dchannels[i];
14009       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14010          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14011          return -1;
14012       }
14013       memset(&p, 0, sizeof(p));
14014       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14015       if (res) {
14016          dahdi_close_pri_fd(pri, i);
14017          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14018          return -1;
14019       }
14020       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14021          dahdi_close_pri_fd(pri, i);
14022          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14023          return -1;
14024       }
14025       memset(&si, 0, sizeof(si));
14026       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14027       if (res) {
14028          dahdi_close_pri_fd(pri, i);
14029          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14030       }
14031       if (!si.alarms) {
14032          pri_event_noalarm(&pri->pri, i, 1);
14033       } else {
14034          pri_event_alarm(&pri->pri, i, 1);
14035       }
14036       memset(&bi, 0, sizeof(bi));
14037       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14038       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14039       bi.numbufs = 32;
14040       bi.bufsize = 1024;
14041       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14042          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14043          dahdi_close_pri_fd(pri, i);
14044          return -1;
14045       }
14046       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14047    }
14048    return 0;
14049 }
14050 #endif   /* defined(HAVE_PRI) */
14051 
14052 #if defined(HAVE_PRI)
14053 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14054 {
14055    int which, span;
14056    char *ret = NULL;
14057 
14058    if (pos != rpos)
14059       return ret;
14060 
14061    for (which = span = 0; span < NUM_SPANS; span++) {
14062       if (pris[span].pri.pri && ++which > state) {
14063          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14064             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14065          }
14066          break;
14067       }
14068    }
14069    return ret;
14070 }
14071 #endif   /* defined(HAVE_PRI) */
14072 
14073 #if defined(HAVE_PRI)
14074 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14075 {
14076    return complete_span_helper(line,word,pos,state,3);
14077 }
14078 #endif   /* defined(HAVE_PRI) */
14079 
14080 #if defined(HAVE_PRI)
14081 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14082 {
14083    int myfd;
14084    switch (cmd) {
14085    case CLI_INIT:
14086       e->command = "pri set debug file";
14087       e->usage = "Usage: pri set debug file [output-file]\n"
14088          "       Sends PRI debug output to the specified output file\n";
14089       return NULL;
14090    case CLI_GENERATE:
14091       return NULL;
14092    }
14093    if (a->argc < 5)
14094       return CLI_SHOWUSAGE;
14095 
14096    if (ast_strlen_zero(a->argv[4]))
14097       return CLI_SHOWUSAGE;
14098 
14099    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14100    if (myfd < 0) {
14101       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14102       return CLI_SUCCESS;
14103    }
14104 
14105    ast_mutex_lock(&pridebugfdlock);
14106 
14107    if (pridebugfd >= 0)
14108       close(pridebugfd);
14109 
14110    pridebugfd = myfd;
14111    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14112    ast_mutex_unlock(&pridebugfdlock);
14113    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14114    return CLI_SUCCESS;
14115 }
14116 #endif   /* defined(HAVE_PRI) */
14117 
14118 #if defined(HAVE_PRI)
14119 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14120 {
14121    int span;
14122    int x;
14123    int level = 0;
14124    switch (cmd) {
14125    case CLI_INIT:
14126       e->command = "pri set debug {on|off|0|1|2} span";
14127       e->usage =
14128          "Usage: pri set debug {<level>|on|off} span <span>\n"
14129          "       Enables debugging on a given PRI span\n";
14130       return NULL;
14131    case CLI_GENERATE:
14132       return complete_span_4(a->line, a->word, a->pos, a->n);
14133    }
14134    if (a->argc < 6) {
14135       return CLI_SHOWUSAGE;
14136    }
14137 
14138    if (!strcasecmp(a->argv[3], "on")) {
14139       level = 1;
14140    } else if (!strcasecmp(a->argv[3], "off")) {
14141       level = 0;
14142    } else {
14143       level = atoi(a->argv[3]);
14144    }
14145    span = atoi(a->argv[5]);
14146    if ((span < 1) || (span > NUM_SPANS)) {
14147       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14148       return CLI_SUCCESS;
14149    }
14150    if (!pris[span-1].pri.pri) {
14151       ast_cli(a->fd, "No PRI running on span %d\n", span);
14152       return CLI_SUCCESS;
14153    }
14154 
14155    /* Set debug level in libpri */
14156    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14157       if (pris[span - 1].pri.dchans[x]) {
14158          switch (level) {
14159          case 0:
14160             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14161             break;
14162          case 1:
14163             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14164             break;
14165          default:
14166             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14167             break;
14168          }
14169       }
14170    }
14171    if (level == 0) {
14172       /* Close the debugging file if it's set */
14173       ast_mutex_lock(&pridebugfdlock);
14174       if (0 <= pridebugfd) {
14175          close(pridebugfd);
14176          pridebugfd = -1;
14177          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14178             pridebugfilename);
14179       }
14180       ast_mutex_unlock(&pridebugfdlock);
14181    }
14182    pris[span - 1].pri.debug = (level) ? 1 : 0;
14183    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14184    return CLI_SUCCESS;
14185 }
14186 #endif   /* defined(HAVE_PRI) */
14187 
14188 #if defined(HAVE_PRI)
14189 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14190 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14191 {
14192    unsigned *why;
14193    int channel;
14194    int trunkgroup;
14195    int x, y, fd = a->fd;
14196    int interfaceid = 0;
14197    char *c;
14198    char db_chan_name[20], db_answer[5];
14199    struct dahdi_pvt *tmp;
14200    struct dahdi_pri *pri;
14201 
14202    if (a->argc < 5 || a->argc > 6)
14203       return CLI_SHOWUSAGE;
14204    if ((c = strchr(a->argv[4], ':'))) {
14205       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14206          return CLI_SHOWUSAGE;
14207       if ((trunkgroup < 1) || (channel < 1))
14208          return CLI_SHOWUSAGE;
14209       pri = NULL;
14210       for (x=0;x<NUM_SPANS;x++) {
14211          if (pris[x].pri.trunkgroup == trunkgroup) {
14212             pri = pris + x;
14213             break;
14214          }
14215       }
14216       if (!pri) {
14217          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14218          return CLI_FAILURE;
14219       }
14220    } else
14221       channel = atoi(a->argv[4]);
14222 
14223    if (a->argc == 6)
14224       interfaceid = atoi(a->argv[5]);
14225 
14226    /* either servicing a D-Channel */
14227    for (x = 0; x < NUM_SPANS; x++) {
14228       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14229          if (pris[x].dchannels[y] == channel) {
14230             pri = pris + x;
14231             if (pri->pri.enable_service_message_support) {
14232                ast_mutex_lock(&pri->pri.lock);
14233                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14234                ast_mutex_unlock(&pri->pri.lock);
14235             } else {
14236                ast_cli(fd,
14237                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14238                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14239             }
14240             return CLI_SUCCESS;
14241          }
14242       }
14243    }
14244 
14245    /* or servicing a B-Channel */
14246    ast_mutex_lock(&iflock);
14247    for (tmp = iflist; tmp; tmp = tmp->next) {
14248       if (tmp->pri && tmp->channel == channel) {
14249          ast_mutex_unlock(&iflock);
14250          ast_mutex_lock(&tmp->pri->lock);
14251          if (!tmp->pri->enable_service_message_support) {
14252             ast_mutex_unlock(&tmp->pri->lock);
14253             ast_cli(fd,
14254                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14255                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14256             return CLI_SUCCESS;
14257          }
14258          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14259          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14260          switch(changestatus) {
14261          case 0: /* enable */
14262             /* Near end wants to be in service now. */
14263             ast_db_del(db_chan_name, SRVST_DBKEY);
14264             *why &= ~SRVST_NEAREND;
14265             if (*why) {
14266                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14267                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14268             } else {
14269                dahdi_pri_update_span_devstate(tmp->pri);
14270             }
14271             break;
14272          /* case 1:  -- loop */
14273          case 2: /* disable */
14274             /* Near end wants to be out-of-service now. */
14275             ast_db_del(db_chan_name, SRVST_DBKEY);
14276             *why |= SRVST_NEAREND;
14277             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14278             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14279             dahdi_pri_update_span_devstate(tmp->pri);
14280             break;
14281          /* case 3:  -- continuity */
14282          /* case 4:  -- shutdown */
14283          default:
14284             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14285             break;
14286          }
14287          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14288          ast_mutex_unlock(&tmp->pri->lock);
14289          return CLI_SUCCESS;
14290       }
14291    }
14292    ast_mutex_unlock(&iflock);
14293 
14294    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14295    return CLI_FAILURE;
14296 }
14297 
14298 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14299 {
14300    switch (cmd) {
14301    case CLI_INIT:
14302       e->command = "pri service enable channel";
14303       e->usage =
14304          "Usage: pri service enable channel <channel> [<interface id>]\n"
14305          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14306          "  to restore a channel to service, with optional interface id\n"
14307          "  as agreed upon with remote switch operator\n";
14308       return NULL;
14309    case CLI_GENERATE:
14310       return NULL;
14311    }
14312    return handle_pri_service_generic(e, cmd, a, 0);
14313 }
14314 
14315 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14316 {
14317    switch (cmd) {
14318    case CLI_INIT:
14319       e->command = "pri service disable channel";
14320       e->usage =
14321          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14322          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14323          "  to remove a channel from service, with optional interface id\n"
14324          "  as agreed upon with remote switch operator\n";
14325       return NULL;
14326    case CLI_GENERATE:
14327       return NULL;
14328    }
14329    return handle_pri_service_generic(e, cmd, a, 2);
14330 }
14331 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14332 #endif   /* defined(HAVE_PRI) */
14333 
14334 #if defined(HAVE_PRI)
14335 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14336 {
14337    int span;
14338 
14339    switch (cmd) {
14340    case CLI_INIT:
14341       e->command = "pri show channels";
14342       e->usage =
14343          "Usage: pri show channels\n"
14344          "       Displays PRI channel information such as the current mapping\n"
14345          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14346          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14347          "       are not associated with any B channel.\n";
14348       return NULL;
14349    case CLI_GENERATE:
14350       return NULL;
14351    }
14352 
14353    if (a->argc != 3)
14354       return CLI_SHOWUSAGE;
14355 
14356    sig_pri_cli_show_channels_header(a->fd);
14357    for (span = 0; span < NUM_SPANS; ++span) {
14358       if (pris[span].pri.pri) {
14359          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14360       }
14361    }
14362    return CLI_SUCCESS;
14363 }
14364 #endif   /* defined(HAVE_PRI) */
14365 
14366 #if defined(HAVE_PRI)
14367 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14368 {
14369    int span;
14370 
14371    switch (cmd) {
14372    case CLI_INIT:
14373       e->command = "pri show spans";
14374       e->usage =
14375          "Usage: pri show spans\n"
14376          "       Displays PRI span information\n";
14377       return NULL;
14378    case CLI_GENERATE:
14379       return NULL;
14380    }
14381 
14382    if (a->argc != 3)
14383       return CLI_SHOWUSAGE;
14384 
14385    for (span = 0; span < NUM_SPANS; span++) {
14386       if (pris[span].pri.pri) {
14387          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14388       }
14389    }
14390    return CLI_SUCCESS;
14391 }
14392 #endif   /* defined(HAVE_PRI) */
14393 
14394 #if defined(HAVE_PRI)
14395 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14396 {
14397    int span;
14398 
14399    switch (cmd) {
14400    case CLI_INIT:
14401       e->command = "pri show span";
14402       e->usage =
14403          "Usage: pri show span <span>\n"
14404          "       Displays PRI Information on a given PRI span\n";
14405       return NULL;
14406    case CLI_GENERATE:
14407       return complete_span_4(a->line, a->word, a->pos, a->n);
14408    }
14409 
14410    if (a->argc < 4)
14411       return CLI_SHOWUSAGE;
14412    span = atoi(a->argv[3]);
14413    if ((span < 1) || (span > NUM_SPANS)) {
14414       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14415       return CLI_SUCCESS;
14416    }
14417    if (!pris[span-1].pri.pri) {
14418       ast_cli(a->fd, "No PRI running on span %d\n", span);
14419       return CLI_SUCCESS;
14420    }
14421 
14422    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14423 
14424    return CLI_SUCCESS;
14425 }
14426 #endif   /* defined(HAVE_PRI) */
14427 
14428 #if defined(HAVE_PRI)
14429 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14430 {
14431    int x;
14432    int span;
14433    int count=0;
14434    int debug;
14435 
14436    switch (cmd) {
14437    case CLI_INIT:
14438       e->command = "pri show debug";
14439       e->usage =
14440          "Usage: pri show debug\n"
14441          "  Show the debug state of pri spans\n";
14442       return NULL;
14443    case CLI_GENERATE:
14444       return NULL;
14445    }
14446 
14447    for (span = 0; span < NUM_SPANS; span++) {
14448       if (pris[span].pri.pri) {
14449          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14450             if (pris[span].pri.dchans[x]) {
14451                debug = pri_get_debug(pris[span].pri.dchans[x]);
14452                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
14453                count++;
14454             }
14455          }
14456       }
14457 
14458    }
14459    ast_mutex_lock(&pridebugfdlock);
14460    if (pridebugfd >= 0)
14461       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14462    ast_mutex_unlock(&pridebugfdlock);
14463 
14464    if (!count)
14465       ast_cli(a->fd, "No PRI running\n");
14466    return CLI_SUCCESS;
14467 }
14468 #endif   /* defined(HAVE_PRI) */
14469 
14470 #if defined(HAVE_PRI)
14471 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14472 {
14473    switch (cmd) {
14474    case CLI_INIT:
14475       e->command = "pri show version";
14476       e->usage =
14477          "Usage: pri show version\n"
14478          "Show libpri version information\n";
14479       return NULL;
14480    case CLI_GENERATE:
14481       return NULL;
14482    }
14483 
14484    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14485 
14486    return CLI_SUCCESS;
14487 }
14488 #endif   /* defined(HAVE_PRI) */
14489 
14490 #if defined(HAVE_PRI)
14491 static struct ast_cli_entry dahdi_pri_cli[] = {
14492    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14493 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14494    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14495    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14496 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14497    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14498    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14499    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14500    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14501    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14502    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14503 };
14504 #endif   /* defined(HAVE_PRI) */
14505 
14506 #ifdef HAVE_OPENR2
14507 
14508 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14509 {
14510    switch (cmd) {
14511    case CLI_INIT:
14512       e->command = "mfcr2 show version";
14513       e->usage =
14514          "Usage: mfcr2 show version\n"
14515          "       Shows the version of the OpenR2 library being used.\n";
14516       return NULL;
14517    case CLI_GENERATE:
14518       return NULL;
14519    }
14520    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14521    return CLI_SUCCESS;
14522 }
14523 
14524 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14525 {
14526 #define FORMAT "%4s %40s\n"
14527    int i = 0;
14528    int numvariants = 0;
14529    const openr2_variant_entry_t *variants;
14530    switch (cmd) {
14531    case CLI_INIT:
14532       e->command = "mfcr2 show variants";
14533       e->usage =
14534          "Usage: mfcr2 show variants\n"
14535          "       Shows the list of MFC/R2 variants supported.\n";
14536       return NULL;
14537    case CLI_GENERATE:
14538       return NULL;
14539    }
14540    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14541       ast_cli(a->fd, "Failed to get list of variants.\n");
14542       return CLI_FAILURE;
14543    }
14544    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14545    for (i = 0; i < numvariants; i++) {
14546       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14547    }
14548    return CLI_SUCCESS;
14549 #undef FORMAT
14550 }
14551 
14552 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14553 {
14554 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14555    int filtertype = 0;
14556    int targetnum = 0;
14557    char channo[5];
14558    char anino[5];
14559    char dnisno[5];
14560    struct dahdi_pvt *p;
14561    openr2_context_t *r2context;
14562    openr2_variant_t r2variant;
14563    switch (cmd) {
14564    case CLI_INIT:
14565       e->command = "mfcr2 show channels [group|context]";
14566       e->usage =
14567          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14568          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14569       return NULL;
14570    case CLI_GENERATE:
14571       return NULL;
14572    }
14573    if (!((a->argc == 3) || (a->argc == 5))) {
14574       return CLI_SHOWUSAGE;
14575    }
14576    if (a->argc == 5) {
14577       if (!strcasecmp(a->argv[3], "group")) {
14578          targetnum = atoi(a->argv[4]);
14579          if ((targetnum < 0) || (targetnum > 63))
14580             return CLI_SHOWUSAGE;
14581          targetnum = 1 << targetnum;
14582          filtertype = 1;
14583       } else if (!strcasecmp(a->argv[3], "context")) {
14584          filtertype = 2;
14585       } else {
14586          return CLI_SHOWUSAGE;
14587       }
14588    }
14589    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14590    ast_mutex_lock(&iflock);
14591    for (p = iflist; p; p = p->next) {
14592       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14593          continue;
14594       }
14595       if (filtertype) {
14596          switch(filtertype) {
14597          case 1: /* mfcr2 show channels group <group> */
14598             if (p->group != targetnum) {
14599                continue;
14600             }
14601             break;
14602          case 2: /* mfcr2 show channels context <context> */
14603             if (strcasecmp(p->context, a->argv[4])) {
14604                continue;
14605             }
14606             break;
14607          default:
14608             ;
14609          }
14610       }
14611       r2context = openr2_chan_get_context(p->r2chan);
14612       r2variant = openr2_context_get_variant(r2context);
14613       snprintf(channo, sizeof(channo), "%d", p->channel);
14614       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14615       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14616       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14617             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14618             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14619             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14620    }
14621    ast_mutex_unlock(&iflock);
14622    return CLI_SUCCESS;
14623 #undef FORMAT
14624 }
14625 
14626 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14627 {
14628    struct dahdi_pvt *p = NULL;
14629    int channo = 0;
14630    char *toklevel = NULL;
14631    char *saveptr = NULL;
14632    char *logval = NULL;
14633    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14634    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14635    switch (cmd) {
14636    case CLI_INIT:
14637       e->command = "mfcr2 set debug";
14638       e->usage =
14639          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14640          "       Set a new logging level for the specified channel.\n"
14641          "       If no channel is specified the logging level will be applied to all channels.\n";
14642       return NULL;
14643    case CLI_GENERATE:
14644       return NULL;
14645    }
14646    if (a->argc < 4) {
14647       return CLI_SHOWUSAGE;
14648    }
14649    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14650    logval = ast_strdupa(a->argv[3]);
14651    toklevel = strtok_r(logval, ",", &saveptr);
14652    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14653       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14654       return CLI_FAILURE;
14655    } else if (OR2_LOG_NOTHING == tmplevel) {
14656       loglevel = tmplevel;
14657    } else {
14658       loglevel |= tmplevel;
14659       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14660          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14661             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14662             continue;
14663          }
14664          loglevel |= tmplevel;
14665       }
14666    }
14667    ast_mutex_lock(&iflock);
14668    for (p = iflist; p; p = p->next) {
14669       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14670          continue;
14671       }
14672       if ((channo != -1) && (p->channel != channo )) {
14673          continue;
14674       }
14675       openr2_chan_set_log_level(p->r2chan, loglevel);
14676       if (channo != -1) {
14677          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14678          break;
14679       }
14680    }
14681    if ((channo != -1) && !p) {
14682       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14683    }
14684    if (channo == -1) {
14685       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14686    }
14687    ast_mutex_unlock(&iflock);
14688    return CLI_SUCCESS;
14689 }
14690 
14691 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14692 {
14693    struct dahdi_pvt *p = NULL;
14694    int channo = 0;
14695    switch (cmd) {
14696    case CLI_INIT:
14697       e->command = "mfcr2 call files [on|off]";
14698       e->usage =
14699          "Usage: mfcr2 call files [on|off] <channel>\n"
14700          "       Enable call files creation on the specified channel.\n"
14701          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14702       return NULL;
14703    case CLI_GENERATE:
14704       return NULL;
14705    }
14706    if (a->argc < 4) {
14707       return CLI_SHOWUSAGE;
14708    }
14709    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14710    ast_mutex_lock(&iflock);
14711    for (p = iflist; p; p = p->next) {
14712       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14713          continue;
14714       }
14715       if ((channo != -1) && (p->channel != channo )) {
14716          continue;
14717       }
14718       if (ast_true(a->argv[3])) {
14719          openr2_chan_enable_call_files(p->r2chan);
14720       } else {
14721          openr2_chan_disable_call_files(p->r2chan);
14722       }
14723       if (channo != -1) {
14724          if (ast_true(a->argv[3])) {
14725             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14726          } else {
14727             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14728          }
14729          break;
14730       }
14731    }
14732    if ((channo != -1) && !p) {
14733       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14734    }
14735    if (channo == -1) {
14736       if (ast_true(a->argv[3])) {
14737          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14738       } else {
14739          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14740       }
14741    }
14742    ast_mutex_unlock(&iflock);
14743    return CLI_SUCCESS;
14744 }
14745 
14746 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14747 {
14748    struct dahdi_pvt *p = NULL;
14749    int channo = 0;
14750    switch (cmd) {
14751    case CLI_INIT:
14752       e->command = "mfcr2 set idle";
14753       e->usage =
14754          "Usage: mfcr2 set idle <channel>\n"
14755          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14756          "       Force the given channel into IDLE state.\n"
14757          "       If no channel is specified, all channels will be set to IDLE.\n";
14758       return NULL;
14759    case CLI_GENERATE:
14760       return NULL;
14761    }
14762    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14763    ast_mutex_lock(&iflock);
14764    for (p = iflist; p; p = p->next) {
14765       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14766          continue;
14767       }
14768       if ((channo != -1) && (p->channel != channo )) {
14769          continue;
14770       }
14771       openr2_chan_set_idle(p->r2chan);
14772       ast_mutex_lock(&p->lock);
14773       p->locallyblocked = 0;
14774       p->mfcr2call = 0;
14775       ast_mutex_unlock(&p->lock);
14776       if (channo != -1) {
14777          break;
14778       }
14779    }
14780    if ((channo != -1) && !p) {
14781       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14782    }
14783    ast_mutex_unlock(&iflock);
14784    return CLI_SUCCESS;
14785 }
14786 
14787 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14788 {
14789    struct dahdi_pvt *p = NULL;
14790    int channo = 0;
14791    switch (cmd) {
14792    case CLI_INIT:
14793       e->command = "mfcr2 set blocked";
14794       e->usage =
14795          "Usage: mfcr2 set blocked <channel>\n"
14796          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14797          "       Force the given channel into BLOCKED state.\n"
14798          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14799       return NULL;
14800    case CLI_GENERATE:
14801       return NULL;
14802    }
14803    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14804    ast_mutex_lock(&iflock);
14805    for (p = iflist; p; p = p->next) {
14806       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14807          continue;
14808       }
14809       if ((channo != -1) && (p->channel != channo )) {
14810          continue;
14811       }
14812       openr2_chan_set_blocked(p->r2chan);
14813       ast_mutex_lock(&p->lock);
14814       p->locallyblocked = 1;
14815       ast_mutex_unlock(&p->lock);
14816       if (channo != -1) {
14817          break;
14818       }
14819    }
14820    if ((channo != -1) && !p) {
14821       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14822    }
14823    ast_mutex_unlock(&iflock);
14824    return CLI_SUCCESS;
14825 }
14826 
14827 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14828    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14829    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14830    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14831    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14832    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14833    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14834    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14835 };
14836 
14837 #endif /* HAVE_OPENR2 */
14838 
14839 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14840 {
14841    int channel;
14842    int ret;
14843    switch (cmd) {
14844    case CLI_INIT:
14845       e->command = "dahdi destroy channel";
14846       e->usage =
14847          "Usage: dahdi destroy channel <chan num>\n"
14848          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14849       return NULL;
14850    case CLI_GENERATE:
14851       return NULL;
14852    }
14853    if (a->argc != 4)
14854       return CLI_SHOWUSAGE;
14855 
14856    channel = atoi(a->argv[3]);
14857    ret = dahdi_destroy_channel_bynum(channel);
14858    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14859 }
14860 
14861 static void dahdi_softhangup_all(void)
14862 {
14863    struct dahdi_pvt *p;
14864 retry:
14865    ast_mutex_lock(&iflock);
14866    for (p = iflist; p; p = p->next) {
14867       ast_mutex_lock(&p->lock);
14868       if (p->owner && !p->restartpending) {
14869          if (ast_channel_trylock(p->owner)) {
14870             if (option_debug > 2)
14871                ast_verbose("Avoiding deadlock\n");
14872             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14873             ast_mutex_unlock(&p->lock);
14874             ast_mutex_unlock(&iflock);
14875             goto retry;
14876          }
14877          if (option_debug > 2)
14878             ast_verbose("Softhanging up on %s\n", p->owner->name);
14879          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14880          p->restartpending = 1;
14881          num_restart_pending++;
14882          ast_channel_unlock(p->owner);
14883       }
14884       ast_mutex_unlock(&p->lock);
14885    }
14886    ast_mutex_unlock(&iflock);
14887 }
14888 
14889 static int setup_dahdi(int reload);
14890 static int dahdi_restart(void)
14891 {
14892 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14893    int i, j;
14894 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14895    int cancel_code;
14896    struct dahdi_pvt *p;
14897 
14898    ast_mutex_lock(&restart_lock);
14899    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14900    dahdi_softhangup_all();
14901    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14902 #ifdef HAVE_OPENR2
14903    dahdi_r2_destroy_links();
14904 #endif
14905 
14906 #if defined(HAVE_PRI)
14907    for (i = 0; i < NUM_SPANS; i++) {
14908       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14909          cancel_code = pthread_cancel(pris[i].pri.master);
14910          pthread_kill(pris[i].pri.master, SIGURG);
14911          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
14912          pthread_join(pris[i].pri.master, NULL);
14913          ast_debug(4, "Joined thread of span %d\n", i);
14914       }
14915    }
14916 #endif
14917 
14918 #if defined(HAVE_SS7)
14919    for (i = 0; i < NUM_SPANS; i++) {
14920       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14921          cancel_code = pthread_cancel(linksets[i].ss7.master);
14922          pthread_kill(linksets[i].ss7.master, SIGURG);
14923          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
14924          pthread_join(linksets[i].ss7.master, NULL);
14925          ast_debug(4, "Joined thread of span %d\n", i);
14926       }
14927    }
14928 #endif   /* defined(HAVE_SS7) */
14929 
14930    ast_mutex_lock(&monlock);
14931    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14932       cancel_code = pthread_cancel(monitor_thread);
14933       pthread_kill(monitor_thread, SIGURG);
14934       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14935       pthread_join(monitor_thread, NULL);
14936       ast_debug(4, "Joined monitor thread\n");
14937    }
14938    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14939 
14940    ast_mutex_lock(&ss_thread_lock);
14941    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14942       int x = DAHDI_FLASH;
14943       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14944 
14945       ast_mutex_lock(&iflock);
14946       for (p = iflist; p; p = p->next) {
14947          if (p->owner) {
14948             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
14949             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14950          }
14951       }
14952       ast_mutex_unlock(&iflock);
14953       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14954    }
14955 
14956    /* ensure any created channels before monitor threads were stopped are hungup */
14957    dahdi_softhangup_all();
14958    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14959    destroy_all_channels();
14960    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14961 
14962    ast_mutex_unlock(&monlock);
14963 
14964 #ifdef HAVE_PRI
14965    for (i = 0; i < NUM_SPANS; i++) {
14966       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14967          dahdi_close_pri_fd(&(pris[i]), j);
14968    }
14969 
14970    memset(pris, 0, sizeof(pris));
14971    for (i = 0; i < NUM_SPANS; i++) {
14972       sig_pri_init_pri(&pris[i].pri);
14973    }
14974    pri_set_error(dahdi_pri_error);
14975    pri_set_message(dahdi_pri_message);
14976 #endif
14977 #if defined(HAVE_SS7)
14978    for (i = 0; i < NUM_SPANS; i++) {
14979       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14980          dahdi_close_ss7_fd(&(linksets[i]), j);
14981    }
14982 
14983    memset(linksets, 0, sizeof(linksets));
14984    for (i = 0; i < NUM_SPANS; i++) {
14985       sig_ss7_init_linkset(&linksets[i].ss7);
14986    }
14987    ss7_set_error(dahdi_ss7_error);
14988    ss7_set_message(dahdi_ss7_message);
14989 #endif   /* defined(HAVE_SS7) */
14990 
14991    if (setup_dahdi(2) != 0) {
14992       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14993       ast_mutex_unlock(&ss_thread_lock);
14994       return 1;
14995    }
14996    ast_mutex_unlock(&ss_thread_lock);
14997    ast_mutex_unlock(&restart_lock);
14998    return 0;
14999 }
15000 
15001 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15002 {
15003    switch (cmd) {
15004    case CLI_INIT:
15005       e->command = "dahdi restart";
15006       e->usage =
15007          "Usage: dahdi restart\n"
15008          "  Restarts the DAHDI channels: destroys them all and then\n"
15009          "  re-reads them from chan_dahdi.conf.\n"
15010          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15011          "";
15012       return NULL;
15013    case CLI_GENERATE:
15014       return NULL;
15015    }
15016    if (a->argc != 2)
15017       return CLI_SHOWUSAGE;
15018 
15019    if (dahdi_restart() != 0)
15020       return CLI_FAILURE;
15021    return CLI_SUCCESS;
15022 }
15023 
15024 static int action_dahdirestart(struct mansession *s, const struct message *m)
15025 {
15026    if (dahdi_restart() != 0) {
15027       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15028       return 1;
15029    }
15030    astman_send_ack(s, m, "DAHDIRestart: Success");
15031    return 0;
15032 }
15033 
15034 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15035 {
15036 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15037 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15038    unsigned int targetnum = 0;
15039    int filtertype = 0;
15040    struct dahdi_pvt *tmp = NULL;
15041    char tmps[20] = "";
15042    char statestr[20] = "";
15043    char blockstr[20] = "";
15044 
15045    switch (cmd) {
15046    case CLI_INIT:
15047       e->command = "dahdi show channels [group|context]";
15048       e->usage =
15049          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15050          "  Shows a list of available channels with optional filtering\n"
15051          "  <group> must be a number between 0 and 63\n";
15052       return NULL;
15053    case CLI_GENERATE:
15054       return NULL;
15055    }
15056 
15057    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15058 
15059    if (!((a->argc == 3) || (a->argc == 5)))
15060       return CLI_SHOWUSAGE;
15061 
15062    if (a->argc == 5) {
15063       if (!strcasecmp(a->argv[3], "group")) {
15064          targetnum = atoi(a->argv[4]);
15065          if ((targetnum < 0) || (targetnum > 63))
15066             return CLI_SHOWUSAGE;
15067          targetnum = 1 << targetnum;
15068          filtertype = 1;
15069       } else if (!strcasecmp(a->argv[3], "context")) {
15070          filtertype = 2;
15071       }
15072    }
15073 
15074    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15075    ast_mutex_lock(&iflock);
15076    for (tmp = iflist; tmp; tmp = tmp->next) {
15077       if (filtertype) {
15078          switch(filtertype) {
15079          case 1: /* dahdi show channels group <group> */
15080             if (!(tmp->group & targetnum)) {
15081                continue;
15082             }
15083             break;
15084          case 2: /* dahdi show channels context <context> */
15085             if (strcasecmp(tmp->context, a->argv[4])) {
15086                continue;
15087             }
15088             break;
15089          default:
15090             break;
15091          }
15092       }
15093       if (tmp->channel > 0) {
15094          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15095       } else
15096          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15097 
15098       if (tmp->locallyblocked)
15099          blockstr[0] = 'L';
15100       else
15101          blockstr[0] = ' ';
15102 
15103       if (tmp->remotelyblocked)
15104          blockstr[1] = 'R';
15105       else
15106          blockstr[1] = ' ';
15107 
15108       blockstr[2] = '\0';
15109 
15110       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15111 
15112       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15113    }
15114    ast_mutex_unlock(&iflock);
15115    return CLI_SUCCESS;
15116 #undef FORMAT
15117 #undef FORMAT2
15118 }
15119 
15120 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15121 {
15122    int channel;
15123    struct dahdi_pvt *tmp = NULL;
15124    struct dahdi_confinfo ci;
15125    struct dahdi_params ps;
15126    int x;
15127 
15128    switch (cmd) {
15129    case CLI_INIT:
15130       e->command = "dahdi show channel";
15131       e->usage =
15132          "Usage: dahdi show channel <chan num>\n"
15133          "  Detailed information about a given channel\n";
15134       return NULL;
15135    case CLI_GENERATE:
15136       return NULL;
15137    }
15138 
15139    if (a->argc != 4)
15140       return CLI_SHOWUSAGE;
15141 
15142    channel = atoi(a->argv[3]);
15143 
15144    ast_mutex_lock(&iflock);
15145    for (tmp = iflist; tmp; tmp = tmp->next) {
15146       if (tmp->channel == channel) {
15147          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15148          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15149          ast_cli(a->fd, "Span: %d\n", tmp->span);
15150          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15151          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15152          ast_cli(a->fd, "Context: %s\n", tmp->context);
15153          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15154          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15155 #if defined(HAVE_PRI)
15156 #if defined(HAVE_PRI_SUBADDR)
15157          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15158 #endif   /* defined(HAVE_PRI_SUBADDR) */
15159 #endif   /* defined(HAVE_PRI) */
15160          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15161          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15162          if (tmp->vars) {
15163             struct ast_variable *v;
15164             ast_cli(a->fd, "Variables:\n");
15165             for (v = tmp->vars ; v ; v = v->next)
15166                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15167          }
15168          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15169          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15170          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15171          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15172          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15173          ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15174          ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15175          ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15176          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15177          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15178          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15179          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15180          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15181          if (tmp->busydetect) {
15182 #if defined(BUSYDETECT_TONEONLY)
15183             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15184 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15185             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15186 #endif
15187 #ifdef BUSYDETECT_DEBUG
15188             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15189 #endif
15190             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15191             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15192          }
15193          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15194          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15195          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15196          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15197          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15198          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15199          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15200          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15201          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15202          ast_cli(a->fd, "Echo Cancellation:\n");
15203 
15204          if (tmp->echocancel.head.tap_length) {
15205             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15206             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15207                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15208             }
15209             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15210          } else {
15211             ast_cli(a->fd, "\tnone\n");
15212          }
15213          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15214          if (tmp->master)
15215             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15216          for (x = 0; x < MAX_SLAVES; x++) {
15217             if (tmp->slaves[x])
15218                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15219          }
15220 #ifdef HAVE_OPENR2
15221          if (tmp->mfcr2) {
15222             char calldir[OR2_MAX_PATH];
15223             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15224             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15225             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15226             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15227             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15228             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15229             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15230             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15231             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15232             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15233             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15234 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15235             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15236 #endif
15237             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15238             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15239             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15240             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15241             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15242             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15243             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15244             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15245             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15246             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15247             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15248             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15249          }
15250 #endif
15251 #if defined(HAVE_SS7)
15252          if (tmp->ss7) {
15253             struct sig_ss7_chan *chan = tmp->sig_pvt;
15254 
15255             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15256          }
15257 #endif   /* defined(HAVE_SS7) */
15258 #ifdef HAVE_PRI
15259          if (tmp->pri) {
15260             struct sig_pri_chan *chan = tmp->sig_pvt;
15261 
15262             ast_cli(a->fd, "PRI Flags: ");
15263             if (chan->resetting)
15264                ast_cli(a->fd, "Resetting ");
15265             if (chan->call)
15266                ast_cli(a->fd, "Call ");
15267             if (chan->allocated) {
15268                ast_cli(a->fd, "Allocated ");
15269             }
15270             ast_cli(a->fd, "\n");
15271             if (tmp->logicalspan)
15272                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15273             else
15274                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15275          }
15276 #endif
15277          memset(&ci, 0, sizeof(ci));
15278          ps.channo = tmp->channel;
15279          if (tmp->subs[SUB_REAL].dfd > -1) {
15280             memset(&ci, 0, sizeof(ci));
15281             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15282                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15283             }
15284             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15285                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15286             }
15287             memset(&ps, 0, sizeof(ps));
15288             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15289                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15290             } else {
15291                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15292             }
15293          }
15294          ast_mutex_unlock(&iflock);
15295          return CLI_SUCCESS;
15296       }
15297    }
15298    ast_mutex_unlock(&iflock);
15299 
15300    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15301    return CLI_FAILURE;
15302 }
15303 
15304 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15305 {
15306    int i, j;
15307    switch (cmd) {
15308    case CLI_INIT:
15309       e->command = "dahdi show cadences";
15310       e->usage =
15311          "Usage: dahdi show cadences\n"
15312          "       Shows all cadences currently defined\n";
15313       return NULL;
15314    case CLI_GENERATE:
15315       return NULL;
15316    }
15317    for (i = 0; i < num_cadence; i++) {
15318       char output[1024];
15319       char tmp[16], tmp2[64];
15320       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15321       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15322 
15323       for (j = 0; j < 16; j++) {
15324          if (cadences[i].ringcadence[j] == 0)
15325             break;
15326          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15327          if (cidrings[i] * 2 - 1 == j)
15328             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15329          else
15330             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15331          if (j != 0)
15332             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15333          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15334       }
15335       ast_cli(a->fd,"%s\n",output);
15336    }
15337    return CLI_SUCCESS;
15338 }
15339 
15340 /* Based on irqmiss.c */
15341 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15342 {
15343    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15344    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15345    int span;
15346    int res;
15347    char alarmstr[50];
15348 
15349    int ctl;
15350    struct dahdi_spaninfo s;
15351 
15352    switch (cmd) {
15353    case CLI_INIT:
15354       e->command = "dahdi show status";
15355       e->usage =
15356          "Usage: dahdi show status\n"
15357          "       Shows a list of DAHDI cards with status\n";
15358       return NULL;
15359    case CLI_GENERATE:
15360       return NULL;
15361    }
15362    ctl = open("/dev/dahdi/ctl", O_RDWR);
15363    if (ctl < 0) {
15364       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15365       return CLI_FAILURE;
15366    }
15367    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15368 
15369    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15370       s.spanno = span;
15371       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15372       if (res) {
15373          continue;
15374       }
15375       alarmstr[0] = '\0';
15376       if (s.alarms > 0) {
15377          if (s.alarms & DAHDI_ALARM_BLUE)
15378             strcat(alarmstr, "BLU/");
15379          if (s.alarms & DAHDI_ALARM_YELLOW)
15380             strcat(alarmstr, "YEL/");
15381          if (s.alarms & DAHDI_ALARM_RED)
15382             strcat(alarmstr, "RED/");
15383          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15384             strcat(alarmstr, "LB/");
15385          if (s.alarms & DAHDI_ALARM_RECOVER)
15386             strcat(alarmstr, "REC/");
15387          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15388             strcat(alarmstr, "NOP/");
15389          if (!strlen(alarmstr))
15390             strcat(alarmstr, "UUU/");
15391          if (strlen(alarmstr)) {
15392             /* Strip trailing / */
15393             alarmstr[strlen(alarmstr) - 1] = '\0';
15394          }
15395       } else {
15396          if (s.numchans)
15397             strcpy(alarmstr, "OK");
15398          else
15399             strcpy(alarmstr, "UNCONFIGURED");
15400       }
15401 
15402       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15403          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15404          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15405          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15406          "CAS",
15407          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15408          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15409          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15410          "Unk",
15411          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15412             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15413             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15414          lbostr[s.lbo]
15415          );
15416    }
15417    close(ctl);
15418 
15419    return CLI_SUCCESS;
15420 #undef FORMAT
15421 #undef FORMAT2
15422 }
15423 
15424 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15425 {
15426    int pseudo_fd = -1;
15427    struct dahdi_versioninfo vi;
15428 
15429    switch (cmd) {
15430    case CLI_INIT:
15431       e->command = "dahdi show version";
15432       e->usage =
15433          "Usage: dahdi show version\n"
15434          "       Shows the DAHDI version in use\n";
15435       return NULL;
15436    case CLI_GENERATE:
15437       return NULL;
15438    }
15439    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15440       ast_cli(a->fd, "Failed to open control file to get version.\n");
15441       return CLI_SUCCESS;
15442    }
15443 
15444    strcpy(vi.version, "Unknown");
15445    strcpy(vi.echo_canceller, "Unknown");
15446 
15447    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15448       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15449    else
15450       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15451 
15452    close(pseudo_fd);
15453 
15454    return CLI_SUCCESS;
15455 }
15456 
15457 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15458 {
15459    int channel;
15460    int gain;
15461    int tx;
15462    struct dahdi_hwgain hwgain;
15463    struct dahdi_pvt *tmp = NULL;
15464 
15465    switch (cmd) {
15466    case CLI_INIT:
15467       e->command = "dahdi set hwgain";
15468       e->usage =
15469          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15470          "  Sets the hardware gain on a a given channel, overriding the\n"
15471          "   value provided at module loadtime, whether the channel is in\n"
15472          "   use or not.  Changes take effect immediately.\n"
15473          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15474          "   <chan num> is the channel number relative to the device\n"
15475          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15476       return NULL;
15477    case CLI_GENERATE:
15478       return NULL;
15479    }
15480 
15481    if (a->argc != 6)
15482       return CLI_SHOWUSAGE;
15483 
15484    if (!strcasecmp("rx", a->argv[3]))
15485       tx = 0; /* rx */
15486    else if (!strcasecmp("tx", a->argv[3]))
15487       tx = 1; /* tx */
15488    else
15489       return CLI_SHOWUSAGE;
15490 
15491    channel = atoi(a->argv[4]);
15492    gain = atof(a->argv[5])*10.0;
15493 
15494    ast_mutex_lock(&iflock);
15495 
15496    for (tmp = iflist; tmp; tmp = tmp->next) {
15497 
15498       if (tmp->channel != channel)
15499          continue;
15500 
15501       if (tmp->subs[SUB_REAL].dfd == -1)
15502          break;
15503 
15504       hwgain.newgain = gain;
15505       hwgain.tx = tx;
15506       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15507          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15508          ast_mutex_unlock(&iflock);
15509          return CLI_FAILURE;
15510       }
15511       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15512          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15513       break;
15514    }
15515 
15516    ast_mutex_unlock(&iflock);
15517 
15518    if (tmp)
15519       return CLI_SUCCESS;
15520 
15521    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15522    return CLI_FAILURE;
15523 
15524 }
15525 
15526 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15527 {
15528    int channel;
15529    float gain;
15530    int tx;
15531    int res;
15532    struct dahdi_pvt *tmp = NULL;
15533 
15534    switch (cmd) {
15535    case CLI_INIT:
15536       e->command = "dahdi set swgain";
15537       e->usage =
15538          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15539          "  Sets the software gain on a a given channel, overriding the\n"
15540          "   value provided at module loadtime, whether the channel is in\n"
15541          "   use or not.  Changes take effect immediately.\n"
15542          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15543          "   <chan num> is the channel number relative to the device\n"
15544          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15545       return NULL;
15546    case CLI_GENERATE:
15547       return NULL;
15548    }
15549 
15550    if (a->argc != 6)
15551       return CLI_SHOWUSAGE;
15552 
15553    if (!strcasecmp("rx", a->argv[3]))
15554       tx = 0; /* rx */
15555    else if (!strcasecmp("tx", a->argv[3]))
15556       tx = 1; /* tx */
15557    else
15558       return CLI_SHOWUSAGE;
15559 
15560    channel = atoi(a->argv[4]);
15561    gain = atof(a->argv[5]);
15562 
15563    ast_mutex_lock(&iflock);
15564    for (tmp = iflist; tmp; tmp = tmp->next) {
15565 
15566       if (tmp->channel != channel)
15567          continue;
15568 
15569       if (tmp->subs[SUB_REAL].dfd == -1)
15570          break;
15571 
15572       if (tx)
15573          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15574       else
15575          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15576 
15577       if (res) {
15578          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15579          ast_mutex_unlock(&iflock);
15580          return CLI_FAILURE;
15581       }
15582 
15583       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15584          tx ? "tx" : "rx", gain, channel);
15585       break;
15586    }
15587    ast_mutex_unlock(&iflock);
15588 
15589    if (tmp)
15590       return CLI_SUCCESS;
15591 
15592    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15593    return CLI_FAILURE;
15594 
15595 }
15596 
15597 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15598 {
15599    int channel;
15600    int on;
15601    struct dahdi_pvt *dahdi_chan = NULL;
15602 
15603    switch (cmd) {
15604    case CLI_INIT:
15605       e->command = "dahdi set dnd";
15606       e->usage =
15607          "Usage: dahdi set dnd <chan#> <on|off>\n"
15608          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15609          "  Changes take effect immediately.\n"
15610          "  <chan num> is the channel number\n"
15611          "  <on|off> Enable or disable DND mode?\n"
15612          ;
15613       return NULL;
15614    case CLI_GENERATE:
15615       return NULL;
15616    }
15617 
15618    if (a->argc != 5)
15619       return CLI_SHOWUSAGE;
15620 
15621    if ((channel = atoi(a->argv[3])) <= 0) {
15622       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15623       return CLI_SHOWUSAGE;
15624    }
15625 
15626    if (ast_true(a->argv[4]))
15627       on = 1;
15628    else if (ast_false(a->argv[4]))
15629       on = 0;
15630    else {
15631       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15632       return CLI_SHOWUSAGE;
15633    }
15634 
15635    ast_mutex_lock(&iflock);
15636    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15637       if (dahdi_chan->channel != channel)
15638          continue;
15639 
15640       /* Found the channel. Actually set it */
15641       dahdi_dnd(dahdi_chan, on);
15642       break;
15643    }
15644    ast_mutex_unlock(&iflock);
15645 
15646    if (!dahdi_chan) {
15647       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15648       return CLI_FAILURE;
15649    }
15650 
15651    return CLI_SUCCESS;
15652 }
15653 
15654 static struct ast_cli_entry dahdi_cli[] = {
15655    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15656    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15657    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15658    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15659    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15660    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15661    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15662    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15663    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15664    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15665 };
15666 
15667 #define TRANSFER  0
15668 #define HANGUP    1
15669 
15670 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15671 {
15672    if (p) {
15673       switch (mode) {
15674       case TRANSFER:
15675          p->fake_event = DAHDI_EVENT_WINKFLASH;
15676          break;
15677       case HANGUP:
15678          p->fake_event = DAHDI_EVENT_ONHOOK;
15679          break;
15680       default:
15681          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15682       }
15683    }
15684    return 0;
15685 }
15686 static struct dahdi_pvt *find_channel(int channel)
15687 {
15688    struct dahdi_pvt *p;
15689 
15690    ast_mutex_lock(&iflock);
15691    for (p = iflist; p; p = p->next) {
15692       if (p->channel == channel) {
15693          break;
15694       }
15695    }
15696    ast_mutex_unlock(&iflock);
15697    return p;
15698 }
15699 
15700 /*!
15701  * \internal
15702  * \brief Get private struct using given numeric channel string.
15703  *
15704  * \param channel Numeric channel number string get private struct.
15705  *
15706  * \retval pvt on success.
15707  * \retval NULL on error.
15708  */
15709 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15710 {
15711    int chan_num;
15712 
15713    if (sscanf(channel, "%30d", &chan_num) != 1) {
15714       /* Not numeric string. */
15715       return NULL;
15716    }
15717 
15718    return find_channel(chan_num);
15719 }
15720 
15721 static int action_dahdidndon(struct mansession *s, const struct message *m)
15722 {
15723    struct dahdi_pvt *p;
15724    const char *channel = astman_get_header(m, "DAHDIChannel");
15725 
15726    if (ast_strlen_zero(channel)) {
15727       astman_send_error(s, m, "No channel specified");
15728       return 0;
15729    }
15730    p = find_channel_from_str(channel);
15731    if (!p) {
15732       astman_send_error(s, m, "No such channel");
15733       return 0;
15734    }
15735    dahdi_dnd(p, 1);
15736    astman_send_ack(s, m, "DND Enabled");
15737    return 0;
15738 }
15739 
15740 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15741 {
15742    struct dahdi_pvt *p;
15743    const char *channel = astman_get_header(m, "DAHDIChannel");
15744 
15745    if (ast_strlen_zero(channel)) {
15746       astman_send_error(s, m, "No channel specified");
15747       return 0;
15748    }
15749    p = find_channel_from_str(channel);
15750    if (!p) {
15751       astman_send_error(s, m, "No such channel");
15752       return 0;
15753    }
15754    dahdi_dnd(p, 0);
15755    astman_send_ack(s, m, "DND Disabled");
15756    return 0;
15757 }
15758 
15759 static int action_transfer(struct mansession *s, const struct message *m)
15760 {
15761    struct dahdi_pvt *p;
15762    const char *channel = astman_get_header(m, "DAHDIChannel");
15763 
15764    if (ast_strlen_zero(channel)) {
15765       astman_send_error(s, m, "No channel specified");
15766       return 0;
15767    }
15768    p = find_channel_from_str(channel);
15769    if (!p) {
15770       astman_send_error(s, m, "No such channel");
15771       return 0;
15772    }
15773    if (!analog_lib_handles(p->sig, 0, 0)) {
15774       astman_send_error(s, m, "Channel signaling is not analog");
15775       return 0;
15776    }
15777    dahdi_fake_event(p,TRANSFER);
15778    astman_send_ack(s, m, "DAHDITransfer");
15779    return 0;
15780 }
15781 
15782 static int action_transferhangup(struct mansession *s, const struct message *m)
15783 {
15784    struct dahdi_pvt *p;
15785    const char *channel = astman_get_header(m, "DAHDIChannel");
15786 
15787    if (ast_strlen_zero(channel)) {
15788       astman_send_error(s, m, "No channel specified");
15789       return 0;
15790    }
15791    p = find_channel_from_str(channel);
15792    if (!p) {
15793       astman_send_error(s, m, "No such channel");
15794       return 0;
15795    }
15796    if (!analog_lib_handles(p->sig, 0, 0)) {
15797       astman_send_error(s, m, "Channel signaling is not analog");
15798       return 0;
15799    }
15800    dahdi_fake_event(p,HANGUP);
15801    astman_send_ack(s, m, "DAHDIHangup");
15802    return 0;
15803 }
15804 
15805 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15806 {
15807    struct dahdi_pvt *p;
15808    const char *channel = astman_get_header(m, "DAHDIChannel");
15809    const char *number = astman_get_header(m, "Number");
15810    int i;
15811 
15812    if (ast_strlen_zero(channel)) {
15813       astman_send_error(s, m, "No channel specified");
15814       return 0;
15815    }
15816    if (ast_strlen_zero(number)) {
15817       astman_send_error(s, m, "No number specified");
15818       return 0;
15819    }
15820    p = find_channel_from_str(channel);
15821    if (!p) {
15822       astman_send_error(s, m, "No such channel");
15823       return 0;
15824    }
15825    if (!p->owner) {
15826       astman_send_error(s, m, "Channel does not have it's owner");
15827       return 0;
15828    }
15829    for (i = 0; i < strlen(number); i++) {
15830       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15831       dahdi_queue_frame(p, &f);
15832    }
15833    astman_send_ack(s, m, "DAHDIDialOffhook");
15834    return 0;
15835 }
15836 
15837 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15838 {
15839    struct dahdi_pvt *tmp = NULL;
15840    const char *id = astman_get_header(m, "ActionID");
15841    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15842    char idText[256] = "";
15843    int channels = 0;
15844    int dahdichanquery;
15845 
15846    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15847       /* Not numeric string. */
15848       dahdichanquery = -1;
15849    }
15850 
15851    astman_send_ack(s, m, "DAHDI channel status will follow");
15852    if (!ast_strlen_zero(id))
15853       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15854 
15855    ast_mutex_lock(&iflock);
15856 
15857    for (tmp = iflist; tmp; tmp = tmp->next) {
15858       if (tmp->channel > 0) {
15859          int alm;
15860 
15861          /* If a specific channel is queried for, only deliver status for that channel */
15862          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15863             continue;
15864 
15865          alm = get_alarms(tmp);
15866          channels++;
15867          if (tmp->owner) {
15868             /* Add data if we have a current call */
15869             astman_append(s,
15870                "Event: DAHDIShowChannels\r\n"
15871                "DAHDIChannel: %d\r\n"
15872                "Channel: %s\r\n"
15873                "Uniqueid: %s\r\n"
15874                "AccountCode: %s\r\n"
15875                "Signalling: %s\r\n"
15876                "SignallingCode: %d\r\n"
15877                "Context: %s\r\n"
15878                "DND: %s\r\n"
15879                "Alarm: %s\r\n"
15880                "%s"
15881                "\r\n",
15882                tmp->channel,
15883                tmp->owner->name,
15884                tmp->owner->uniqueid,
15885                tmp->owner->accountcode,
15886                sig2str(tmp->sig),
15887                tmp->sig,
15888                tmp->context,
15889                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15890                alarm2str(alm), idText);
15891          } else {
15892             astman_append(s,
15893                "Event: DAHDIShowChannels\r\n"
15894                "DAHDIChannel: %d\r\n"
15895                "Signalling: %s\r\n"
15896                "SignallingCode: %d\r\n"
15897                "Context: %s\r\n"
15898                "DND: %s\r\n"
15899                "Alarm: %s\r\n"
15900                "%s"
15901                "\r\n",
15902                tmp->channel, sig2str(tmp->sig), tmp->sig,
15903                tmp->context,
15904                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15905                alarm2str(alm), idText);
15906          }
15907       }
15908    }
15909 
15910    ast_mutex_unlock(&iflock);
15911 
15912    astman_append(s,
15913       "Event: DAHDIShowChannelsComplete\r\n"
15914       "%s"
15915       "Items: %d\r\n"
15916       "\r\n",
15917       idText,
15918       channels);
15919    return 0;
15920 }
15921 
15922 #if defined(HAVE_SS7)
15923 static int linkset_addsigchan(int sigchan)
15924 {
15925    struct dahdi_ss7 *link;
15926    int res;
15927    int curfd;
15928    struct dahdi_params params;
15929    struct dahdi_bufferinfo bi;
15930    struct dahdi_spaninfo si;
15931 
15932    if (sigchan < 0) {
15933       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15934       return -1;
15935    }
15936    if (cur_ss7type < 0) {
15937       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15938       return -1;
15939    }
15940    if (cur_pointcode < 0) {
15941       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15942       return -1;
15943    }
15944    if (cur_adjpointcode < 0) {
15945       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15946       return -1;
15947    }
15948    if (cur_defaultdpc < 0) {
15949       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15950       return -1;
15951    }
15952    if (cur_networkindicator < 0) {
15953       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15954       return -1;
15955    }
15956    link = ss7_resolve_linkset(cur_linkset);
15957    if (!link) {
15958       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15959       return -1;
15960    }
15961    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15962       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15963       return -1;
15964    }
15965 
15966    curfd = link->ss7.numsigchans;
15967 
15968    /* Open signaling channel */
15969    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15970    if (link->ss7.fds[curfd] < 0) {
15971       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15972          strerror(errno));
15973       return -1;
15974    }
15975    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15976       dahdi_close_ss7_fd(link, curfd);
15977       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15978          strerror(errno));
15979       return -1;
15980    }
15981 
15982    /* Get signaling channel parameters */
15983    memset(&params, 0, sizeof(params));
15984    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
15985    if (res) {
15986       dahdi_close_ss7_fd(link, curfd);
15987       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15988          strerror(errno));
15989       return -1;
15990    }
15991    if (params.sigtype != DAHDI_SIG_HDLCFCS
15992       && params.sigtype != DAHDI_SIG_HARDHDLC
15993       && params.sigtype != DAHDI_SIG_MTP2) {
15994       dahdi_close_ss7_fd(link, curfd);
15995       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15996       return -1;
15997    }
15998 
15999    /* Set signaling channel buffer policy. */
16000    memset(&bi, 0, sizeof(bi));
16001    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16002    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16003    bi.numbufs = 32;
16004    bi.bufsize = 512;
16005    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16006       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16007          sigchan, strerror(errno));
16008       dahdi_close_ss7_fd(link, curfd);
16009       return -1;
16010    }
16011 
16012    /* Get current signaling channel alarm status. */
16013    memset(&si, 0, sizeof(si));
16014    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16015    if (res) {
16016       dahdi_close_ss7_fd(link, curfd);
16017       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16018          strerror(errno));
16019    }
16020 
16021    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16022       (params.sigtype == DAHDI_SIG_MTP2)
16023          ? SS7_TRANSPORT_DAHDIMTP2
16024          : SS7_TRANSPORT_DAHDIDCHAN,
16025       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16026    if (res) {
16027       dahdi_close_ss7_fd(link, curfd);
16028       return -1;
16029    }
16030 
16031    ++link->ss7.numsigchans;
16032 
16033    return 0;
16034 }
16035 #endif   /* defined(HAVE_SS7) */
16036 
16037 #if defined(HAVE_SS7)
16038 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16039 {
16040    int span;
16041    switch (cmd) {
16042    case CLI_INIT:
16043       e->command = "ss7 set debug {on|off} linkset";
16044       e->usage =
16045          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16046          "       Enables debugging on a given SS7 linkset\n";
16047       return NULL;
16048    case CLI_GENERATE:
16049       return NULL;
16050    }
16051    if (a->argc < 6)
16052       return CLI_SHOWUSAGE;
16053    span = atoi(a->argv[5]);
16054    if ((span < 1) || (span > NUM_SPANS)) {
16055       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16056       return CLI_SUCCESS;
16057    }
16058    if (!linksets[span-1].ss7.ss7) {
16059       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16060    } else {
16061       if (!strcasecmp(a->argv[3], "on")) {
16062          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16063          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16064       } else {
16065          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16066          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16067       }
16068    }
16069 
16070    return CLI_SUCCESS;
16071 }
16072 #endif   /* defined(HAVE_SS7) */
16073 
16074 #if defined(HAVE_SS7)
16075 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16076 {
16077    int linkset, cic;
16078    int blocked = -1, i;
16079    switch (cmd) {
16080    case CLI_INIT:
16081       e->command = "ss7 block cic";
16082       e->usage =
16083          "Usage: ss7 block cic <linkset> <CIC>\n"
16084          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16085       return NULL;
16086    case CLI_GENERATE:
16087       return NULL;
16088    }
16089    if (a->argc == 5)
16090       linkset = atoi(a->argv[3]);
16091    else
16092       return CLI_SHOWUSAGE;
16093 
16094    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16095       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16096       return CLI_SUCCESS;
16097    }
16098 
16099    if (!linksets[linkset-1].ss7.ss7) {
16100       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16101       return CLI_SUCCESS;
16102    }
16103 
16104    cic = atoi(a->argv[4]);
16105 
16106    if (cic < 1) {
16107       ast_cli(a->fd, "Invalid CIC specified!\n");
16108       return CLI_SUCCESS;
16109    }
16110 
16111    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16112       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16113          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16114          if (!blocked) {
16115             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16116             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16117             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16118          }
16119       }
16120    }
16121 
16122    if (blocked < 0) {
16123       ast_cli(a->fd, "Invalid CIC specified!\n");
16124       return CLI_SUCCESS;
16125    }
16126 
16127    if (!blocked)
16128       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16129    else
16130       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16131 
16132    /* Break poll on the linkset so it sends our messages */
16133    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16134 
16135    return CLI_SUCCESS;
16136 }
16137 #endif   /* defined(HAVE_SS7) */
16138 
16139 #if defined(HAVE_SS7)
16140 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16141 {
16142    int linkset;
16143    int i;
16144    switch (cmd) {
16145    case CLI_INIT:
16146       e->command = "ss7 block linkset";
16147       e->usage =
16148          "Usage: ss7 block linkset <linkset number>\n"
16149          "       Sends a remote blocking request for all CICs on the given linkset\n";
16150       return NULL;
16151    case CLI_GENERATE:
16152       return NULL;
16153    }
16154    if (a->argc == 4)
16155       linkset = atoi(a->argv[3]);
16156    else
16157       return CLI_SHOWUSAGE;
16158 
16159    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16160       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16161       return CLI_SUCCESS;
16162    }
16163 
16164    if (!linksets[linkset-1].ss7.ss7) {
16165       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16166       return CLI_SUCCESS;
16167    }
16168 
16169    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16170       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16171       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16172       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16173       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16174    }
16175 
16176    /* Break poll on the linkset so it sends our messages */
16177    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16178 
16179    return CLI_SUCCESS;
16180 }
16181 #endif   /* defined(HAVE_SS7) */
16182 
16183 #if defined(HAVE_SS7)
16184 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16185 {
16186    int linkset, cic;
16187    int i, blocked = -1;
16188    switch (cmd) {
16189    case CLI_INIT:
16190       e->command = "ss7 unblock cic";
16191       e->usage =
16192          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16193          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16194       return NULL;
16195    case CLI_GENERATE:
16196       return NULL;
16197    }
16198 
16199    if (a->argc == 5)
16200       linkset = atoi(a->argv[3]);
16201    else
16202       return CLI_SHOWUSAGE;
16203 
16204    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16205       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16206       return CLI_SUCCESS;
16207    }
16208 
16209    if (!linksets[linkset-1].ss7.ss7) {
16210       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16211       return CLI_SUCCESS;
16212    }
16213 
16214    cic = atoi(a->argv[4]);
16215 
16216    if (cic < 1) {
16217       ast_cli(a->fd, "Invalid CIC specified!\n");
16218       return CLI_SUCCESS;
16219    }
16220 
16221    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16222       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16223          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16224          if (blocked) {
16225             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16226             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16227             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16228          }
16229       }
16230    }
16231 
16232    if (blocked > 0)
16233       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16234 
16235    /* Break poll on the linkset so it sends our messages */
16236    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16237 
16238    return CLI_SUCCESS;
16239 }
16240 #endif   /* defined(HAVE_SS7) */
16241 
16242 #if defined(HAVE_SS7)
16243 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16244 {
16245    int linkset;
16246    int i;
16247    switch (cmd) {
16248    case CLI_INIT:
16249       e->command = "ss7 unblock linkset";
16250       e->usage =
16251          "Usage: ss7 unblock linkset <linkset number>\n"
16252          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16253       return NULL;
16254    case CLI_GENERATE:
16255       return NULL;
16256    }
16257 
16258    if (a->argc == 4)
16259       linkset = atoi(a->argv[3]);
16260    else
16261       return CLI_SHOWUSAGE;
16262 
16263    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16264       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16265       return CLI_SUCCESS;
16266    }
16267 
16268    if (!linksets[linkset-1].ss7.ss7) {
16269       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16270       return CLI_SUCCESS;
16271    }
16272 
16273    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16274       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16275       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16276       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16277       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16278    }
16279 
16280    /* Break poll on the linkset so it sends our messages */
16281    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16282 
16283    return CLI_SUCCESS;
16284 }
16285 #endif   /* defined(HAVE_SS7) */
16286 
16287 #if defined(HAVE_SS7)
16288 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16289 {
16290    int linkset;
16291    struct sig_ss7_linkset *ss7;
16292    switch (cmd) {
16293    case CLI_INIT:
16294       e->command = "ss7 show linkset";
16295       e->usage =
16296          "Usage: ss7 show linkset <span>\n"
16297          "       Shows the status of an SS7 linkset.\n";
16298       return NULL;
16299    case CLI_GENERATE:
16300       return NULL;
16301    }
16302 
16303    if (a->argc < 4)
16304       return CLI_SHOWUSAGE;
16305    linkset = atoi(a->argv[3]);
16306    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16307       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16308       return CLI_SUCCESS;
16309    }
16310    ss7 = &linksets[linkset - 1].ss7;
16311    if (!ss7->ss7) {
16312       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16313       return CLI_SUCCESS;
16314    }
16315 
16316    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16317 
16318    return CLI_SUCCESS;
16319 }
16320 #endif   /* defined(HAVE_SS7) */
16321 
16322 #if defined(HAVE_SS7)
16323 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16324 {
16325    switch (cmd) {
16326    case CLI_INIT:
16327       e->command = "ss7 show version";
16328       e->usage =
16329          "Usage: ss7 show version\n"
16330          "  Show the libss7 version\n";
16331       return NULL;
16332    case CLI_GENERATE:
16333       return NULL;
16334    }
16335 
16336    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16337 
16338    return CLI_SUCCESS;
16339 }
16340 #endif   /* defined(HAVE_SS7) */
16341 
16342 #if defined(HAVE_SS7)
16343 static struct ast_cli_entry dahdi_ss7_cli[] = {
16344    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16345    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16346    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16347    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16348    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16349    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16350    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16351 };
16352 #endif   /* defined(HAVE_SS7) */
16353 
16354 #if defined(HAVE_PRI)
16355 #if defined(HAVE_PRI_CCSS)
16356 /*!
16357  * \internal
16358  * \brief CC agent initialization.
16359  * \since 1.8
16360  *
16361  * \param agent CC core agent control.
16362  * \param chan Original channel the agent will attempt to recall.
16363  *
16364  * \details
16365  * This callback is called when the CC core is initialized.  Agents should allocate
16366  * any private data necessary for the call and assign it to the private_data
16367  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16368  * specific agent type, they should be set in this function as well.
16369  *
16370  * \retval 0 on success.
16371  * \retval -1 on error.
16372  */
16373 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16374 {
16375    struct dahdi_pvt *pvt;
16376    struct sig_pri_chan *pvt_chan;
16377    int res;
16378 
16379    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16380 
16381    pvt = chan->tech_pvt;
16382    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16383       pvt_chan = pvt->sig_pvt;
16384    } else {
16385       pvt_chan = NULL;
16386    }
16387    if (!pvt_chan) {
16388       return -1;
16389    }
16390 
16391    ast_module_ref(ast_module_info->self);
16392 
16393    res = sig_pri_cc_agent_init(agent, pvt_chan);
16394    if (res) {
16395       ast_module_unref(ast_module_info->self);
16396    }
16397    return res;
16398 }
16399 #endif   /* defined(HAVE_PRI_CCSS) */
16400 #endif   /* defined(HAVE_PRI) */
16401 
16402 #if defined(HAVE_PRI)
16403 #if defined(HAVE_PRI_CCSS)
16404 /*!
16405  * \internal
16406  * \brief Destroy private data on the agent.
16407  * \since 1.8
16408  *
16409  * \param agent CC core agent control.
16410  *
16411  * \details
16412  * The core will call this function upon completion
16413  * or failure of CC.
16414  *
16415  * \return Nothing
16416  */
16417 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16418 {
16419    sig_pri_cc_agent_destructor(agent);
16420 
16421    ast_module_unref(ast_module_info->self);
16422 }
16423 #endif   /* defined(HAVE_PRI_CCSS) */
16424 #endif   /* defined(HAVE_PRI) */
16425 
16426 #if defined(HAVE_PRI)
16427 #if defined(HAVE_PRI_CCSS)
16428 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16429    .type = dahdi_pri_cc_type,
16430    .init = dahdi_pri_cc_agent_init,
16431    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16432    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16433    .respond = sig_pri_cc_agent_req_rsp,
16434    .status_request = sig_pri_cc_agent_status_req,
16435    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16436    .party_b_free = sig_pri_cc_agent_party_b_free,
16437    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16438    .callee_available = sig_pri_cc_agent_callee_available,
16439    .destructor = dahdi_pri_cc_agent_destructor,
16440 };
16441 #endif   /* defined(HAVE_PRI_CCSS) */
16442 #endif   /* defined(HAVE_PRI) */
16443 
16444 #if defined(HAVE_PRI)
16445 #if defined(HAVE_PRI_CCSS)
16446 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16447    .type = dahdi_pri_cc_type,
16448    .request_cc = sig_pri_cc_monitor_req_cc,
16449    .suspend = sig_pri_cc_monitor_suspend,
16450    .unsuspend = sig_pri_cc_monitor_unsuspend,
16451    .status_response = sig_pri_cc_monitor_status_rsp,
16452    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16453    .destructor = sig_pri_cc_monitor_destructor,
16454 };
16455 #endif   /* defined(HAVE_PRI_CCSS) */
16456 #endif   /* defined(HAVE_PRI) */
16457 
16458 static int __unload_module(void)
16459 {
16460    struct dahdi_pvt *p;
16461 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16462    int i, j;
16463 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16464 
16465 #ifdef HAVE_PRI
16466    for (i = 0; i < NUM_SPANS; i++) {
16467       if (pris[i].pri.master != AST_PTHREADT_NULL)
16468          pthread_cancel(pris[i].pri.master);
16469    }
16470    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16471    ast_unregister_application(dahdi_send_keypad_facility_app);
16472 #ifdef HAVE_PRI_PROG_W_CAUSE
16473    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16474 #endif
16475 #endif
16476 #if defined(HAVE_SS7)
16477    for (i = 0; i < NUM_SPANS; i++) {
16478       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16479          pthread_cancel(linksets[i].ss7.master);
16480       }
16481    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16482 #endif   /* defined(HAVE_SS7) */
16483 #if defined(HAVE_OPENR2)
16484    dahdi_r2_destroy_links();
16485    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16486    ast_unregister_application(dahdi_accept_r2_call_app);
16487 #endif
16488 
16489    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16490    ast_manager_unregister("DAHDIDialOffhook");
16491    ast_manager_unregister("DAHDIHangup");
16492    ast_manager_unregister("DAHDITransfer");
16493    ast_manager_unregister("DAHDIDNDoff");
16494    ast_manager_unregister("DAHDIDNDon");
16495    ast_manager_unregister("DAHDIShowChannels");
16496    ast_manager_unregister("DAHDIRestart");
16497    ast_data_unregister(NULL);
16498    ast_channel_unregister(&dahdi_tech);
16499 
16500    /* Hangup all interfaces if they have an owner */
16501    ast_mutex_lock(&iflock);
16502    for (p = iflist; p; p = p->next) {
16503       if (p->owner)
16504          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16505    }
16506    ast_mutex_unlock(&iflock);
16507 
16508    ast_mutex_lock(&monlock);
16509    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16510       pthread_cancel(monitor_thread);
16511       pthread_kill(monitor_thread, SIGURG);
16512       pthread_join(monitor_thread, NULL);
16513    }
16514    monitor_thread = AST_PTHREADT_STOP;
16515    ast_mutex_unlock(&monlock);
16516 
16517    destroy_all_channels();
16518 
16519 #if defined(HAVE_PRI)
16520    for (i = 0; i < NUM_SPANS; i++) {
16521       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16522          pthread_join(pris[i].pri.master, NULL);
16523       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16524          dahdi_close_pri_fd(&(pris[i]), j);
16525       }
16526       sig_pri_stop_pri(&pris[i].pri);
16527    }
16528 #if defined(HAVE_PRI_CCSS)
16529    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16530    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16531 #endif   /* defined(HAVE_PRI_CCSS) */
16532    sig_pri_unload();
16533 #endif
16534 
16535 #if defined(HAVE_SS7)
16536    for (i = 0; i < NUM_SPANS; i++) {
16537       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16538          pthread_join(linksets[i].ss7.master, NULL);
16539       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16540          dahdi_close_ss7_fd(&(linksets[i]), j);
16541       }
16542    }
16543 #endif   /* defined(HAVE_SS7) */
16544    ast_cond_destroy(&ss_thread_complete);
16545    return 0;
16546 }
16547 
16548 static int unload_module(void)
16549 {
16550 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16551    int y;
16552 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16553 #ifdef HAVE_PRI
16554    for (y = 0; y < NUM_SPANS; y++)
16555       ast_mutex_destroy(&pris[y].pri.lock);
16556 #endif
16557 #if defined(HAVE_SS7)
16558    for (y = 0; y < NUM_SPANS; y++)
16559       ast_mutex_destroy(&linksets[y].ss7.lock);
16560 #endif   /* defined(HAVE_SS7) */
16561    return __unload_module();
16562 }
16563 
16564 static void string_replace(char *str, int char1, int char2)
16565 {
16566    for (; *str; str++) {
16567       if (*str == char1) {
16568          *str = char2;
16569       }
16570    }
16571 }
16572 
16573 static char *parse_spanchan(char *chanstr, char **subdir)
16574 {
16575    char *p;
16576 
16577    if ((p = strrchr(chanstr, '!')) == NULL) {
16578       *subdir = NULL;
16579       return chanstr;
16580    }
16581    *p++ = '\0';
16582    string_replace(chanstr, '!', '/');
16583    *subdir = chanstr;
16584    return p;
16585 }
16586 
16587 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16588 {
16589    char *c, *chan;
16590    char *subdir;
16591    int x, start, finish;
16592    struct dahdi_pvt *tmp;
16593 
16594    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16595       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16596       return -1;
16597    }
16598 
16599    c = ast_strdupa(value);
16600    c = parse_spanchan(c, &subdir);
16601 
16602    while ((chan = strsep(&c, ","))) {
16603       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16604          /* Range */
16605       } else if (sscanf(chan, "%30d", &start)) {
16606          /* Just one */
16607          finish = start;
16608       } else if (!strcasecmp(chan, "pseudo")) {
16609          finish = start = CHAN_PSEUDO;
16610          if (found_pseudo)
16611             *found_pseudo = 1;
16612       } else {
16613          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16614          return -1;
16615       }
16616       if (finish < start) {
16617          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16618          x = finish;
16619          finish = start;
16620          start = x;
16621       }
16622 
16623       for (x = start; x <= finish; x++) {
16624          char fn[PATH_MAX];
16625          int real_channel = x;
16626 
16627          if (!ast_strlen_zero(subdir)) {
16628             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16629             if (real_channel < 0) {
16630                if (conf->ignore_failed_channels) {
16631                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16632                         subdir, x, real_channel);
16633                   continue;
16634                } else {
16635                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16636                         subdir, x, real_channel);
16637                   return -1;
16638                }
16639             }
16640          }
16641          tmp = mkintf(real_channel, conf, reload);
16642 
16643          if (tmp) {
16644             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16645          } else {
16646             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16647                   (reload == 1) ? "reconfigure" : "register", value);
16648             return -1;
16649          }
16650       }
16651    }
16652 
16653    return 0;
16654 }
16655 
16656 /** The length of the parameters list of 'dahdichan'.
16657  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16658 #define MAX_CHANLIST_LEN 80
16659 
16660 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16661 {
16662    char *parse = ast_strdupa(data);
16663    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16664    unsigned int param_count;
16665    unsigned int x;
16666 
16667    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16668       return;
16669 
16670    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16671 
16672    /* first parameter is tap length, process it here */
16673 
16674    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16675 
16676    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16677       confp->chan.echocancel.head.tap_length = x;
16678    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16679       confp->chan.echocancel.head.tap_length = 128;
16680 
16681    /* now process any remaining parameters */
16682 
16683    for (x = 1; x < param_count; x++) {
16684       struct {
16685          char *name;
16686          char *value;
16687       } param;
16688 
16689       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16690          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16691          continue;
16692       }
16693 
16694       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16695          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16696          continue;
16697       }
16698 
16699       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16700 
16701       if (param.value) {
16702          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16703             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16704             continue;
16705          }
16706       }
16707       confp->chan.echocancel.head.param_count++;
16708    }
16709 }
16710 
16711 /*! process_dahdi() - ignore keyword 'channel' and similar */
16712 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16713 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16714 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16715 
16716 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16717 {
16718    struct dahdi_pvt *tmp;
16719    int y;
16720    int found_pseudo = 0;
16721    struct ast_variable *dahdichan = NULL;
16722 
16723    for (; v; v = v->next) {
16724       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16725          continue;
16726 
16727       /* Create the interface list */
16728       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16729          if (options & PROC_DAHDI_OPT_NOCHAN) {
16730             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16731             continue;
16732          }
16733          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16734             if (confp->ignore_failed_channels) {
16735                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16736                continue;
16737             } else {
16738                return -1;
16739             }
16740          }
16741          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16742       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16743          confp->ignore_failed_channels = ast_true(v->value);
16744       } else if (!strcasecmp(v->name, "buffers")) {
16745          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16746             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16747             confp->chan.buf_no = numbufs;
16748             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16749          }
16750       } else if (!strcasecmp(v->name, "faxbuffers")) {
16751          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16752             confp->chan.usefaxbuffers = 1;
16753          }
16754       } else if (!strcasecmp(v->name, "dahdichan")) {
16755          /* Only process the last dahdichan value. */
16756          dahdichan = v;
16757       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16758          usedistinctiveringdetection = ast_true(v->value);
16759       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16760          distinctiveringaftercid = ast_true(v->value);
16761       } else if (!strcasecmp(v->name, "dring1context")) {
16762          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16763       } else if (!strcasecmp(v->name, "dring2context")) {
16764          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16765       } else if (!strcasecmp(v->name, "dring3context")) {
16766          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16767       } else if (!strcasecmp(v->name, "dring1range")) {
16768          confp->chan.drings.ringnum[0].range = atoi(v->value);
16769       } else if (!strcasecmp(v->name, "dring2range")) {
16770          confp->chan.drings.ringnum[1].range = atoi(v->value);
16771       } else if (!strcasecmp(v->name, "dring3range")) {
16772          confp->chan.drings.ringnum[2].range = atoi(v->value);
16773       } else if (!strcasecmp(v->name, "dring1")) {
16774          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
16775       } else if (!strcasecmp(v->name, "dring2")) {
16776          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
16777       } else if (!strcasecmp(v->name, "dring3")) {
16778          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
16779       } else if (!strcasecmp(v->name, "usecallerid")) {
16780          confp->chan.use_callerid = ast_true(v->value);
16781       } else if (!strcasecmp(v->name, "cidsignalling")) {
16782          if (!strcasecmp(v->value, "bell"))
16783             confp->chan.cid_signalling = CID_SIG_BELL;
16784          else if (!strcasecmp(v->value, "v23"))
16785             confp->chan.cid_signalling = CID_SIG_V23;
16786          else if (!strcasecmp(v->value, "dtmf"))
16787             confp->chan.cid_signalling = CID_SIG_DTMF;
16788          else if (!strcasecmp(v->value, "smdi"))
16789             confp->chan.cid_signalling = CID_SIG_SMDI;
16790          else if (!strcasecmp(v->value, "v23_jp"))
16791             confp->chan.cid_signalling = CID_SIG_V23_JP;
16792          else if (ast_true(v->value))
16793             confp->chan.cid_signalling = CID_SIG_BELL;
16794       } else if (!strcasecmp(v->name, "cidstart")) {
16795          if (!strcasecmp(v->value, "ring"))
16796             confp->chan.cid_start = CID_START_RING;
16797          else if (!strcasecmp(v->value, "polarity_in"))
16798             confp->chan.cid_start = CID_START_POLARITY_IN;
16799          else if (!strcasecmp(v->value, "polarity"))
16800             confp->chan.cid_start = CID_START_POLARITY;
16801          else if (!strcasecmp(v->value, "dtmf"))
16802             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16803          else if (ast_true(v->value))
16804             confp->chan.cid_start = CID_START_RING;
16805       } else if (!strcasecmp(v->name, "threewaycalling")) {
16806          confp->chan.threewaycalling = ast_true(v->value);
16807       } else if (!strcasecmp(v->name, "cancallforward")) {
16808          confp->chan.cancallforward = ast_true(v->value);
16809       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16810          if (ast_true(v->value))
16811             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16812          else
16813             confp->chan.dtmfrelax = 0;
16814       } else if (!strcasecmp(v->name, "mailbox")) {
16815          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16816       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16817          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16818             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16819          }
16820       } else if (!strcasecmp(v->name, "adsi")) {
16821          confp->chan.adsi = ast_true(v->value);
16822       } else if (!strcasecmp(v->name, "usesmdi")) {
16823          confp->chan.use_smdi = ast_true(v->value);
16824       } else if (!strcasecmp(v->name, "smdiport")) {
16825          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16826       } else if (!strcasecmp(v->name, "transfer")) {
16827          confp->chan.transfer = ast_true(v->value);
16828       } else if (!strcasecmp(v->name, "canpark")) {
16829          confp->chan.canpark = ast_true(v->value);
16830       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16831          confp->chan.echocanbridged = ast_true(v->value);
16832       } else if (!strcasecmp(v->name, "busydetect")) {
16833          confp->chan.busydetect = ast_true(v->value);
16834       } else if (!strcasecmp(v->name, "busycount")) {
16835          confp->chan.busycount = atoi(v->value);
16836       } else if (!strcasecmp(v->name, "busypattern")) {
16837          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16838             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16839          }
16840       } else if (!strcasecmp(v->name, "callprogress")) {
16841          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16842          if (ast_true(v->value))
16843             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16844       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16845          confp->chan.waitfordialtone = atoi(v->value);
16846       } else if (!strcasecmp(v->name, "faxdetect")) {
16847          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16848          if (!strcasecmp(v->value, "incoming")) {
16849             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16850          } else if (!strcasecmp(v->value, "outgoing")) {
16851             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16852          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16853             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16854       } else if (!strcasecmp(v->name, "echocancel")) {
16855          process_echocancel(confp, v->value, v->lineno);
16856       } else if (!strcasecmp(v->name, "echotraining")) {
16857          if (sscanf(v->value, "%30d", &y) == 1) {
16858             if ((y < 10) || (y > 4000)) {
16859                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16860             } else {
16861                confp->chan.echotraining = y;
16862             }
16863          } else if (ast_true(v->value)) {
16864             confp->chan.echotraining = 400;
16865          } else
16866             confp->chan.echotraining = 0;
16867       } else if (!strcasecmp(v->name, "hidecallerid")) {
16868          confp->chan.hidecallerid = ast_true(v->value);
16869       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16870          confp->chan.hidecalleridname = ast_true(v->value);
16871       } else if (!strcasecmp(v->name, "pulsedial")) {
16872          confp->chan.pulse = ast_true(v->value);
16873       } else if (!strcasecmp(v->name, "callreturn")) {
16874          confp->chan.callreturn = ast_true(v->value);
16875       } else if (!strcasecmp(v->name, "callwaiting")) {
16876          confp->chan.callwaiting = ast_true(v->value);
16877       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16878          confp->chan.callwaitingcallerid = ast_true(v->value);
16879       } else if (!strcasecmp(v->name, "context")) {
16880          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16881       } else if (!strcasecmp(v->name, "language")) {
16882          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16883       } else if (!strcasecmp(v->name, "progzone")) {
16884          ast_copy_string(progzone, v->value, sizeof(progzone));
16885       } else if (!strcasecmp(v->name, "mohinterpret")
16886          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16887          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16888       } else if (!strcasecmp(v->name, "mohsuggest")) {
16889          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16890       } else if (!strcasecmp(v->name, "parkinglot")) {
16891          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16892       } else if (!strcasecmp(v->name, "stripmsd")) {
16893          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16894          confp->chan.stripmsd = atoi(v->value);
16895       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16896          numbufs = atoi(v->value);
16897       } else if (!strcasecmp(v->name, "group")) {
16898          confp->chan.group = ast_get_group(v->value);
16899       } else if (!strcasecmp(v->name, "callgroup")) {
16900          if (!strcasecmp(v->value, "none"))
16901             confp->chan.callgroup = 0;
16902          else
16903             confp->chan.callgroup = ast_get_group(v->value);
16904       } else if (!strcasecmp(v->name, "pickupgroup")) {
16905          if (!strcasecmp(v->value, "none"))
16906             confp->chan.pickupgroup = 0;
16907          else
16908             confp->chan.pickupgroup = ast_get_group(v->value);
16909       } else if (!strcasecmp(v->name, "setvar")) {
16910          char *varname = ast_strdupa(v->value), *varval = NULL;
16911          struct ast_variable *tmpvar;
16912          if (varname && (varval = strchr(varname, '='))) {
16913             *varval++ = '\0';
16914             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16915                tmpvar->next = confp->chan.vars;
16916                confp->chan.vars = tmpvar;
16917             }
16918          }
16919       } else if (!strcasecmp(v->name, "immediate")) {
16920          confp->chan.immediate = ast_true(v->value);
16921       } else if (!strcasecmp(v->name, "transfertobusy")) {
16922          confp->chan.transfertobusy = ast_true(v->value);
16923       } else if (!strcasecmp(v->name, "mwimonitor")) {
16924          confp->chan.mwimonitor_neon = 0;
16925          confp->chan.mwimonitor_fsk = 0;
16926          confp->chan.mwimonitor_rpas = 0;
16927          if (strcasestr(v->value, "fsk")) {
16928             confp->chan.mwimonitor_fsk = 1;
16929          }
16930          if (strcasestr(v->value, "rpas")) {
16931             confp->chan.mwimonitor_rpas = 1;
16932          }
16933          if (strcasestr(v->value, "neon")) {
16934             confp->chan.mwimonitor_neon = 1;
16935          }
16936          /* If set to true or yes, assume that simple fsk is desired */
16937          if (ast_true(v->value)) {
16938             confp->chan.mwimonitor_fsk = 1;
16939          }
16940       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16941          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16942             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16943          }
16944       } else if (!strcasecmp(v->name, "rxgain")) {
16945          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16946             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16947          }
16948       } else if (!strcasecmp(v->name, "txgain")) {
16949          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16950             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16951          }
16952       } else if (!strcasecmp(v->name, "txdrc")) {
16953          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16954             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16955          }
16956       } else if (!strcasecmp(v->name, "rxdrc")) {
16957          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16958             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16959          }
16960       } else if (!strcasecmp(v->name, "tonezone")) {
16961          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16962             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16963          }
16964       } else if (!strcasecmp(v->name, "callerid")) {
16965          if (!strcasecmp(v->value, "asreceived")) {
16966             confp->chan.cid_num[0] = '\0';
16967             confp->chan.cid_name[0] = '\0';
16968          } else {
16969             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16970          }
16971       } else if (!strcasecmp(v->name, "fullname")) {
16972          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16973       } else if (!strcasecmp(v->name, "cid_number")) {
16974          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16975       } else if (!strcasecmp(v->name, "cid_tag")) {
16976          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16977       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16978          confp->chan.dahditrcallerid = ast_true(v->value);
16979       } else if (!strcasecmp(v->name, "restrictcid")) {
16980          confp->chan.restrictcid = ast_true(v->value);
16981       } else if (!strcasecmp(v->name, "usecallingpres")) {
16982          confp->chan.use_callingpres = ast_true(v->value);
16983       } else if (!strcasecmp(v->name, "accountcode")) {
16984          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16985       } else if (!strcasecmp(v->name, "amaflags")) {
16986          y = ast_cdr_amaflags2int(v->value);
16987          if (y < 0)
16988             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16989          else
16990             confp->chan.amaflags = y;
16991       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16992          confp->chan.polarityonanswerdelay = atoi(v->value);
16993       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16994          confp->chan.answeronpolarityswitch = ast_true(v->value);
16995       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16996          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16997       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16998          confp->chan.sendcalleridafter = atoi(v->value);
16999       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17000          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17001       } else if (ast_cc_is_config_param(v->name)) {
17002          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17003       } else if (!strcasecmp(v->name, "mwisendtype")) {
17004 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17005          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17006             mwisend_rpas = 1;
17007          } else {
17008             mwisend_rpas = 0;
17009          }
17010 #else
17011          /* Default is fsk, to turn it off you must specify nofsk */
17012          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17013          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17014             confp->chan.mwisend_fsk = 0;
17015          } else {             /* Default FSK */
17016             confp->chan.mwisend_fsk = 1;
17017          }
17018          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17019             confp->chan.mwisend_rpas = 1;
17020          } else {
17021             confp->chan.mwisend_rpas = 0;
17022          }
17023          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17024             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17025          }
17026          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17027             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17028          }
17029          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17030             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17031          }
17032 #endif
17033       } else if (reload != 1) {
17034           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17035             int orig_radio = confp->chan.radio;
17036             int orig_outsigmod = confp->chan.outsigmod;
17037             int orig_auto = confp->is_sig_auto;
17038 
17039             confp->chan.radio = 0;
17040             confp->chan.outsigmod = -1;
17041             confp->is_sig_auto = 0;
17042             if (!strcasecmp(v->value, "em")) {
17043                confp->chan.sig = SIG_EM;
17044             } else if (!strcasecmp(v->value, "em_e1")) {
17045                confp->chan.sig = SIG_EM_E1;
17046             } else if (!strcasecmp(v->value, "em_w")) {
17047                confp->chan.sig = SIG_EMWINK;
17048             } else if (!strcasecmp(v->value, "fxs_ls")) {
17049                confp->chan.sig = SIG_FXSLS;
17050             } else if (!strcasecmp(v->value, "fxs_gs")) {
17051                confp->chan.sig = SIG_FXSGS;
17052             } else if (!strcasecmp(v->value, "fxs_ks")) {
17053                confp->chan.sig = SIG_FXSKS;
17054             } else if (!strcasecmp(v->value, "fxo_ls")) {
17055                confp->chan.sig = SIG_FXOLS;
17056             } else if (!strcasecmp(v->value, "fxo_gs")) {
17057                confp->chan.sig = SIG_FXOGS;
17058             } else if (!strcasecmp(v->value, "fxo_ks")) {
17059                confp->chan.sig = SIG_FXOKS;
17060             } else if (!strcasecmp(v->value, "fxs_rx")) {
17061                confp->chan.sig = SIG_FXSKS;
17062                confp->chan.radio = 1;
17063             } else if (!strcasecmp(v->value, "fxo_rx")) {
17064                confp->chan.sig = SIG_FXOLS;
17065                confp->chan.radio = 1;
17066             } else if (!strcasecmp(v->value, "fxs_tx")) {
17067                confp->chan.sig = SIG_FXSLS;
17068                confp->chan.radio = 1;
17069             } else if (!strcasecmp(v->value, "fxo_tx")) {
17070                confp->chan.sig = SIG_FXOGS;
17071                confp->chan.radio = 1;
17072             } else if (!strcasecmp(v->value, "em_rx")) {
17073                confp->chan.sig = SIG_EM;
17074                confp->chan.radio = 1;
17075             } else if (!strcasecmp(v->value, "em_tx")) {
17076                confp->chan.sig = SIG_EM;
17077                confp->chan.radio = 1;
17078             } else if (!strcasecmp(v->value, "em_rxtx")) {
17079                confp->chan.sig = SIG_EM;
17080                confp->chan.radio = 2;
17081             } else if (!strcasecmp(v->value, "em_txrx")) {
17082                confp->chan.sig = SIG_EM;
17083                confp->chan.radio = 2;
17084             } else if (!strcasecmp(v->value, "sf")) {
17085                confp->chan.sig = SIG_SF;
17086             } else if (!strcasecmp(v->value, "sf_w")) {
17087                confp->chan.sig = SIG_SFWINK;
17088             } else if (!strcasecmp(v->value, "sf_featd")) {
17089                confp->chan.sig = SIG_FEATD;
17090             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17091                confp->chan.sig = SIG_FEATDMF;
17092             } else if (!strcasecmp(v->value, "sf_featb")) {
17093                confp->chan.sig = SIG_SF_FEATB;
17094             } else if (!strcasecmp(v->value, "sf")) {
17095                confp->chan.sig = SIG_SF;
17096             } else if (!strcasecmp(v->value, "sf_rx")) {
17097                confp->chan.sig = SIG_SF;
17098                confp->chan.radio = 1;
17099             } else if (!strcasecmp(v->value, "sf_tx")) {
17100                confp->chan.sig = SIG_SF;
17101                confp->chan.radio = 1;
17102             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17103                confp->chan.sig = SIG_SF;
17104                confp->chan.radio = 2;
17105             } else if (!strcasecmp(v->value, "sf_txrx")) {
17106                confp->chan.sig = SIG_SF;
17107                confp->chan.radio = 2;
17108             } else if (!strcasecmp(v->value, "featd")) {
17109                confp->chan.sig = SIG_FEATD;
17110             } else if (!strcasecmp(v->value, "featdmf")) {
17111                confp->chan.sig = SIG_FEATDMF;
17112             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17113                confp->chan.sig = SIG_FEATDMF_TA;
17114             } else if (!strcasecmp(v->value, "e911")) {
17115                confp->chan.sig = SIG_E911;
17116             } else if (!strcasecmp(v->value, "fgccama")) {
17117                confp->chan.sig = SIG_FGC_CAMA;
17118             } else if (!strcasecmp(v->value, "fgccamamf")) {
17119                confp->chan.sig = SIG_FGC_CAMAMF;
17120             } else if (!strcasecmp(v->value, "featb")) {
17121                confp->chan.sig = SIG_FEATB;
17122 #ifdef HAVE_PRI
17123             } else if (!strcasecmp(v->value, "pri_net")) {
17124                confp->chan.sig = SIG_PRI;
17125                confp->pri.pri.nodetype = PRI_NETWORK;
17126             } else if (!strcasecmp(v->value, "pri_cpe")) {
17127                confp->chan.sig = SIG_PRI;
17128                confp->pri.pri.nodetype = PRI_CPE;
17129             } else if (!strcasecmp(v->value, "bri_cpe")) {
17130                confp->chan.sig = SIG_BRI;
17131                confp->pri.pri.nodetype = PRI_CPE;
17132             } else if (!strcasecmp(v->value, "bri_net")) {
17133                confp->chan.sig = SIG_BRI;
17134                confp->pri.pri.nodetype = PRI_NETWORK;
17135             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17136                confp->chan.sig = SIG_BRI_PTMP;
17137                confp->pri.pri.nodetype = PRI_CPE;
17138             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17139 #if defined(HAVE_PRI_CALL_HOLD)
17140                confp->chan.sig = SIG_BRI_PTMP;
17141                confp->pri.pri.nodetype = PRI_NETWORK;
17142 #else
17143                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17144 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17145 #endif
17146 #if defined(HAVE_SS7)
17147             } else if (!strcasecmp(v->value, "ss7")) {
17148                confp->chan.sig = SIG_SS7;
17149 #endif   /* defined(HAVE_SS7) */
17150 #ifdef HAVE_OPENR2
17151             } else if (!strcasecmp(v->value, "mfcr2")) {
17152                confp->chan.sig = SIG_MFCR2;
17153 #endif
17154             } else if (!strcasecmp(v->value, "auto")) {
17155                confp->is_sig_auto = 1;
17156             } else {
17157                confp->chan.outsigmod = orig_outsigmod;
17158                confp->chan.radio = orig_radio;
17159                confp->is_sig_auto = orig_auto;
17160                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17161             }
17162           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17163             if (!strcasecmp(v->value, "em")) {
17164                confp->chan.outsigmod = SIG_EM;
17165             } else if (!strcasecmp(v->value, "em_e1")) {
17166                confp->chan.outsigmod = SIG_EM_E1;
17167             } else if (!strcasecmp(v->value, "em_w")) {
17168                confp->chan.outsigmod = SIG_EMWINK;
17169             } else if (!strcasecmp(v->value, "sf")) {
17170                confp->chan.outsigmod = SIG_SF;
17171             } else if (!strcasecmp(v->value, "sf_w")) {
17172                confp->chan.outsigmod = SIG_SFWINK;
17173             } else if (!strcasecmp(v->value, "sf_featd")) {
17174                confp->chan.outsigmod = SIG_FEATD;
17175             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17176                confp->chan.outsigmod = SIG_FEATDMF;
17177             } else if (!strcasecmp(v->value, "sf_featb")) {
17178                confp->chan.outsigmod = SIG_SF_FEATB;
17179             } else if (!strcasecmp(v->value, "sf")) {
17180                confp->chan.outsigmod = SIG_SF;
17181             } else if (!strcasecmp(v->value, "featd")) {
17182                confp->chan.outsigmod = SIG_FEATD;
17183             } else if (!strcasecmp(v->value, "featdmf")) {
17184                confp->chan.outsigmod = SIG_FEATDMF;
17185             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17186                confp->chan.outsigmod = SIG_FEATDMF_TA;
17187             } else if (!strcasecmp(v->value, "e911")) {
17188                confp->chan.outsigmod = SIG_E911;
17189             } else if (!strcasecmp(v->value, "fgccama")) {
17190                confp->chan.outsigmod = SIG_FGC_CAMA;
17191             } else if (!strcasecmp(v->value, "fgccamamf")) {
17192                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17193             } else if (!strcasecmp(v->value, "featb")) {
17194                confp->chan.outsigmod = SIG_FEATB;
17195             } else {
17196                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17197             }
17198 #ifdef HAVE_PRI
17199          } else if (!strcasecmp(v->name, "pridialplan")) {
17200             if (!strcasecmp(v->value, "national")) {
17201                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17202             } else if (!strcasecmp(v->value, "unknown")) {
17203                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17204             } else if (!strcasecmp(v->value, "private")) {
17205                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17206             } else if (!strcasecmp(v->value, "international")) {
17207                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17208             } else if (!strcasecmp(v->value, "local")) {
17209                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17210             } else if (!strcasecmp(v->value, "dynamic")) {
17211                confp->pri.pri.dialplan = -1;
17212             } else if (!strcasecmp(v->value, "redundant")) {
17213                confp->pri.pri.dialplan = -2;
17214             } else {
17215                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17216             }
17217          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17218             if (!strcasecmp(v->value, "national")) {
17219                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17220             } else if (!strcasecmp(v->value, "unknown")) {
17221                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17222             } else if (!strcasecmp(v->value, "private")) {
17223                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17224             } else if (!strcasecmp(v->value, "international")) {
17225                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17226             } else if (!strcasecmp(v->value, "local")) {
17227                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17228             } else if (!strcasecmp(v->value, "dynamic")) {
17229                confp->pri.pri.localdialplan = -1;
17230             } else if (!strcasecmp(v->value, "redundant")) {
17231                confp->pri.pri.localdialplan = -2;
17232             } else {
17233                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17234             }
17235          } else if (!strcasecmp(v->name, "switchtype")) {
17236             if (!strcasecmp(v->value, "national"))
17237                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17238             else if (!strcasecmp(v->value, "ni1"))
17239                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17240             else if (!strcasecmp(v->value, "dms100"))
17241                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17242             else if (!strcasecmp(v->value, "4ess"))
17243                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17244             else if (!strcasecmp(v->value, "5ess"))
17245                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17246             else if (!strcasecmp(v->value, "euroisdn"))
17247                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17248             else if (!strcasecmp(v->value, "qsig"))
17249                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17250             else {
17251                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17252                return -1;
17253             }
17254          } else if (!strcasecmp(v->name, "msn")) {
17255             ast_copy_string(confp->pri.pri.msn_list, v->value,
17256                sizeof(confp->pri.pri.msn_list));
17257          } else if (!strcasecmp(v->name, "nsf")) {
17258             if (!strcasecmp(v->value, "sdn"))
17259                confp->pri.pri.nsf = PRI_NSF_SDN;
17260             else if (!strcasecmp(v->value, "megacom"))
17261                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17262             else if (!strcasecmp(v->value, "tollfreemegacom"))
17263                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17264             else if (!strcasecmp(v->value, "accunet"))
17265                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17266             else if (!strcasecmp(v->value, "none"))
17267                confp->pri.pri.nsf = PRI_NSF_NONE;
17268             else {
17269                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17270                confp->pri.pri.nsf = PRI_NSF_NONE;
17271             }
17272          } else if (!strcasecmp(v->name, "priindication")) {
17273             if (!strcasecmp(v->value, "outofband"))
17274                confp->chan.priindication_oob = 1;
17275             else if (!strcasecmp(v->value, "inband"))
17276                confp->chan.priindication_oob = 0;
17277             else
17278                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17279                   v->value, v->lineno);
17280          } else if (!strcasecmp(v->name, "priexclusive")) {
17281             confp->chan.priexclusive = ast_true(v->value);
17282          } else if (!strcasecmp(v->name, "internationalprefix")) {
17283             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17284          } else if (!strcasecmp(v->name, "nationalprefix")) {
17285             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17286          } else if (!strcasecmp(v->name, "localprefix")) {
17287             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17288          } else if (!strcasecmp(v->name, "privateprefix")) {
17289             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17290          } else if (!strcasecmp(v->name, "unknownprefix")) {
17291             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17292          } else if (!strcasecmp(v->name, "resetinterval")) {
17293             if (!strcasecmp(v->value, "never"))
17294                confp->pri.pri.resetinterval = -1;
17295             else if (atoi(v->value) >= 60)
17296                confp->pri.pri.resetinterval = atoi(v->value);
17297             else
17298                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17299                   v->value, v->lineno);
17300          } else if (!strcasecmp(v->name, "minunused")) {
17301             confp->pri.pri.minunused = atoi(v->value);
17302          } else if (!strcasecmp(v->name, "minidle")) {
17303             confp->pri.pri.minidle = atoi(v->value);
17304          } else if (!strcasecmp(v->name, "idleext")) {
17305             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17306          } else if (!strcasecmp(v->name, "idledial")) {
17307             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17308          } else if (!strcasecmp(v->name, "overlapdial")) {
17309             if (ast_true(v->value)) {
17310                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17311             } else if (!strcasecmp(v->value, "incoming")) {
17312                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17313             } else if (!strcasecmp(v->value, "outgoing")) {
17314                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17315             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17316                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17317             } else {
17318                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17319             }
17320 #ifdef HAVE_PRI_PROG_W_CAUSE
17321          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17322             if (!strcasecmp(v->value, "logical")) {
17323                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17324             } else if (!strcasecmp(v->value, "physical")) {
17325                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17326             } else {
17327                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17328             }
17329 #endif
17330          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17331             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17332 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17333          } else if (!strcasecmp(v->name, "service_message_support")) {
17334             /* assuming switchtype for this channel group has been configured already */
17335             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17336                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17337                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17338                confp->pri.pri.enable_service_message_support = 1;
17339             } else {
17340                confp->pri.pri.enable_service_message_support = 0;
17341             }
17342 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17343 #ifdef HAVE_PRI_INBANDDISCONNECT
17344          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17345             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17346 #endif
17347          } else if (!strcasecmp(v->name, "pritimer")) {
17348 #ifdef PRI_GETSET_TIMERS
17349             char tmp[20];
17350             char *timerc;
17351             char *c;
17352             int timer;
17353             int timeridx;
17354 
17355             ast_copy_string(tmp, v->value, sizeof(tmp));
17356             c = tmp;
17357             timerc = strsep(&c, ",");
17358             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17359                timeridx = pri_timer2idx(timerc);
17360                timer = atoi(c);
17361                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17362                   ast_log(LOG_WARNING,
17363                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17364                      v->lineno);
17365                } else if (!timer) {
17366                   ast_log(LOG_WARNING,
17367                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17368                      c, timerc, v->lineno);
17369                } else {
17370                   confp->pri.pri.pritimers[timeridx] = timer;
17371                }
17372             } else {
17373                ast_log(LOG_WARNING,
17374                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17375                   v->value, v->lineno);
17376             }
17377 #endif /* PRI_GETSET_TIMERS */
17378          } else if (!strcasecmp(v->name, "facilityenable")) {
17379             confp->pri.pri.facilityenable = ast_true(v->value);
17380 #if defined(HAVE_PRI_AOC_EVENTS)
17381          } else if (!strcasecmp(v->name, "aoc_enable")) {
17382             confp->pri.pri.aoc_passthrough_flag = 0;
17383             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17384                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17385             }
17386             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17387                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17388             }
17389             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17390                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17391             }
17392          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17393             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17394 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17395 #if defined(HAVE_PRI_CALL_HOLD)
17396          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17397             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17398 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17399 #if defined(HAVE_PRI_CCSS)
17400          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17401             if (!strcasecmp(v->value, "global")) {
17402                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17403             } else if (!strcasecmp(v->value, "specific")) {
17404                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17405             } else {
17406                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17407             }
17408          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17409             if (!strcasecmp(v->value, "release")) {
17410                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17411             } else if (!strcasecmp(v->value, "retain")) {
17412                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17413             } else if (!strcasecmp(v->value, "do_not_care")) {
17414                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17415             } else {
17416                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17417             }
17418          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17419             if (!strcasecmp(v->value, "release")) {
17420                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17421             } else if (!strcasecmp(v->value, "retain")) {
17422                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17423             } else {
17424                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17425             }
17426 #endif   /* defined(HAVE_PRI_CCSS) */
17427 #if defined(HAVE_PRI_CALL_WAITING)
17428          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17429             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17430             if (confp->pri.pri.max_call_waiting_calls < 0) {
17431                /* Negative values are not allowed. */
17432                confp->pri.pri.max_call_waiting_calls = 0;
17433             }
17434          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17435             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17436 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17437 #if defined(HAVE_PRI_MWI)
17438          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17439             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17440                sizeof(confp->pri.pri.mwi_mailboxes));
17441 #endif   /* defined(HAVE_PRI_MWI) */
17442          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17443             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17444 #if defined(HAVE_PRI_L2_PERSISTENCE)
17445          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17446             if (!strcasecmp(v->value, "keep_up")) {
17447                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17448             } else if (!strcasecmp(v->value, "leave_down")) {
17449                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17450             } else {
17451                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17452             }
17453 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17454 #endif /* HAVE_PRI */
17455 #if defined(HAVE_SS7)
17456          } else if (!strcasecmp(v->name, "ss7type")) {
17457             if (!strcasecmp(v->value, "itu")) {
17458                cur_ss7type = SS7_ITU;
17459             } else if (!strcasecmp(v->value, "ansi")) {
17460                cur_ss7type = SS7_ANSI;
17461             } else
17462                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17463          } else if (!strcasecmp(v->name, "linkset")) {
17464             cur_linkset = atoi(v->value);
17465          } else if (!strcasecmp(v->name, "pointcode")) {
17466             cur_pointcode = parse_pointcode(v->value);
17467          } else if (!strcasecmp(v->name, "adjpointcode")) {
17468             cur_adjpointcode = parse_pointcode(v->value);
17469          } else if (!strcasecmp(v->name, "defaultdpc")) {
17470             cur_defaultdpc = parse_pointcode(v->value);
17471          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17472             cur_cicbeginswith = atoi(v->value);
17473          } else if (!strcasecmp(v->name, "networkindicator")) {
17474             if (!strcasecmp(v->value, "national"))
17475                cur_networkindicator = SS7_NI_NAT;
17476             else if (!strcasecmp(v->value, "national_spare"))
17477                cur_networkindicator = SS7_NI_NAT_SPARE;
17478             else if (!strcasecmp(v->value, "international"))
17479                cur_networkindicator = SS7_NI_INT;
17480             else if (!strcasecmp(v->value, "international_spare"))
17481                cur_networkindicator = SS7_NI_INT_SPARE;
17482             else
17483                cur_networkindicator = -1;
17484          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17485             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17486          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17487             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17488          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17489             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17490          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17491             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17492          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17493             if (!strcasecmp(v->value, "national")) {
17494                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17495             } else if (!strcasecmp(v->value, "international")) {
17496                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17497             } else if (!strcasecmp(v->value, "subscriber")) {
17498                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17499             } else if (!strcasecmp(v->value, "unknown")) {
17500                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17501             } else if (!strcasecmp(v->value, "dynamic")) {
17502                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17503             } else {
17504                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17505             }
17506          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17507             if (!strcasecmp(v->value, "national")) {
17508                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17509             } else if (!strcasecmp(v->value, "international")) {
17510                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17511             } else if (!strcasecmp(v->value, "subscriber")) {
17512                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17513             } else if (!strcasecmp(v->value, "unknown")) {
17514                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17515             } else if (!strcasecmp(v->value, "dynamic")) {
17516                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17517             } else {
17518                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17519             }
17520          } else if (!strcasecmp(v->name, "sigchan")) {
17521             int sigchan, res;
17522             sigchan = atoi(v->value);
17523             res = linkset_addsigchan(sigchan);
17524             if (res < 0)
17525                return -1;
17526 
17527          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17528             struct dahdi_ss7 *link;
17529             link = ss7_resolve_linkset(cur_linkset);
17530             if (!link) {
17531                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17532                return -1;
17533             }
17534             if (ast_true(v->value))
17535                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17536 #endif   /* defined(HAVE_SS7) */
17537 #ifdef HAVE_OPENR2
17538          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17539             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17540             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
17541          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17542             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17543          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17544             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17545             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17546                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17547                confp->mfcr2.variant = OR2_VAR_ITU;
17548             }
17549          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17550             confp->mfcr2.mfback_timeout = atoi(v->value);
17551             if (!confp->mfcr2.mfback_timeout) {
17552                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17553                confp->mfcr2.mfback_timeout = -1;
17554             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17555                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17556             }
17557          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17558             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17559             if (confp->mfcr2.metering_pulse_timeout > 500) {
17560                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17561             }
17562          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17563             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17564          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17565             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17566          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17567             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17568          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17569             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17570          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17571             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17572          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17573             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17574          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17575             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17576 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17577          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17578             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17579 #endif
17580          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17581             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17582          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17583             confp->mfcr2.max_ani = atoi(v->value);
17584             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17585                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17586             }
17587          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17588             confp->mfcr2.max_dnis = atoi(v->value);
17589             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17590                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17591             }
17592          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17593             confp->mfcr2.category = openr2_proto_get_category(v->value);
17594             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17595                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17596                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17597                      v->value, v->lineno);
17598             }
17599          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17600             openr2_log_level_t tmplevel;
17601             char *clevel;
17602             char *logval = ast_strdupa(v->value);
17603             while (logval) {
17604                clevel = strsep(&logval,",");
17605                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17606                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17607                   continue;
17608                }
17609                confp->mfcr2.loglevel |= tmplevel;
17610             }
17611 #endif /* HAVE_OPENR2 */
17612          } else if (!strcasecmp(v->name, "cadence")) {
17613             /* setup to scan our argument */
17614             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17615             int i;
17616             struct dahdi_ring_cadence new_cadence;
17617             int cid_location = -1;
17618             int firstcadencepos = 0;
17619             char original_args[80];
17620             int cadence_is_ok = 1;
17621 
17622             ast_copy_string(original_args, v->value, sizeof(original_args));
17623             /* 16 cadences allowed (8 pairs) */
17624             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
17625 
17626             /* Cadence must be even (on/off) */
17627             if (element_count % 2 == 1) {
17628                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17629                cadence_is_ok = 0;
17630             }
17631 
17632             /* Ring cadences cannot be negative */
17633             for (i = 0; i < element_count; i++) {
17634                if (c[i] == 0) {
17635                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17636                   cadence_is_ok = 0;
17637                   break;
17638                } else if (c[i] < 0) {
17639                   if (i % 2 == 1) {
17640                      /* Silence duration, negative possibly okay */
17641                      if (cid_location == -1) {
17642                         cid_location = i;
17643                         c[i] *= -1;
17644                      } else {
17645                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17646                         cadence_is_ok = 0;
17647                         break;
17648                      }
17649                   } else {
17650                      if (firstcadencepos == 0) {
17651                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17652                                  /* duration will be passed negative to the DAHDI driver */
17653                      } else {
17654                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17655                         cadence_is_ok = 0;
17656                         break;
17657                      }
17658                   }
17659                }
17660             }
17661 
17662             /* Substitute our scanned cadence */
17663             for (i = 0; i < 16; i++) {
17664                new_cadence.ringcadence[i] = c[i];
17665             }
17666 
17667             if (cadence_is_ok) {
17668                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17669                if (element_count < 2) {
17670                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17671                } else {
17672                   if (cid_location == -1) {
17673                      /* user didn't say; default to first pause */
17674                      cid_location = 1;
17675                   } else {
17676                      /* convert element_index to cidrings value */
17677                      cid_location = (cid_location + 1) / 2;
17678                   }
17679                   /* ---we like their cadence; try to install it--- */
17680                   if (!user_has_defined_cadences++)
17681                      /* this is the first user-defined cadence; clear the default user cadences */
17682                      num_cadence = 0;
17683                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17684                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17685                   else {
17686                      cadences[num_cadence] = new_cadence;
17687                      cidrings[num_cadence++] = cid_location;
17688                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17689                   }
17690                }
17691             }
17692          } else if (!strcasecmp(v->name, "ringtimeout")) {
17693             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17694          } else if (!strcasecmp(v->name, "prewink")) {
17695             confp->timing.prewinktime = atoi(v->value);
17696          } else if (!strcasecmp(v->name, "preflash")) {
17697             confp->timing.preflashtime = atoi(v->value);
17698          } else if (!strcasecmp(v->name, "wink")) {
17699             confp->timing.winktime = atoi(v->value);
17700          } else if (!strcasecmp(v->name, "flash")) {
17701             confp->timing.flashtime = atoi(v->value);
17702          } else if (!strcasecmp(v->name, "start")) {
17703             confp->timing.starttime = atoi(v->value);
17704          } else if (!strcasecmp(v->name, "rxwink")) {
17705             confp->timing.rxwinktime = atoi(v->value);
17706          } else if (!strcasecmp(v->name, "rxflash")) {
17707             confp->timing.rxflashtime = atoi(v->value);
17708          } else if (!strcasecmp(v->name, "debounce")) {
17709             confp->timing.debouncetime = atoi(v->value);
17710          } else if (!strcasecmp(v->name, "toneduration")) {
17711             int toneduration;
17712             int ctlfd;
17713             int res;
17714             struct dahdi_dialparams dps;
17715 
17716             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17717             if (ctlfd == -1) {
17718                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17719                return -1;
17720             }
17721 
17722             toneduration = atoi(v->value);
17723             if (toneduration > -1) {
17724                memset(&dps, 0, sizeof(dps));
17725 
17726                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17727                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17728                if (res < 0) {
17729                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17730                   close(ctlfd);
17731                   return -1;
17732                }
17733             }
17734             close(ctlfd);
17735          } else if (!strcasecmp(v->name, "defaultcic")) {
17736             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17737          } else if (!strcasecmp(v->name, "defaultozz")) {
17738             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17739          } else if (!strcasecmp(v->name, "mwilevel")) {
17740             mwilevel = atoi(v->value);
17741          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17742             dtmfcid_level = atoi(v->value);
17743          } else if (!strcasecmp(v->name, "reportalarms")) {
17744             if (!strcasecmp(v->value, "all"))
17745                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17746             if (!strcasecmp(v->value, "none"))
17747                report_alarms = 0;
17748             else if (!strcasecmp(v->value, "channels"))
17749                report_alarms = REPORT_CHANNEL_ALARMS;
17750             else if (!strcasecmp(v->value, "spans"))
17751                report_alarms = REPORT_SPAN_ALARMS;
17752           }
17753       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17754          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17755    }
17756 
17757    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
17758    if (confp->chan.vars) {
17759       ast_variables_destroy(confp->chan.vars);
17760       confp->chan.vars = NULL;
17761    }
17762 
17763    if (dahdichan) {
17764       /* Process the deferred dahdichan value. */
17765       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17766          &found_pseudo)) {
17767          if (confp->ignore_failed_channels) {
17768             ast_log(LOG_WARNING,
17769                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17770                dahdichan->value);
17771          } else {
17772             return -1;
17773          }
17774       }
17775    }
17776 
17777    /* mark the first channels of each DAHDI span to watch for their span alarms */
17778    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17779       if (!tmp->destroy && tmp->span != y) {
17780          tmp->manages_span_alarms = 1;
17781          y = tmp->span; 
17782       } else {
17783          tmp->manages_span_alarms = 0;
17784       }
17785    }
17786 
17787    /*< \todo why check for the pseudo in the per-channel section.
17788     * Any actual use for manual setup of the pseudo channel? */
17789    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17790       /* use the default configuration for a channel, so
17791          that any settings from real configured channels
17792          don't "leak" into the pseudo channel config
17793       */
17794       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17795 
17796       if (conf.chan.cc_params) {
17797          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17798       } else {
17799          tmp = NULL;
17800       }
17801       if (tmp) {
17802          ast_verb(3, "Automatically generated pseudo channel\n");
17803       } else {
17804          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17805       }
17806       ast_cc_config_params_destroy(conf.chan.cc_params);
17807    }
17808    return 0;
17809 }
17810 
17811 /*!
17812  * \internal
17813  * \brief Deep copy struct dahdi_chan_conf.
17814  * \since 1.8
17815  *
17816  * \param dest Destination.
17817  * \param src Source.
17818  *
17819  * \return Nothing
17820  */
17821 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17822 {
17823    struct ast_cc_config_params *cc_params;
17824 
17825    cc_params = dest->chan.cc_params;
17826    *dest = *src;
17827    dest->chan.cc_params = cc_params;
17828    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17829 }
17830 
17831 /*!
17832  * \internal
17833  * \brief Setup DAHDI channel driver.
17834  *
17835  * \param reload enum: load_module(0), reload(1), restart(2).
17836  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
17837  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
17838  * \param conf Local config parameters.  So cc_params can be properly destroyed.
17839  *
17840  * \retval 0 on success.
17841  * \retval -1 on error.
17842  */
17843 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17844 {
17845    struct ast_config *cfg;
17846    struct ast_config *ucfg;
17847    struct ast_variable *v;
17848    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17849    const char *chans;
17850    const char *cat;
17851    int res;
17852 
17853 #ifdef HAVE_PRI
17854    char *c;
17855    int spanno;
17856    int i;
17857    int logicalspan;
17858    int trunkgroup;
17859    int dchannels[SIG_PRI_NUM_DCHANS];
17860 #endif
17861    int have_cfg_now;
17862    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
17863 
17864    cfg = ast_config_load(config, config_flags);
17865    have_cfg_now = !!cfg;
17866    if (!cfg) {
17867       /* Error if we have no config file */
17868       if (had_cfg_before) {
17869          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17870          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17871       }
17872       cfg = ast_config_new();/* Dummy config */
17873       if (!cfg) {
17874          return 0;
17875       }
17876       ucfg = ast_config_load("users.conf", config_flags);
17877       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17878          ast_config_destroy(cfg);
17879          return 0;
17880       }
17881       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17882          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17883          ast_config_destroy(cfg);
17884          return 0;
17885       }
17886    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17887       ucfg = ast_config_load("users.conf", config_flags);
17888       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17889          return 0;
17890       }
17891       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17892          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17893          return 0;
17894       }
17895       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17896       cfg = ast_config_load(config, config_flags);
17897       have_cfg_now = !!cfg;
17898       if (!cfg) {
17899          if (had_cfg_before) {
17900             /* We should have been able to load the config. */
17901             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
17902             ast_config_destroy(ucfg);
17903             return 0;
17904          }
17905          cfg = ast_config_new();/* Dummy config */
17906          if (!cfg) {
17907             ast_config_destroy(ucfg);
17908             return 0;
17909          }
17910       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17911          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17912          ast_config_destroy(ucfg);
17913          return 0;
17914       }
17915    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17916       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17917       return 0;
17918    } else {
17919       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17920       ucfg = ast_config_load("users.conf", config_flags);
17921       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17922          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17923          ast_config_destroy(cfg);
17924          return 0;
17925       }
17926    }
17927    had_cfg_before = have_cfg_now;
17928 
17929    /* It's a little silly to lock it, but we might as well just to be sure */
17930    ast_mutex_lock(&iflock);
17931 #ifdef HAVE_PRI
17932    if (reload != 1) {
17933       /* Process trunkgroups first */
17934       v = ast_variable_browse(cfg, "trunkgroups");
17935       while (v) {
17936          if (!strcasecmp(v->name, "trunkgroup")) {
17937             trunkgroup = atoi(v->value);
17938             if (trunkgroup > 0) {
17939                if ((c = strchr(v->value, ','))) {
17940                   i = 0;
17941                   memset(dchannels, 0, sizeof(dchannels));
17942                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
17943                      dchannels[i] = atoi(c + 1);
17944                      if (dchannels[i] < 0) {
17945                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17946                      } else
17947                         i++;
17948                      c = strchr(c + 1, ',');
17949                   }
17950                   if (i) {
17951                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17952                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
17953                   } else
17954                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
17955                   } else
17956                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17957                } else
17958                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17959             } else
17960                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17961          } else if (!strcasecmp(v->name, "spanmap")) {
17962             spanno = atoi(v->value);
17963             if (spanno > 0) {
17964                if ((c = strchr(v->value, ','))) {
17965                   trunkgroup = atoi(c + 1);
17966                   if (trunkgroup > 0) {
17967                      if ((c = strchr(c + 1, ',')))
17968                         logicalspan = atoi(c + 1);
17969                      else
17970                         logicalspan = 0;
17971                      if (logicalspan >= 0) {
17972                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17973                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17974                      } else
17975                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17976                      } else
17977                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
17978                   } else
17979                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17980                } else
17981                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17982             } else
17983                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17984          } else {
17985             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17986          }
17987          v = v->next;
17988       }
17989    }
17990 #endif
17991 
17992    /* Copy the default jb config over global_jbconf */
17993    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17994 
17995    mwimonitornotify[0] = '\0';
17996 
17997    v = ast_variable_browse(cfg, "channels");
17998    if ((res = process_dahdi(base_conf,
17999       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18000       v, reload, 0))) {
18001       ast_mutex_unlock(&iflock);
18002       ast_config_destroy(cfg);
18003       if (ucfg) {
18004          ast_config_destroy(ucfg);
18005       }
18006       return res;
18007    }
18008 
18009    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18010    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18011       /* [channels] and [trunkgroups] are used. Let's also reserve
18012        * [globals] and [general] for future use
18013        */
18014       if (!strcasecmp(cat, "general") ||
18015          !strcasecmp(cat, "trunkgroups") ||
18016          !strcasecmp(cat, "globals") ||
18017          !strcasecmp(cat, "channels")) {
18018          continue;
18019       }
18020 
18021       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18022       if (ast_strlen_zero(chans)) {
18023          /* Section is useless without a dahdichan value present. */
18024          continue;
18025       }
18026 
18027       /* Copy base_conf to conf. */
18028       deep_copy_dahdi_chan_conf(conf, base_conf);
18029 
18030       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18031          ast_mutex_unlock(&iflock);
18032          ast_config_destroy(cfg);
18033          if (ucfg) {
18034             ast_config_destroy(ucfg);
18035          }
18036          return res;
18037       }
18038    }
18039 
18040    ast_config_destroy(cfg);
18041 
18042    if (ucfg) {
18043       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18044       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18045       process_dahdi(base_conf,
18046          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18047          ast_variable_browse(ucfg, "general"), 1, 0);
18048 
18049       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18050          if (!strcasecmp(cat, "general")) {
18051             continue;
18052          }
18053 
18054          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18055          if (ast_strlen_zero(chans)) {
18056             /* Section is useless without a dahdichan value present. */
18057             continue;
18058          }
18059 
18060          /* Copy base_conf to conf. */
18061          deep_copy_dahdi_chan_conf(conf, base_conf);
18062 
18063          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18064             ast_config_destroy(ucfg);
18065             ast_mutex_unlock(&iflock);
18066             return res;
18067          }
18068       }
18069       ast_config_destroy(ucfg);
18070    }
18071    ast_mutex_unlock(&iflock);
18072 
18073 #ifdef HAVE_PRI
18074    if (reload != 1) {
18075       int x;
18076       for (x = 0; x < NUM_SPANS; x++) {
18077          if (pris[x].pri.pvts[0]) {
18078             prepare_pri(pris + x);
18079             if (sig_pri_start_pri(&pris[x].pri)) {
18080                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18081                return -1;
18082             } else
18083                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18084          }
18085       }
18086    }
18087 #endif
18088 #if defined(HAVE_SS7)
18089    if (reload != 1) {
18090       int x;
18091       for (x = 0; x < NUM_SPANS; x++) {
18092          if (linksets[x].ss7.ss7) {
18093             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18094             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18095                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18096                return -1;
18097             } else
18098                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18099          }
18100       }
18101    }
18102 #endif   /* defined(HAVE_SS7) */
18103 #ifdef HAVE_OPENR2
18104    if (reload != 1) {
18105       int x;
18106       for (x = 0; x < r2links_count; x++) {
18107          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18108             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18109             return -1;
18110          } else {
18111             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18112          }
18113       }
18114    }
18115 #endif
18116    /* And start the monitor for the first time */
18117    restart_monitor();
18118    return 0;
18119 }
18120 
18121 /*!
18122  * \internal
18123  * \brief Setup DAHDI channel driver.
18124  *
18125  * \param reload enum: load_module(0), reload(1), restart(2).
18126  *
18127  * \retval 0 on success.
18128  * \retval -1 on error.
18129  */
18130 static int setup_dahdi(int reload)
18131 {
18132    int res;
18133    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18134    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18135    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18136 
18137    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18138       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18139    } else {
18140       res = -1;
18141    }
18142    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18143    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18144    ast_cc_config_params_destroy(conf.chan.cc_params);
18145 
18146    return res;
18147 }
18148 
18149 /*!
18150  * \internal
18151  * \brief Callback used to generate the dahdi status tree.
18152  * \param[in] search The search pattern tree.
18153  * \retval NULL on error.
18154  * \retval non-NULL The generated tree.
18155  */
18156 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18157       struct ast_data *data_root)
18158 {
18159    int ctl, res, span;
18160    struct ast_data *data_span, *data_alarms;
18161    struct dahdi_spaninfo s;
18162 
18163    ctl = open("/dev/dahdi/ctl", O_RDWR);
18164    if (ctl < 0) {
18165       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18166       return -1;
18167    }
18168    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18169       s.spanno = span;
18170       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18171       if (res) {
18172          continue;
18173       }
18174 
18175       data_span = ast_data_add_node(data_root, "span");
18176       if (!data_span) {
18177          continue;
18178       }
18179       ast_data_add_str(data_span, "description", s.desc);
18180 
18181       /* insert the alarms status */
18182       data_alarms = ast_data_add_node(data_span, "alarms");
18183       if (!data_alarms) {
18184          continue;
18185       }
18186 
18187       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18188       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18189       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18190       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18191       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18192       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18193 
18194       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18195       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18196       ast_data_add_int(data_span, "crc4", s.crc4count);
18197       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18198                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18199                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18200                      "CAS");
18201       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18202                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18203                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18204                      "Unknown");
18205       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18206                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18207                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18208       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18209 
18210       /* if this span doesn't match remove it. */
18211       if (!ast_data_search_match(search, data_span)) {
18212          ast_data_remove_node(data_root, data_span);
18213       }
18214    }
18215    close(ctl);
18216 
18217    return 0;
18218 }
18219 
18220 /*!
18221  * \internal
18222  * \brief Callback used to generate the dahdi channels tree.
18223  * \param[in] search The search pattern tree.
18224  * \retval NULL on error.
18225  * \retval non-NULL The generated tree.
18226  */
18227 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18228       struct ast_data *data_root)
18229 {
18230    struct dahdi_pvt *tmp;
18231    struct ast_data *data_channel;
18232 
18233    ast_mutex_lock(&iflock);
18234    for (tmp = iflist; tmp; tmp = tmp->next) {
18235       data_channel = ast_data_add_node(data_root, "channel");
18236       if (!data_channel) {
18237          continue;
18238       }
18239 
18240       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18241 
18242       /* if this channel doesn't match remove it. */
18243       if (!ast_data_search_match(search, data_channel)) {
18244          ast_data_remove_node(data_root, data_channel);
18245       }
18246    }
18247    ast_mutex_unlock(&iflock);
18248 
18249    return 0;
18250 }
18251 
18252 /*!
18253  * \internal
18254  * \brief Callback used to generate the dahdi channels tree.
18255  * \param[in] search The search pattern tree.
18256  * \retval NULL on error.
18257  * \retval non-NULL The generated tree.
18258  */
18259 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18260       struct ast_data *data_root)
18261 {
18262    int pseudo_fd = -1;
18263    struct dahdi_versioninfo vi = {
18264       .version = "Unknown",
18265       .echo_canceller = "Unknown"
18266    };
18267 
18268    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18269       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18270       return -1;
18271    }
18272 
18273    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18274       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18275    }
18276 
18277    close(pseudo_fd);
18278 
18279    ast_data_add_str(data_root, "value", vi.version);
18280    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18281 
18282    return 0;
18283 }
18284 
18285 static const struct ast_data_handler dahdi_status_data_provider = {
18286    .version = AST_DATA_HANDLER_VERSION,
18287    .get = dahdi_status_data_provider_get
18288 };
18289 
18290 static const struct ast_data_handler dahdi_channels_data_provider = {
18291    .version = AST_DATA_HANDLER_VERSION,
18292    .get = dahdi_channels_data_provider_get
18293 };
18294 
18295 static const struct ast_data_handler dahdi_version_data_provider = {
18296    .version = AST_DATA_HANDLER_VERSION,
18297    .get = dahdi_version_data_provider_get
18298 };
18299 
18300 static const struct ast_data_entry dahdi_data_providers[] = {
18301    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18302    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18303    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18304 };
18305 
18306 static int load_module(void)
18307 {
18308    int res;
18309 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18310    int y;
18311 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18312 
18313 #ifdef HAVE_PRI
18314    memset(pris, 0, sizeof(pris));
18315    for (y = 0; y < NUM_SPANS; y++) {
18316       sig_pri_init_pri(&pris[y].pri);
18317    }
18318    pri_set_error(dahdi_pri_error);
18319    pri_set_message(dahdi_pri_message);
18320    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18321 #ifdef HAVE_PRI_PROG_W_CAUSE
18322    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18323 #endif
18324 #if defined(HAVE_PRI_CCSS)
18325    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18326       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18327       __unload_module();
18328       return AST_MODULE_LOAD_FAILURE;
18329    }
18330 #endif   /* defined(HAVE_PRI_CCSS) */
18331    if (sig_pri_load(
18332 #if defined(HAVE_PRI_CCSS)
18333       dahdi_pri_cc_type
18334 #else
18335       NULL
18336 #endif   /* defined(HAVE_PRI_CCSS) */
18337       )) {
18338       __unload_module();
18339       return AST_MODULE_LOAD_FAILURE;
18340    }
18341 #endif
18342 #if defined(HAVE_SS7)
18343    memset(linksets, 0, sizeof(linksets));
18344    for (y = 0; y < NUM_SPANS; y++) {
18345       sig_ss7_init_linkset(&linksets[y].ss7);
18346    }
18347    ss7_set_error(dahdi_ss7_error);
18348    ss7_set_message(dahdi_ss7_message);
18349 #endif   /* defined(HAVE_SS7) */
18350    res = setup_dahdi(0);
18351    /* Make sure we can register our DAHDI channel type */
18352    if (res)
18353       return AST_MODULE_LOAD_DECLINE;
18354    if (ast_channel_register(&dahdi_tech)) {
18355       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18356       __unload_module();
18357       return AST_MODULE_LOAD_FAILURE;
18358    }
18359 #ifdef HAVE_PRI
18360    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18361 #endif
18362 #if defined(HAVE_SS7)
18363    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18364 #endif   /* defined(HAVE_SS7) */
18365 #ifdef HAVE_OPENR2
18366    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18367    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18368 #endif
18369 
18370    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18371    /* register all the data providers */
18372    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18373    memset(round_robin, 0, sizeof(round_robin));
18374    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18375    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18376    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18377    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18378    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18379    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18380    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18381 
18382    ast_cond_init(&ss_thread_complete, NULL);
18383 
18384    return res;
18385 }
18386 
18387 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18388 {
18389 #define  END_SILENCE_LEN 400
18390 #define  HEADER_MS 50
18391 #define  TRAILER_MS 5
18392 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18393 #define  ASCII_BYTES_PER_CHAR 80
18394 
18395    unsigned char *buf,*mybuf;
18396    struct dahdi_pvt *p = c->tech_pvt;
18397    struct pollfd fds[1];
18398    int size,res,fd,len,x;
18399    int bytes=0;
18400    /* Initial carrier (imaginary) */
18401    float cr = 1.0;
18402    float ci = 0.0;
18403    float scont = 0.0;
18404    int idx;
18405 
18406    idx = dahdi_get_index(c, p, 0);
18407    if (idx < 0) {
18408       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18409       return -1;
18410    }
18411    if (!text[0]) return(0); /* if nothing to send, don't */
18412    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18413    if (p->mate)
18414       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18415    else
18416       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18417    if (!buf)
18418       return -1;
18419    mybuf = buf;
18420    if (p->mate) {
18421       int codec = AST_LAW(p);
18422       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18423          PUT_CLID_MARKMS;
18424       }
18425       /* Put actual message */
18426       for (x = 0; text[x]; x++) {
18427          PUT_CLID(text[x]);
18428       }
18429       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18430          PUT_CLID_MARKMS;
18431       }
18432       len = bytes;
18433       buf = mybuf;
18434    } else {
18435       len = tdd_generate(p->tdd, buf, text);
18436       if (len < 1) {
18437          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18438          ast_free(mybuf);
18439          return -1;
18440       }
18441    }
18442    memset(buf + len, 0x7f, END_SILENCE_LEN);
18443    len += END_SILENCE_LEN;
18444    fd = p->subs[idx].dfd;
18445    while (len) {
18446       if (ast_check_hangup(c)) {
18447          ast_free(mybuf);
18448          return -1;
18449       }
18450       size = len;
18451       if (size > READ_SIZE)
18452          size = READ_SIZE;
18453       fds[0].fd = fd;
18454       fds[0].events = POLLOUT | POLLPRI;
18455       fds[0].revents = 0;
18456       res = poll(fds, 1, -1);
18457       if (!res) {
18458          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18459          continue;
18460       }
18461       /* if got exception */
18462       if (fds[0].revents & POLLPRI) {
18463          ast_free(mybuf);
18464          return -1;
18465       }
18466       if (!(fds[0].revents & POLLOUT)) {
18467          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18468          continue;
18469       }
18470       res = write(fd, buf, size);
18471       if (res != size) {
18472          if (res == -1) {
18473             ast_free(mybuf);
18474             return -1;
18475          }
18476          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18477          break;
18478       }
18479       len -= size;
18480       buf += size;
18481    }
18482    ast_free(mybuf);
18483    return(0);
18484 }
18485 
18486 
18487 static int reload(void)
18488 {
18489    int res = 0;
18490 
18491    res = setup_dahdi(1);
18492    if (res) {
18493       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18494       return -1;
18495    }
18496    return 0;
18497 }
18498 
18499 /* This is a workaround so that menuselect displays a proper description
18500  * AST_MODULE_INFO(, , "DAHDI Telephony"
18501  */
18502 
18503 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18504    .load = load_module,
18505    .unload = unload_module,
18506    .reload = reload,
18507    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18508       .nonoptreq = "res_smdi",
18509    );