Mon Mar 12 2012 21:19:29

Asterisk developer's documentation


chan_dahdi.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 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: 347006 $")
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 static int my_have_progressdetect(void *pvt)
03580 {
03581    struct dahdi_pvt *p = pvt;
03582 
03583    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03584       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03585       return 1;
03586    } else {
03587       /* Don't have progress detection. */
03588       return 0;
03589    }
03590 }
03591 
03592 static struct analog_callback dahdi_analog_callbacks =
03593 {
03594    .play_tone = my_play_tone,
03595    .get_event = my_get_event,
03596    .wait_event = my_wait_event,
03597    .is_off_hook = my_is_off_hook,
03598    .set_echocanceller = my_set_echocanceller,
03599    .ring = my_ring,
03600    .flash = my_flash,
03601    .off_hook = my_off_hook,
03602    .dial_digits = my_dial_digits,
03603    .train_echocanceller = my_train_echocanceller,
03604    .on_hook = my_on_hook,
03605    .is_dialing = my_is_dialing,
03606    .allocate_sub = my_allocate_sub,
03607    .unallocate_sub = my_unallocate_sub,
03608    .swap_subs = my_swap_subchannels,
03609    .has_voicemail = my_has_voicemail,
03610    .check_for_conference = my_check_for_conference,
03611    .conf_add = my_conf_add,
03612    .conf_del = my_conf_del,
03613    .complete_conference_update = my_complete_conference_update,
03614    .start = my_start,
03615    .all_subchannels_hungup = my_all_subchannels_hungup,
03616    .lock_private = my_lock_private,
03617    .unlock_private = my_unlock_private,
03618    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03619    .handle_dtmf = my_handle_dtmf,
03620    .wink = my_wink,
03621    .new_ast_channel = my_new_analog_ast_channel,
03622    .dsp_set_digitmode = my_dsp_set_digitmode,
03623    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03624    .send_callerid = my_send_callerid,
03625    .callwait = my_callwait,
03626    .stop_callwait = my_stop_callwait,
03627    .get_callerid = my_get_callerid,
03628    .start_cid_detect = my_start_cid_detect,
03629    .stop_cid_detect = my_stop_cid_detect,
03630    .handle_notify_message = my_handle_notify_message,
03631    .increase_ss_count = my_increase_ss_count,
03632    .decrease_ss_count = my_decrease_ss_count,
03633    .distinctive_ring = my_distinctive_ring,
03634    .set_linear_mode = my_set_linear_mode,
03635    .set_inthreeway = my_set_inthreeway,
03636    .get_and_handle_alarms = my_get_and_handle_alarms,
03637    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03638    .get_sub_fd = my_get_sub_fd,
03639    .set_cadence = my_set_cadence,
03640    .set_alarm = my_set_alarm,
03641    .set_dialing = my_set_dialing,
03642    .set_ringtimeout = my_set_ringtimeout,
03643    .set_waitingfordt = my_set_waitingfordt,
03644    .check_waitingfordt = my_check_waitingfordt,
03645    .set_confirmanswer = my_set_confirmanswer,
03646    .check_confirmanswer = my_check_confirmanswer,
03647    .set_callwaiting = my_set_callwaiting,
03648    .cancel_cidspill = my_cancel_cidspill,
03649    .confmute = my_confmute,
03650    .set_pulsedial = my_set_pulsedial,
03651    .set_new_owner = my_set_new_owner,
03652    .get_orig_dialstring = my_get_orig_dialstring,
03653    .set_needringing = my_set_needringing,
03654    .set_polarity = my_set_polarity,
03655    .start_polarityswitch = my_start_polarityswitch,
03656    .answer_polarityswitch = my_answer_polarityswitch,
03657    .hangup_polarityswitch = my_hangup_polarityswitch,
03658    .have_progressdetect = my_have_progressdetect,
03659 };
03660 
03661 /*! Round robin search locations. */
03662 static struct dahdi_pvt *round_robin[32];
03663 
03664 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03665 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03666 {
03667    int res;
03668    if (p->subs[SUB_REAL].owner == ast)
03669       res = 0;
03670    else if (p->subs[SUB_CALLWAIT].owner == ast)
03671       res = 1;
03672    else if (p->subs[SUB_THREEWAY].owner == ast)
03673       res = 2;
03674    else {
03675       res = -1;
03676       if (!nullok)
03677          ast_log(LOG_WARNING,
03678             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03679             ast ? ast->name : "", p->channel, fname, line);
03680    }
03681    return res;
03682 }
03683 
03684 /*!
03685  * \internal
03686  * \brief Obtain the specified subchannel owner lock if the owner exists.
03687  *
03688  * \param pvt Channel private struct.
03689  * \param sub_idx Subchannel owner to lock.
03690  *
03691  * \note Assumes the pvt->lock is already obtained.
03692  *
03693  * \note
03694  * Because deadlock avoidance may have been necessary, you need to confirm
03695  * the state of things before continuing.
03696  *
03697  * \return Nothing
03698  */
03699 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03700 {
03701    for (;;) {
03702       if (!pvt->subs[sub_idx].owner) {
03703          /* No subchannel owner pointer */
03704          break;
03705       }
03706       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03707          /* Got subchannel owner lock */
03708          break;
03709       }
03710       /* We must unlock the private to avoid the possibility of a deadlock */
03711       DEADLOCK_AVOIDANCE(&pvt->lock);
03712    }
03713 }
03714 
03715 static void wakeup_sub(struct dahdi_pvt *p, int a)
03716 {
03717    dahdi_lock_sub_owner(p, a);
03718    if (p->subs[a].owner) {
03719       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03720       ast_channel_unlock(p->subs[a].owner);
03721    }
03722 }
03723 
03724 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03725 {
03726    for (;;) {
03727       if (p->owner) {
03728          if (ast_channel_trylock(p->owner)) {
03729             DEADLOCK_AVOIDANCE(&p->lock);
03730          } else {
03731             ast_queue_frame(p->owner, f);
03732             ast_channel_unlock(p->owner);
03733             break;
03734          }
03735       } else
03736          break;
03737    }
03738 }
03739 
03740 static void handle_clear_alarms(struct dahdi_pvt *p)
03741 {
03742    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03743       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03744       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03745    }
03746    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03747       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03748       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03749    }
03750 }
03751 
03752 #ifdef HAVE_OPENR2
03753 
03754 static int dahdi_r2_answer(struct dahdi_pvt *p)
03755 {
03756    int res = 0;
03757    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03758    * and does not has support for openr2_chan_answer_call_with_mode
03759    *  */
03760 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03761    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03762    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03763    if (!double_answer) {
03764       /* this still can result in double answer if the channel context
03765       * was configured that way */
03766       res = openr2_chan_answer_call(p->r2chan);
03767    } else if (wants_double_answer) {
03768       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03769    } else {
03770       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03771    }
03772 #else
03773    res = openr2_chan_answer_call(p->r2chan);
03774 #endif
03775    return res;
03776 }
03777 
03778 
03779 
03780 /* should be called with the ast_channel locked */
03781 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03782 {
03783    openr2_calling_party_category_t cat;
03784    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03785    struct dahdi_pvt *p = c->tech_pvt;
03786    if (ast_strlen_zero(catstr)) {
03787       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03788             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03789       return p->mfcr2_category;
03790    }
03791    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03792       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03793             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03794       return p->mfcr2_category;
03795    }
03796    ast_debug(1, "Using category %s\n", catstr);
03797    return cat;
03798 }
03799 
03800 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03801 {
03802    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03803    ast_mutex_lock(&p->lock);
03804    if (p->mfcr2call) {
03805       ast_mutex_unlock(&p->lock);
03806       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03807          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03808          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03809          the other end will see our seize as a forced release and drop the call, we will see an invalid
03810          pattern that will be seen and treated as protocol error. */
03811       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03812       return;
03813    }
03814    p->mfcr2call = 1;
03815    /* better safe than sorry ... */
03816    p->cid_name[0] = '\0';
03817    p->cid_num[0] = '\0';
03818    p->cid_subaddr[0] = '\0';
03819    p->rdnis[0] = '\0';
03820    p->exten[0] = '\0';
03821    p->mfcr2_ani_index = '\0';
03822    p->mfcr2_dnis_index = '\0';
03823    p->mfcr2_dnis_matched = 0;
03824    p->mfcr2_answer_pending = 0;
03825    p->mfcr2_call_accepted = 0;
03826    ast_mutex_unlock(&p->lock);
03827    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03828 }
03829 
03830 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03831 {
03832    int res;
03833    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03834    ast_mutex_lock(&p->lock);
03835    p->inalarm = alarm ? 1 : 0;
03836    if (p->inalarm) {
03837       res = get_alarms(p);
03838       handle_alarms(p, res);
03839    } else {
03840       handle_clear_alarms(p);
03841    }
03842    ast_mutex_unlock(&p->lock);
03843 }
03844 
03845 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03846 {
03847    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03848 }
03849 
03850 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03851 {
03852    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03853    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03854    if (p->owner) {
03855       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03856       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03857    }
03858    ast_mutex_lock(&p->lock);
03859    p->mfcr2call = 0;
03860    ast_mutex_unlock(&p->lock);
03861 }
03862 
03863 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03864 {
03865    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03866       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03867          p->channel, openr2_proto_get_disconnect_string(cause));
03868       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03869       openr2_chan_set_idle(p->r2chan);
03870       ast_mutex_lock(&p->lock);
03871       p->mfcr2call = 0;
03872       ast_mutex_unlock(&p->lock);
03873    }
03874 }
03875 
03876 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03877 {
03878    struct dahdi_pvt *p;
03879    struct ast_channel *c;
03880    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03881          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03882          openr2_proto_get_category_string(category));
03883    p = openr2_chan_get_client_data(r2chan);
03884    /* if collect calls are not allowed and this is a collect call, reject it! */
03885    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03886       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03887       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03888       return;
03889    }
03890    ast_mutex_lock(&p->lock);
03891    p->mfcr2_recvd_category = category;
03892    /* if we're not supposed to use CID, clear whatever we have */
03893    if (!p->use_callerid) {
03894       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03895       p->cid_num[0] = 0;
03896       p->cid_name[0] = 0;
03897    }
03898    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03899    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03900       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03901       p->exten[0] = 's';
03902       p->exten[1] = 0;
03903    }
03904    ast_mutex_unlock(&p->lock);
03905    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03906       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03907             p->channel, p->exten, p->context);
03908       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03909       return;
03910    }
03911    if (!p->mfcr2_accept_on_offer) {
03912       /* The user wants us to start the PBX thread right away without accepting the call first */
03913       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03914       if (c) {
03915          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03916             the call or reject it and detect the tone off condition of the other end, all of this
03917             will be done in the PBX thread now */
03918          return;
03919       }
03920       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03921       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03922    } else if (p->mfcr2_charge_calls) {
03923       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03924       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03925    } else {
03926       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03927       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03928    }
03929 }
03930 
03931 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03932 {
03933    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03934    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03935    ast_mutex_lock(&p->lock);
03936    p->mfcr2call = 0;
03937    ast_mutex_unlock(&p->lock);
03938 }
03939 
03940 static void dahdi_enable_ec(struct dahdi_pvt *p);
03941 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03942 {
03943    struct dahdi_pvt *p = NULL;
03944    struct ast_channel *c = NULL;
03945    p = openr2_chan_get_client_data(r2chan);
03946    dahdi_enable_ec(p);
03947    p->mfcr2_call_accepted = 1;
03948    /* if it's an incoming call ... */
03949    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03950       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03951       /* If accept on offer is not set, it means at this point the PBX thread is already
03952          launched (was launched in the 'on call offered' handler) and therefore this callback
03953          is being executed already in the PBX thread rather than the monitor thread, don't launch
03954          any other thread, just disable the openr2 reading and answer the call if needed */
03955       if (!p->mfcr2_accept_on_offer) {
03956          openr2_chan_disable_read(r2chan);
03957          if (p->mfcr2_answer_pending) {
03958             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03959             dahdi_r2_answer(p);
03960          }
03961          return;
03962       }
03963       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03964       if (c) {
03965          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03966             library to forget about it */
03967          openr2_chan_disable_read(r2chan);
03968          return;
03969       }
03970       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03971       /* failed to create the channel, bail out and report it as an out of order line */
03972       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03973       return;
03974    }
03975    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03976    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03977    p->subs[SUB_REAL].needringing = 1;
03978    p->dialing = 0;
03979    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
03980    openr2_chan_disable_read(r2chan);
03981 }
03982 
03983 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03984 {
03985    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03986    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03987    p->subs[SUB_REAL].needanswer = 1;
03988 }
03989 
03990 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03991 {
03992    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
03993 }
03994 
03995 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03996 {
03997    switch (cause) {
03998    case OR2_CAUSE_BUSY_NUMBER:
03999       return AST_CAUSE_BUSY;
04000    case OR2_CAUSE_NETWORK_CONGESTION:
04001       return AST_CAUSE_CONGESTION;
04002    case OR2_CAUSE_OUT_OF_ORDER:
04003       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04004    case OR2_CAUSE_UNALLOCATED_NUMBER:
04005       return AST_CAUSE_UNREGISTERED;
04006    case OR2_CAUSE_NO_ANSWER:
04007       return AST_CAUSE_NO_ANSWER;
04008    case OR2_CAUSE_NORMAL_CLEARING:
04009       return AST_CAUSE_NORMAL_CLEARING;
04010    case OR2_CAUSE_UNSPECIFIED:
04011    default:
04012       return AST_CAUSE_NOTDEFINED;
04013    }
04014 }
04015 
04016 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04017 {
04018    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04019    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04020    ast_mutex_lock(&p->lock);
04021    if (!p->owner) {
04022       ast_mutex_unlock(&p->lock);
04023       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04024       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04025       return;
04026    }
04027    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04028       be done in dahdi_hangup */
04029    if (p->owner->_state == AST_STATE_UP) {
04030       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04031       ast_mutex_unlock(&p->lock);
04032    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04033       /* being the forward side we must report what happened to the call to whoever requested it */
04034       switch (cause) {
04035       case OR2_CAUSE_BUSY_NUMBER:
04036          p->subs[SUB_REAL].needbusy = 1;
04037          break;
04038       case OR2_CAUSE_NETWORK_CONGESTION:
04039       case OR2_CAUSE_OUT_OF_ORDER:
04040       case OR2_CAUSE_UNALLOCATED_NUMBER:
04041       case OR2_CAUSE_NO_ANSWER:
04042       case OR2_CAUSE_UNSPECIFIED:
04043       case OR2_CAUSE_NORMAL_CLEARING:
04044          p->subs[SUB_REAL].needcongestion = 1;
04045          break;
04046       default:
04047          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04048       }
04049       ast_mutex_unlock(&p->lock);
04050    } else {
04051       ast_mutex_unlock(&p->lock);
04052       /* being the backward side and not UP yet, we only need to request hangup */
04053       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04054       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04055    }
04056 }
04057 
04058 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04059 {
04060    switch (level) {
04061    case OR2_LOG_NOTICE:
04062       ast_verbose("%s", logmessage);
04063       break;
04064    case OR2_LOG_WARNING:
04065       ast_log(LOG_WARNING, "%s", logmessage);
04066       break;
04067    case OR2_LOG_ERROR:
04068       ast_log(LOG_ERROR, "%s", logmessage);
04069       break;
04070    case OR2_LOG_STACK_TRACE:
04071    case OR2_LOG_MF_TRACE:
04072    case OR2_LOG_CAS_TRACE:
04073    case OR2_LOG_DEBUG:
04074    case OR2_LOG_EX_DEBUG:
04075       ast_log(LOG_DEBUG, "%s", logmessage);
04076       break;
04077    default:
04078       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04079       ast_log(LOG_DEBUG, "%s", logmessage);
04080       break;
04081    }
04082 }
04083 
04084 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04085 {
04086    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04087    ast_mutex_lock(&p->lock);
04088    p->remotelyblocked = 1;
04089    ast_mutex_unlock(&p->lock);
04090    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04091 }
04092 
04093 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04094 {
04095    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04096    ast_mutex_lock(&p->lock);
04097    p->remotelyblocked = 0;
04098    ast_mutex_unlock(&p->lock);
04099    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04100 }
04101 
04102 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04103    __attribute__((format (printf, 3, 0)));
04104 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04105 {
04106 #define CONTEXT_TAG "Context - "
04107    char logmsg[256];
04108    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04109    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04110    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04111    dahdi_r2_write_log(level, completemsg);
04112 #undef CONTEXT_TAG
04113 }
04114 
04115 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04116    __attribute__((format (printf, 3, 0)));
04117 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04118 {
04119 #define CHAN_TAG "Chan "
04120    char logmsg[256];
04121    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04122    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04123    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04124    dahdi_r2_write_log(level, completemsg);
04125 }
04126 
04127 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04128 {
04129    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04130    /* if 'immediate' is set, let's stop requesting DNIS */
04131    if (p->immediate) {
04132       return 0;
04133    }
04134    p->exten[p->mfcr2_dnis_index] = digit;
04135    p->rdnis[p->mfcr2_dnis_index] = digit;
04136    p->mfcr2_dnis_index++;
04137    p->exten[p->mfcr2_dnis_index] = 0;
04138    p->rdnis[p->mfcr2_dnis_index] = 0;
04139    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04140    if ((p->mfcr2_dnis_matched ||
04141        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04142        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04143       return 0;
04144    }
04145    /* otherwise keep going */
04146    return 1;
04147 }
04148 
04149 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04150 {
04151    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04152    p->cid_num[p->mfcr2_ani_index] = digit;
04153    p->cid_name[p->mfcr2_ani_index] = digit;
04154    p->mfcr2_ani_index++;
04155    p->cid_num[p->mfcr2_ani_index] = 0;
04156    p->cid_name[p->mfcr2_ani_index] = 0;
04157 }
04158 
04159 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04160 {
04161    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04162 }
04163 
04164 static openr2_event_interface_t dahdi_r2_event_iface = {
04165    .on_call_init = dahdi_r2_on_call_init,
04166    .on_call_offered = dahdi_r2_on_call_offered,
04167    .on_call_accepted = dahdi_r2_on_call_accepted,
04168    .on_call_answered = dahdi_r2_on_call_answered,
04169    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04170    .on_call_end = dahdi_r2_on_call_end,
04171    .on_call_read = dahdi_r2_on_call_read,
04172    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04173    .on_os_error = dahdi_r2_on_os_error,
04174    .on_protocol_error = dahdi_r2_on_protocol_error,
04175    .on_line_blocked = dahdi_r2_on_line_blocked,
04176    .on_line_idle = dahdi_r2_on_line_idle,
04177    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04178    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04179    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04180    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04181    /* so far we do nothing with billing pulses */
04182    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04183 };
04184 
04185 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04186 {
04187    return AST_ALAW(sample);
04188 }
04189 
04190 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04191 {
04192    return AST_LIN2A(sample);
04193 }
04194 
04195 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04196    dahdi_r2_alaw_to_linear,
04197    dahdi_r2_linear_to_alaw
04198 };
04199 
04200 #endif /* HAVE_OPENR2 */
04201 
04202 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04203 {
04204    int tchan;
04205    int tinthreeway;
04206    struct ast_channel *towner;
04207 
04208    ast_debug(1, "Swapping %d and %d\n", a, b);
04209 
04210    tchan = p->subs[a].chan;
04211    towner = p->subs[a].owner;
04212    tinthreeway = p->subs[a].inthreeway;
04213 
04214    p->subs[a].chan = p->subs[b].chan;
04215    p->subs[a].owner = p->subs[b].owner;
04216    p->subs[a].inthreeway = p->subs[b].inthreeway;
04217 
04218    p->subs[b].chan = tchan;
04219    p->subs[b].owner = towner;
04220    p->subs[b].inthreeway = tinthreeway;
04221 
04222    if (p->subs[a].owner)
04223       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04224    if (p->subs[b].owner)
04225       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04226    wakeup_sub(p, a);
04227    wakeup_sub(p, b);
04228 }
04229 
04230 static int dahdi_open(char *fn)
04231 {
04232    int fd;
04233    int isnum;
04234    int chan = 0;
04235    int bs;
04236    int x;
04237    isnum = 1;
04238    for (x = 0; x < strlen(fn); x++) {
04239       if (!isdigit(fn[x])) {
04240          isnum = 0;
04241          break;
04242       }
04243    }
04244    if (isnum) {
04245       chan = atoi(fn);
04246       if (chan < 1) {
04247          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04248          return -1;
04249       }
04250       fn = "/dev/dahdi/channel";
04251    }
04252    fd = open(fn, O_RDWR | O_NONBLOCK);
04253    if (fd < 0) {
04254       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04255       return -1;
04256    }
04257    if (chan) {
04258       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04259          x = errno;
04260          close(fd);
04261          errno = x;
04262          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04263          return -1;
04264       }
04265    }
04266    bs = READ_SIZE;
04267    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04268       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04269       x = errno;
04270       close(fd);
04271       errno = x;
04272       return -1;
04273    }
04274    return fd;
04275 }
04276 
04277 static void dahdi_close(int fd)
04278 {
04279    if (fd > 0)
04280       close(fd);
04281 }
04282 
04283 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04284 {
04285    dahdi_close(chan_pvt->subs[sub_num].dfd);
04286    chan_pvt->subs[sub_num].dfd = -1;
04287 }
04288 
04289 #if defined(HAVE_PRI)
04290 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04291 {
04292    dahdi_close(pri->pri.fds[fd_num]);
04293    pri->pri.fds[fd_num] = -1;
04294 }
04295 #endif   /* defined(HAVE_PRI) */
04296 
04297 #if defined(HAVE_SS7)
04298 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04299 {
04300    dahdi_close(ss7->ss7.fds[fd_num]);
04301    ss7->ss7.fds[fd_num] = -1;
04302 }
04303 #endif   /* defined(HAVE_SS7) */
04304 
04305 static int dahdi_setlinear(int dfd, int linear)
04306 {
04307    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04308 }
04309 
04310 
04311 static int alloc_sub(struct dahdi_pvt *p, int x)
04312 {
04313    struct dahdi_bufferinfo bi;
04314    int res;
04315    if (p->subs[x].dfd >= 0) {
04316       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04317       return -1;
04318    }
04319 
04320    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04321    if (p->subs[x].dfd <= -1) {
04322       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04323       return -1;
04324    }
04325 
04326    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04327    if (!res) {
04328       bi.txbufpolicy = p->buf_policy;
04329       bi.rxbufpolicy = p->buf_policy;
04330       bi.numbufs = p->buf_no;
04331       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04332       if (res < 0) {
04333          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04334       }
04335    } else
04336       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04337 
04338    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04339       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04340       dahdi_close_sub(p, x);
04341       p->subs[x].dfd = -1;
04342       return -1;
04343    }
04344    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04345    return 0;
04346 }
04347 
04348 static int unalloc_sub(struct dahdi_pvt *p, int x)
04349 {
04350    if (!x) {
04351       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04352       return -1;
04353    }
04354    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04355    dahdi_close_sub(p, x);
04356    p->subs[x].linear = 0;
04357    p->subs[x].chan = 0;
04358    p->subs[x].owner = NULL;
04359    p->subs[x].inthreeway = 0;
04360    p->polarity = POLARITY_IDLE;
04361    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04362    return 0;
04363 }
04364 
04365 static int digit_to_dtmfindex(char digit)
04366 {
04367    if (isdigit(digit))
04368       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04369    else if (digit >= 'A' && digit <= 'D')
04370       return DAHDI_TONE_DTMF_A + (digit - 'A');
04371    else if (digit >= 'a' && digit <= 'd')
04372       return DAHDI_TONE_DTMF_A + (digit - 'a');
04373    else if (digit == '*')
04374       return DAHDI_TONE_DTMF_s;
04375    else if (digit == '#')
04376       return DAHDI_TONE_DTMF_p;
04377    else
04378       return -1;
04379 }
04380 
04381 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04382 {
04383    struct dahdi_pvt *pvt;
04384    int idx;
04385    int dtmf = -1;
04386    int res;
04387 
04388    pvt = chan->tech_pvt;
04389 
04390    ast_mutex_lock(&pvt->lock);
04391 
04392    idx = dahdi_get_index(chan, pvt, 0);
04393 
04394    if ((idx != SUB_REAL) || !pvt->owner)
04395       goto out;
04396 
04397 #ifdef HAVE_PRI
04398    switch (pvt->sig) {
04399    case SIG_PRI_LIB_HANDLE_CASES:
04400       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04401       if (!res)
04402          goto out;
04403       break;
04404    default:
04405       break;
04406    }
04407 #endif
04408    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04409       goto out;
04410 
04411    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04412       struct dahdi_dialoperation zo = {
04413          .op = DAHDI_DIAL_OP_APPEND,
04414       };
04415 
04416       zo.dialstr[0] = 'T';
04417       zo.dialstr[1] = digit;
04418       zo.dialstr[2] = '\0';
04419       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04420          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04421       else
04422          pvt->dialing = 1;
04423    } else {
04424       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04425       pvt->dialing = 1;
04426       pvt->begindigit = digit;
04427    }
04428 
04429 out:
04430    ast_mutex_unlock(&pvt->lock);
04431 
04432    return 0;
04433 }
04434 
04435 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04436 {
04437    struct dahdi_pvt *pvt;
04438    int res = 0;
04439    int idx;
04440    int x;
04441 
04442    pvt = chan->tech_pvt;
04443 
04444    ast_mutex_lock(&pvt->lock);
04445 
04446    idx = dahdi_get_index(chan, pvt, 0);
04447 
04448    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04449       goto out;
04450 
04451 #ifdef HAVE_PRI
04452    /* This means that the digit was already sent via PRI signalling */
04453    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04454       goto out;
04455    }
04456 #endif
04457 
04458    if (pvt->begindigit) {
04459       x = -1;
04460       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04461       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04462       pvt->dialing = 0;
04463       pvt->begindigit = 0;
04464    }
04465 
04466 out:
04467    ast_mutex_unlock(&pvt->lock);
04468 
04469    return res;
04470 }
04471 
04472 static const char * const events[] = {
04473    "No event",
04474    "On hook",
04475    "Ring/Answered",
04476    "Wink/Flash",
04477    "Alarm",
04478    "No more alarm",
04479    "HDLC Abort",
04480    "HDLC Overrun",
04481    "HDLC Bad FCS",
04482    "Dial Complete",
04483    "Ringer On",
04484    "Ringer Off",
04485    "Hook Transition Complete",
04486    "Bits Changed",
04487    "Pulse Start",
04488    "Timer Expired",
04489    "Timer Ping",
04490    "Polarity Reversal",
04491    "Ring Begin",
04492 };
04493 
04494 static struct {
04495    int alarm;
04496    char *name;
04497 } alarms[] = {
04498    { DAHDI_ALARM_RED, "Red Alarm" },
04499    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04500    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04501    { DAHDI_ALARM_RECOVER, "Recovering" },
04502    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04503    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04504    { DAHDI_ALARM_NONE, "None" },
04505 };
04506 
04507 static char *alarm2str(int alm)
04508 {
04509    int x;
04510    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04511       if (alarms[x].alarm & alm)
04512          return alarms[x].name;
04513    }
04514    return alm ? "Unknown Alarm" : "No Alarm";
04515 }
04516 
04517 static const char *event2str(int event)
04518 {
04519    static char buf[256];
04520    if ((event < (ARRAY_LEN(events))) && (event > -1))
04521       return events[event];
04522    sprintf(buf, "Event %d", event); /* safe */
04523    return buf;
04524 }
04525 
04526 static char *dahdi_sig2str(int sig)
04527 {
04528    static char buf[256];
04529    switch (sig) {
04530    case SIG_EM:
04531       return "E & M Immediate";
04532    case SIG_EMWINK:
04533       return "E & M Wink";
04534    case SIG_EM_E1:
04535       return "E & M E1";
04536    case SIG_FEATD:
04537       return "Feature Group D (DTMF)";
04538    case SIG_FEATDMF:
04539       return "Feature Group D (MF)";
04540    case SIG_FEATDMF_TA:
04541       return "Feature Groud D (MF) Tandem Access";
04542    case SIG_FEATB:
04543       return "Feature Group B (MF)";
04544    case SIG_E911:
04545       return "E911 (MF)";
04546    case SIG_FGC_CAMA:
04547       return "FGC/CAMA (Dialpulse)";
04548    case SIG_FGC_CAMAMF:
04549       return "FGC/CAMA (MF)";
04550    case SIG_FXSLS:
04551       return "FXS Loopstart";
04552    case SIG_FXSGS:
04553       return "FXS Groundstart";
04554    case SIG_FXSKS:
04555       return "FXS Kewlstart";
04556    case SIG_FXOLS:
04557       return "FXO Loopstart";
04558    case SIG_FXOGS:
04559       return "FXO Groundstart";
04560    case SIG_FXOKS:
04561       return "FXO Kewlstart";
04562    case SIG_PRI:
04563       return "ISDN PRI";
04564    case SIG_BRI:
04565       return "ISDN BRI Point to Point";
04566    case SIG_BRI_PTMP:
04567       return "ISDN BRI Point to MultiPoint";
04568    case SIG_SS7:
04569       return "SS7";
04570    case SIG_MFCR2:
04571       return "MFC/R2";
04572    case SIG_SF:
04573       return "SF (Tone) Immediate";
04574    case SIG_SFWINK:
04575       return "SF (Tone) Wink";
04576    case SIG_SF_FEATD:
04577       return "SF (Tone) with Feature Group D (DTMF)";
04578    case SIG_SF_FEATDMF:
04579       return "SF (Tone) with Feature Group D (MF)";
04580    case SIG_SF_FEATB:
04581       return "SF (Tone) with Feature Group B (MF)";
04582    case 0:
04583       return "Pseudo";
04584    default:
04585       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04586       return buf;
04587    }
04588 }
04589 
04590 #define sig2str dahdi_sig2str
04591 
04592 static int analog_lib_handles(int signalling, int radio, int oprmode)
04593 {
04594    switch (signalling) {
04595    case SIG_FXOLS:
04596    case SIG_FXOGS:
04597    case SIG_FXOKS:
04598    case SIG_FXSLS:
04599    case SIG_FXSGS:
04600    case SIG_FXSKS:
04601    case SIG_EMWINK:
04602    case SIG_EM:
04603    case SIG_EM_E1:
04604    case SIG_FEATD:
04605    case SIG_FEATDMF:
04606    case SIG_E911:
04607    case SIG_FGC_CAMA:
04608    case SIG_FGC_CAMAMF:
04609    case SIG_FEATB:
04610    case SIG_SFWINK:
04611    case SIG_SF:
04612    case SIG_SF_FEATD:
04613    case SIG_SF_FEATDMF:
04614    case SIG_FEATDMF_TA:
04615    case SIG_SF_FEATB:
04616       break;
04617    default:
04618       /* The rest of the function should cover the remainder of signalling types */
04619       return 0;
04620    }
04621 
04622    if (radio)
04623       return 0;
04624 
04625    if (oprmode)
04626       return 0;
04627 
04628    return 1;
04629 }
04630 
04631 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04632 {
04633    /* If the conference already exists, and we're already in it
04634       don't bother doing anything */
04635    struct dahdi_confinfo zi;
04636 
04637    memset(&zi, 0, sizeof(zi));
04638    zi.chan = 0;
04639 
04640    if (slavechannel > 0) {
04641       /* If we have only one slave, do a digital mon */
04642       zi.confmode = DAHDI_CONF_DIGITALMON;
04643       zi.confno = slavechannel;
04644    } else {
04645       if (!idx) {
04646          /* Real-side and pseudo-side both participate in conference */
04647          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04648             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04649       } else
04650          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04651       zi.confno = p->confno;
04652    }
04653    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04654       return 0;
04655    if (c->dfd < 0)
04656       return 0;
04657    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04658       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04659       return -1;
04660    }
04661    if (slavechannel < 1) {
04662       p->confno = zi.confno;
04663    }
04664    c->curconf = zi;
04665    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04666    return 0;
04667 }
04668 
04669 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04670 {
04671    /* If they're listening to our channel, they're ours */
04672    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04673       return 1;
04674    /* If they're a talker on our (allocated) conference, they're ours */
04675    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04676       return 1;
04677    return 0;
04678 }
04679 
04680 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04681 {
04682    struct dahdi_confinfo zi;
04683    if (/* Can't delete if there's no dfd */
04684       (c->dfd < 0) ||
04685       /* Don't delete from the conference if it's not our conference */
04686       !isourconf(p, c)
04687       /* Don't delete if we don't think it's conferenced at all (implied) */
04688       ) return 0;
04689    memset(&zi, 0, sizeof(zi));
04690    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04691       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04692       return -1;
04693    }
04694    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04695    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04696    return 0;
04697 }
04698 
04699 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04700 {
04701    int x;
04702    int useslavenative;
04703    struct dahdi_pvt *slave = NULL;
04704    /* Start out optimistic */
04705    useslavenative = 1;
04706    /* Update conference state in a stateless fashion */
04707    for (x = 0; x < 3; x++) {
04708       /* Any three-way calling makes slave native mode *definitely* out
04709          of the question */
04710       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04711          useslavenative = 0;
04712    }
04713    /* If we don't have any 3-way calls, check to see if we have
04714       precisely one slave */
04715    if (useslavenative) {
04716       for (x = 0; x < MAX_SLAVES; x++) {
04717          if (p->slaves[x]) {
04718             if (slave) {
04719                /* Whoops already have a slave!  No
04720                   slave native and stop right away */
04721                slave = NULL;
04722                useslavenative = 0;
04723                break;
04724             } else {
04725                /* We have one slave so far */
04726                slave = p->slaves[x];
04727             }
04728          }
04729       }
04730    }
04731    /* If no slave, slave native definitely out */
04732    if (!slave)
04733       useslavenative = 0;
04734    else if (slave->law != p->law) {
04735       useslavenative = 0;
04736       slave = NULL;
04737    }
04738    if (out)
04739       *out = slave;
04740    return useslavenative;
04741 }
04742 
04743 static int reset_conf(struct dahdi_pvt *p)
04744 {
04745    p->confno = -1;
04746    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04747    if (p->subs[SUB_REAL].dfd > -1) {
04748       struct dahdi_confinfo zi;
04749 
04750       memset(&zi, 0, sizeof(zi));
04751       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04752          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04753    }
04754    return 0;
04755 }
04756 
04757 static int update_conf(struct dahdi_pvt *p)
04758 {
04759    int needconf = 0;
04760    int x;
04761    int useslavenative;
04762    struct dahdi_pvt *slave = NULL;
04763 
04764    useslavenative = isslavenative(p, &slave);
04765    /* Start with the obvious, general stuff */
04766    for (x = 0; x < 3; x++) {
04767       /* Look for three way calls */
04768       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04769          conf_add(p, &p->subs[x], x, 0);
04770          needconf++;
04771       } else {
04772          conf_del(p, &p->subs[x], x);
04773       }
04774    }
04775    /* If we have a slave, add him to our conference now. or DAX
04776       if this is slave native */
04777    for (x = 0; x < MAX_SLAVES; x++) {
04778       if (p->slaves[x]) {
04779          if (useslavenative)
04780             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04781          else {
04782             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04783             needconf++;
04784          }
04785       }
04786    }
04787    /* If we're supposed to be in there, do so now */
04788    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04789       if (useslavenative)
04790          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04791       else {
04792          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04793          needconf++;
04794       }
04795    }
04796    /* If we have a master, add ourselves to his conference */
04797    if (p->master) {
04798       if (isslavenative(p->master, NULL)) {
04799          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04800       } else {
04801          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04802       }
04803    }
04804    if (!needconf) {
04805       /* Nobody is left (or should be left) in our conference.
04806          Kill it. */
04807       p->confno = -1;
04808    }
04809    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04810    return 0;
04811 }
04812 
04813 static void dahdi_enable_ec(struct dahdi_pvt *p)
04814 {
04815    int res;
04816    if (!p)
04817       return;
04818    if (p->echocanon) {
04819       ast_debug(1, "Echo cancellation already on\n");
04820       return;
04821    }
04822    if (p->digital) {
04823       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04824       return;
04825    }
04826    if (p->echocancel.head.tap_length) {
04827 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04828       switch (p->sig) {
04829 #if defined(HAVE_PRI)
04830       case SIG_PRI_LIB_HANDLE_CASES:
04831          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04832             /*
04833              * PRI nobch pseudo channel.  Does not need ec anyway.
04834              * Does not handle ioctl(DAHDI_AUDIOMODE)
04835              */
04836             return;
04837          }
04838          /* Fall through */
04839 #endif   /* defined(HAVE_PRI) */
04840 #if defined(HAVE_SS7)
04841       case SIG_SS7:
04842 #endif   /* defined(HAVE_SS7) */
04843          {
04844             int x = 1;
04845 
04846             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04847             if (res)
04848                ast_log(LOG_WARNING,
04849                   "Unable to enable audio mode on channel %d (%s)\n",
04850                   p->channel, strerror(errno));
04851          }
04852          break;
04853       default:
04854          break;
04855       }
04856 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04857       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04858       if (res) {
04859          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04860       } else {
04861          p->echocanon = 1;
04862          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04863       }
04864    } else
04865       ast_debug(1, "No echo cancellation requested\n");
04866 }
04867 
04868 static void dahdi_train_ec(struct dahdi_pvt *p)
04869 {
04870    int x;
04871    int res;
04872 
04873    if (p && p->echocanon && p->echotraining) {
04874       x = p->echotraining;
04875       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04876       if (res)
04877          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04878       else
04879          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04880    } else {
04881       ast_debug(1, "No echo training requested\n");
04882    }
04883 }
04884 
04885 static void dahdi_disable_ec(struct dahdi_pvt *p)
04886 {
04887    int res;
04888 
04889    if (p->echocanon) {
04890       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04891 
04892       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04893 
04894       if (res)
04895          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04896       else
04897          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04898    }
04899 
04900    p->echocanon = 0;
04901 }
04902 
04903 /* perform a dynamic range compression transform on the given sample */
04904 static int drc_sample(int sample, float drc)
04905 {
04906    float neg;
04907    float shallow, steep;
04908    float max = SHRT_MAX;
04909    
04910    neg = (sample < 0 ? -1 : 1);
04911    steep = drc*sample;
04912    shallow = neg*(max-max/drc)+(float)sample/drc;
04913    if (abs(steep) < abs(shallow)) {
04914       sample = steep;
04915    }
04916    else {
04917       sample = shallow;
04918    }
04919 
04920    return sample;
04921 }
04922 
04923 
04924 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04925 {
04926    int j;
04927    int k;
04928 
04929    float linear_gain = pow(10.0, gain / 20.0);
04930 
04931    switch (law) {
04932    case DAHDI_LAW_ALAW:
04933       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04934          if (gain || drc) {
04935             k = AST_ALAW(j);
04936             if (drc) {
04937                k = drc_sample(k, drc);
04938             }
04939             k = (float)k*linear_gain;
04940             if (k > 32767) k = 32767;
04941             if (k < -32767) k = -32767;
04942             g->txgain[j] = AST_LIN2A(k);
04943          } else {
04944             g->txgain[j] = j;
04945          }
04946       }
04947       break;
04948    case DAHDI_LAW_MULAW:
04949       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04950          if (gain || drc) {
04951             k = AST_MULAW(j);
04952             if (drc) {
04953                k = drc_sample(k, drc);
04954             }
04955             k = (float)k*linear_gain;
04956             if (k > 32767) k = 32767;
04957             if (k < -32767) k = -32767;
04958             g->txgain[j] = AST_LIN2MU(k);
04959 
04960          } else {
04961             g->txgain[j] = j;
04962          }
04963       }
04964       break;
04965    }
04966 }
04967 
04968 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04969 {
04970    int j;
04971    int k;
04972    float linear_gain = pow(10.0, gain / 20.0);
04973 
04974    switch (law) {
04975    case DAHDI_LAW_ALAW:
04976       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04977          if (gain || drc) {
04978             k = AST_ALAW(j);
04979             if (drc) {
04980                k = drc_sample(k, drc);
04981             }
04982             k = (float)k*linear_gain;
04983             if (k > 32767) k = 32767;
04984             if (k < -32767) k = -32767;
04985             g->rxgain[j] = AST_LIN2A(k);
04986          } else {
04987             g->rxgain[j] = j;
04988          }
04989       }
04990       break;
04991    case DAHDI_LAW_MULAW:
04992       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04993          if (gain || drc) {
04994             k = AST_MULAW(j);
04995             if (drc) {
04996                k = drc_sample(k, drc);
04997             }
04998             k = (float)k*linear_gain;
04999             if (k > 32767) k = 32767;
05000             if (k < -32767) k = -32767;
05001             g->rxgain[j] = AST_LIN2MU(k);
05002          } else {
05003             g->rxgain[j] = j;
05004          }
05005       }
05006       break;
05007    }
05008 }
05009 
05010 static int set_actual_txgain(int fd, float gain, float drc, int law)
05011 {
05012    struct dahdi_gains g;
05013    int res;
05014 
05015    memset(&g, 0, sizeof(g));
05016    res = ioctl(fd, DAHDI_GETGAINS, &g);
05017    if (res) {
05018       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05019       return res;
05020    }
05021 
05022    fill_txgain(&g, gain, drc, law);
05023 
05024    return ioctl(fd, DAHDI_SETGAINS, &g);
05025 }
05026 
05027 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05028 {
05029    struct dahdi_gains g;
05030    int res;
05031 
05032    memset(&g, 0, sizeof(g));
05033    res = ioctl(fd, DAHDI_GETGAINS, &g);
05034    if (res) {
05035       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05036       return res;
05037    }
05038 
05039    fill_rxgain(&g, gain, drc, law);
05040 
05041    return ioctl(fd, DAHDI_SETGAINS, &g);
05042 }
05043 
05044 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05045 {
05046    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05047 }
05048 
05049 static int bump_gains(struct dahdi_pvt *p)
05050 {
05051    int res;
05052 
05053    /* Bump receive gain by value stored in cid_rxgain */
05054    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05055    if (res) {
05056       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05057       return -1;
05058    }
05059 
05060    return 0;
05061 }
05062 
05063 static int restore_gains(struct dahdi_pvt *p)
05064 {
05065    int res;
05066 
05067    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05068    if (res) {
05069       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05070       return -1;
05071    }
05072 
05073    return 0;
05074 }
05075 
05076 static inline int dahdi_set_hook(int fd, int hs)
05077 {
05078    int x, res;
05079 
05080    x = hs;
05081    res = ioctl(fd, DAHDI_HOOK, &x);
05082 
05083    if (res < 0) {
05084       if (errno == EINPROGRESS)
05085          return 0;
05086       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05087       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05088    }
05089 
05090    return res;
05091 }
05092 
05093 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05094 {
05095    int x, res;
05096 
05097    x = muted;
05098 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05099    switch (p->sig) {
05100 #if defined(HAVE_PRI)
05101    case SIG_PRI_LIB_HANDLE_CASES:
05102       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05103          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05104          break;
05105       }
05106       /* Fall through */
05107 #endif   /* defined(HAVE_PRI) */
05108 #if defined(HAVE_SS7)
05109    case SIG_SS7:
05110 #endif   /* defined(HAVE_SS7) */
05111       {
05112          int y = 1;
05113 
05114          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05115          if (res)
05116             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05117                p->channel, strerror(errno));
05118       }
05119       break;
05120    default:
05121       break;
05122    }
05123 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05124    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05125    if (res < 0)
05126       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05127    return res;
05128 }
05129 
05130 static int save_conference(struct dahdi_pvt *p)
05131 {
05132    struct dahdi_confinfo c;
05133    int res;
05134    if (p->saveconf.confmode) {
05135       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05136       return -1;
05137    }
05138    p->saveconf.chan = 0;
05139    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05140    if (res) {
05141       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05142       p->saveconf.confmode = 0;
05143       return -1;
05144    }
05145    memset(&c, 0, sizeof(c));
05146    c.confmode = DAHDI_CONF_NORMAL;
05147    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05148    if (res) {
05149       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05150       return -1;
05151    }
05152    ast_debug(1, "Disabled conferencing\n");
05153    return 0;
05154 }
05155 
05156 static int restore_conference(struct dahdi_pvt *p)
05157 {
05158    int res;
05159    if (p->saveconf.confmode) {
05160       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05161       p->saveconf.confmode = 0;
05162       if (res) {
05163          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05164          return -1;
05165       }
05166       ast_debug(1, "Restored conferencing\n");
05167    }
05168    return 0;
05169 }
05170 
05171 static int send_cwcidspill(struct dahdi_pvt *p)
05172 {
05173    p->callwaitcas = 0;
05174    p->cidcwexpire = 0;
05175    p->cid_suppress_expire = 0;
05176    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05177       return -1;
05178    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05179    /* Make sure we account for the end */
05180    p->cidlen += READ_SIZE * 4;
05181    p->cidpos = 0;
05182    send_callerid(p);
05183    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05184    return 0;
05185 }
05186 
05187 static int has_voicemail(struct dahdi_pvt *p)
05188 {
05189    int new_msgs;
05190    struct ast_event *event;
05191    char *mailbox, *context;
05192 
05193    mailbox = context = ast_strdupa(p->mailbox);
05194    strsep(&context, "@");
05195    if (ast_strlen_zero(context))
05196       context = "default";
05197 
05198    event = ast_event_get_cached(AST_EVENT_MWI,
05199       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05200       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05201       AST_EVENT_IE_END);
05202 
05203    if (event) {
05204       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05205       ast_event_destroy(event);
05206    } else
05207       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05208 
05209    return new_msgs;
05210 }
05211 
05212 
05213 
05214 static int send_callerid(struct dahdi_pvt *p)
05215 {
05216    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05217    int res;
05218    /* Take out of linear mode if necessary */
05219    if (p->subs[SUB_REAL].linear) {
05220       p->subs[SUB_REAL].linear = 0;
05221       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05222    }
05223    while (p->cidpos < p->cidlen) {
05224       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05225       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05226       if (res < 0) {
05227          if (errno == EAGAIN)
05228             return 0;
05229          else {
05230             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05231             return -1;
05232          }
05233       }
05234       if (!res)
05235          return 0;
05236       p->cidpos += res;
05237    }
05238    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05239    ast_free(p->cidspill);
05240    p->cidspill = NULL;
05241    if (p->callwaitcas) {
05242       /* Wait for CID/CW to expire */
05243       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05244       p->cid_suppress_expire = p->cidcwexpire;
05245    } else
05246       restore_conference(p);
05247    return 0;
05248 }
05249 
05250 static int dahdi_callwait(struct ast_channel *ast)
05251 {
05252    struct dahdi_pvt *p = ast->tech_pvt;
05253    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05254    if (p->cidspill) {
05255       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05256       ast_free(p->cidspill);
05257    }
05258 
05259    /*
05260     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05261     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05262     */
05263    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05264       return -1;
05265    save_conference(p);
05266    /* Silence */
05267    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05268    if (!p->callwaitrings && p->callwaitingcallerid) {
05269       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05270       p->callwaitcas = 1;
05271       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05272    } else {
05273       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05274       p->callwaitcas = 0;
05275       p->cidlen = 2400 + READ_SIZE * 4;
05276    }
05277    p->cidpos = 0;
05278    send_callerid(p);
05279 
05280    return 0;
05281 }
05282 
05283 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05284 {
05285    struct dahdi_pvt *p = ast->tech_pvt;
05286    int x, res, mysig;
05287    char dest[256]; /* must be same length as p->dialdest */
05288 
05289    ast_mutex_lock(&p->lock);
05290    ast_copy_string(dest, rdest, sizeof(dest));
05291    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05292    if ((ast->_state == AST_STATE_BUSY)) {
05293       p->subs[SUB_REAL].needbusy = 1;
05294       ast_mutex_unlock(&p->lock);
05295       return 0;
05296    }
05297    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05298       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05299       ast_mutex_unlock(&p->lock);
05300       return -1;
05301    }
05302    p->waitingfordt.tv_sec = 0;
05303    p->dialednone = 0;
05304    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05305    {
05306       /* Special pseudo -- automatically up */
05307       ast_setstate(ast, AST_STATE_UP);
05308       ast_mutex_unlock(&p->lock);
05309       return 0;
05310    }
05311    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05312    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05313    if (res)
05314       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05315    p->outgoing = 1;
05316 
05317    if (IS_DIGITAL(ast->transfercapability)){
05318       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05319    } else {
05320       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05321    }  
05322 
05323 #ifdef HAVE_PRI
05324    if (dahdi_sig_pri_lib_handles(p->sig)) {
05325       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05326          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05327       ast_mutex_unlock(&p->lock);
05328       return res;
05329    }
05330 #endif
05331 
05332 #if defined(HAVE_SS7)
05333    if (p->sig == SIG_SS7) {
05334       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05335       ast_mutex_unlock(&p->lock);
05336       return res;
05337    }
05338 #endif   /* defined(HAVE_SS7) */
05339 
05340    /* If this is analog signalling we can exit here */
05341    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05342       p->callwaitrings = 0;
05343       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05344       ast_mutex_unlock(&p->lock);
05345       return res;
05346    }
05347 
05348    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05349    switch (mysig) {
05350    case 0:
05351       /* Special pseudo -- automatically up*/
05352       ast_setstate(ast, AST_STATE_UP);
05353       break;
05354    case SIG_MFCR2:
05355       break;
05356    default:
05357       ast_debug(1, "not yet implemented\n");
05358       ast_mutex_unlock(&p->lock);
05359       return -1;
05360    }
05361 
05362 #ifdef HAVE_OPENR2
05363    if (p->mfcr2) {
05364       openr2_calling_party_category_t chancat;
05365       int callres = 0;
05366       char *c, *l;
05367 
05368       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05369       p->dialdest[0] = '\0';
05370 
05371       c = strchr(dest, '/');
05372       if (c) {
05373          c++;
05374       } else {
05375          c = "";
05376       }
05377       if (!p->hidecallerid) {
05378          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05379       } else {
05380          l = NULL;
05381       }
05382       if (strlen(c) < p->stripmsd) {
05383          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05384          ast_mutex_unlock(&p->lock);
05385          return -1;
05386       }
05387       p->dialing = 1;
05388       chancat = dahdi_r2_get_channel_category(ast);
05389       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05390       if (-1 == callres) {
05391          ast_mutex_unlock(&p->lock);
05392          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05393          return -1;
05394       }
05395       p->mfcr2_call_accepted = 0;
05396       p->mfcr2_progress = 0;
05397       ast_setstate(ast, AST_STATE_DIALING);
05398    }
05399 #endif /* HAVE_OPENR2 */
05400    ast_mutex_unlock(&p->lock);
05401    return 0;
05402 }
05403 
05404 /*!
05405  * \internal
05406  * \brief Insert the given chan_dahdi interface structure into the interface list.
05407  * \since 1.8
05408  *
05409  * \param pvt chan_dahdi private interface structure to insert.
05410  *
05411  * \details
05412  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05413  * Any duplicates are inserted after the existing entries.
05414  *
05415  * \note The new interface must not already be in the list.
05416  *
05417  * \return Nothing
05418  */
05419 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05420 {
05421    struct dahdi_pvt *cur;
05422 
05423    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05424 
05425    /* Find place in middle of list for the new interface. */
05426    for (cur = iflist; cur; cur = cur->next) {
05427       if (pvt->channel < cur->channel) {
05428          /* New interface goes before the current interface. */
05429          pvt->prev = cur->prev;
05430          pvt->next = cur;
05431          if (cur->prev) {
05432             /* Insert into the middle of the list. */
05433             cur->prev->next = pvt;
05434          } else {
05435             /* Insert at head of list. */
05436             iflist = pvt;
05437          }
05438          cur->prev = pvt;
05439          return;
05440       }
05441    }
05442 
05443    /* New interface goes onto the end of the list */
05444    pvt->prev = ifend;
05445    pvt->next = NULL;
05446    if (ifend) {
05447       ifend->next = pvt;
05448    }
05449    ifend = pvt;
05450    if (!iflist) {
05451       /* List was empty */
05452       iflist = pvt;
05453    }
05454 }
05455 
05456 /*!
05457  * \internal
05458  * \brief Extract the given chan_dahdi interface structure from the interface list.
05459  * \since 1.8
05460  *
05461  * \param pvt chan_dahdi private interface structure to extract.
05462  *
05463  * \note
05464  * The given interface structure can be either in the interface list or a stand alone
05465  * structure that has not been put in the list if the next and prev pointers are NULL.
05466  *
05467  * \return Nothing
05468  */
05469 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05470 {
05471    /* Extract from the forward chain. */
05472    if (pvt->prev) {
05473       pvt->prev->next = pvt->next;
05474    } else if (iflist == pvt) {
05475       /* Node is at the head of the list. */
05476       iflist = pvt->next;
05477    }
05478 
05479    /* Extract from the reverse chain. */
05480    if (pvt->next) {
05481       pvt->next->prev = pvt->prev;
05482    } else if (ifend == pvt) {
05483       /* Node is at the end of the list. */
05484       ifend = pvt->prev;
05485    }
05486 
05487    /* Node is no longer in the list. */
05488    pvt->which_iflist = DAHDI_IFLIST_NONE;
05489    pvt->prev = NULL;
05490    pvt->next = NULL;
05491 }
05492 
05493 #if defined(HAVE_PRI)
05494 /*!
05495  * \internal
05496  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05497  * \since 1.8
05498  *
05499  * \param pri sig_pri span control structure holding no B channel list.
05500  * \param pvt chan_dahdi private interface structure to insert.
05501  *
05502  * \details
05503  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05504  * Any duplicates are inserted after the existing entries.
05505  *
05506  * \note The new interface must not already be in the list.
05507  *
05508  * \return Nothing
05509  */
05510 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05511 {
05512    struct dahdi_pvt *cur;
05513 
05514    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05515 
05516    /* Find place in middle of list for the new interface. */
05517    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05518       if (pvt->channel < cur->channel) {
05519          /* New interface goes before the current interface. */
05520          pvt->prev = cur->prev;
05521          pvt->next = cur;
05522          if (cur->prev) {
05523             /* Insert into the middle of the list. */
05524             cur->prev->next = pvt;
05525          } else {
05526             /* Insert at head of list. */
05527             pri->no_b_chan_iflist = pvt;
05528          }
05529          cur->prev = pvt;
05530          return;
05531       }
05532    }
05533 
05534    /* New interface goes onto the end of the list */
05535    pvt->prev = pri->no_b_chan_end;
05536    pvt->next = NULL;
05537    if (pri->no_b_chan_end) {
05538       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05539    }
05540    pri->no_b_chan_end = pvt;
05541    if (!pri->no_b_chan_iflist) {
05542       /* List was empty */
05543       pri->no_b_chan_iflist = pvt;
05544    }
05545 }
05546 #endif   /* defined(HAVE_PRI) */
05547 
05548 #if defined(HAVE_PRI)
05549 /*!
05550  * \internal
05551  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05552  * \since 1.8
05553  *
05554  * \param pri sig_pri span control structure holding no B channel list.
05555  * \param pvt chan_dahdi private interface structure to extract.
05556  *
05557  * \note
05558  * The given interface structure can be either in the interface list or a stand alone
05559  * structure that has not been put in the list if the next and prev pointers are NULL.
05560  *
05561  * \return Nothing
05562  */
05563 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05564 {
05565    /* Extract from the forward chain. */
05566    if (pvt->prev) {
05567       pvt->prev->next = pvt->next;
05568    } else if (pri->no_b_chan_iflist == pvt) {
05569       /* Node is at the head of the list. */
05570       pri->no_b_chan_iflist = pvt->next;
05571    }
05572 
05573    /* Extract from the reverse chain. */
05574    if (pvt->next) {
05575       pvt->next->prev = pvt->prev;
05576    } else if (pri->no_b_chan_end == pvt) {
05577       /* Node is at the end of the list. */
05578       pri->no_b_chan_end = pvt->prev;
05579    }
05580 
05581    /* Node is no longer in the list. */
05582    pvt->which_iflist = DAHDI_IFLIST_NONE;
05583    pvt->prev = NULL;
05584    pvt->next = NULL;
05585 }
05586 #endif   /* defined(HAVE_PRI) */
05587 
05588 #if defined(HAVE_PRI)
05589 /*!
05590  * \internal
05591  * \brief Unlink the channel interface from the PRI private pointer array.
05592  * \since 1.8
05593  *
05594  * \param pvt chan_dahdi private interface structure to unlink.
05595  *
05596  * \return Nothing
05597  */
05598 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05599 {
05600    unsigned idx;
05601    struct sig_pri_span *pri;
05602 
05603    pri = pvt->pri;
05604    if (!pri) {
05605       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05606       return;
05607    }
05608    ast_mutex_lock(&pri->lock);
05609    for (idx = 0; idx < pri->numchans; ++idx) {
05610       if (pri->pvts[idx] == pvt->sig_pvt) {
05611          pri->pvts[idx] = NULL;
05612          ast_mutex_unlock(&pri->lock);
05613          return;
05614       }
05615    }
05616    ast_mutex_unlock(&pri->lock);
05617 }
05618 #endif   /* defined(HAVE_PRI) */
05619 
05620 #if defined(HAVE_SS7)
05621 /*!
05622  * \internal
05623  * \brief Unlink the channel interface from the SS7 private pointer array.
05624  * \since 1.8
05625  *
05626  * \param pvt chan_dahdi private interface structure to unlink.
05627  *
05628  * \return Nothing
05629  */
05630 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05631 {
05632    unsigned idx;
05633    struct sig_ss7_linkset *ss7;
05634 
05635    ss7 = pvt->ss7;
05636    if (!ss7) {
05637       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05638       return;
05639    }
05640    ast_mutex_lock(&ss7->lock);
05641    for (idx = 0; idx < ss7->numchans; ++idx) {
05642       if (ss7->pvts[idx] == pvt->sig_pvt) {
05643          ss7->pvts[idx] = NULL;
05644          ast_mutex_unlock(&ss7->lock);
05645          return;
05646       }
05647    }
05648    ast_mutex_unlock(&ss7->lock);
05649 }
05650 #endif   /* defined(HAVE_SS7) */
05651 
05652 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05653 {
05654    if (cur->next && cur->next->span == cur->span) {
05655       return cur->next;
05656    } else if (cur->prev && cur->prev->span == cur->span) {
05657       return cur->prev;
05658    }
05659 
05660    return NULL;
05661 }
05662 
05663 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05664 {
05665    struct dahdi_pvt *p = pvt;
05666 
05667    if (p->manages_span_alarms) {
05668       struct dahdi_pvt *next = find_next_iface_in_span(p);
05669       if (next) {
05670          next->manages_span_alarms = 1;
05671       }
05672    }
05673 
05674    /* Remove channel from the list */
05675 #if defined(HAVE_PRI)
05676    dahdi_unlink_pri_pvt(p);
05677 #endif   /* defined(HAVE_PRI) */
05678 #if defined(HAVE_SS7)
05679    dahdi_unlink_ss7_pvt(p);
05680 #endif   /* defined(HAVE_SS7) */
05681    switch (pvt->which_iflist) {
05682    case DAHDI_IFLIST_NONE:
05683       break;
05684    case DAHDI_IFLIST_MAIN:
05685       dahdi_iflist_extract(p);
05686       break;
05687 #if defined(HAVE_PRI)
05688    case DAHDI_IFLIST_NO_B_CHAN:
05689       if (p->pri) {
05690          dahdi_nobch_extract(p->pri, p);
05691       }
05692       break;
05693 #endif   /* defined(HAVE_PRI) */
05694    }
05695 
05696    if (p->sig_pvt) {
05697       if (analog_lib_handles(p->sig, 0, 0)) {
05698          analog_delete(p->sig_pvt);
05699       }
05700       switch (p->sig) {
05701 #if defined(HAVE_PRI)
05702       case SIG_PRI_LIB_HANDLE_CASES:
05703          sig_pri_chan_delete(p->sig_pvt);
05704          break;
05705 #endif   /* defined(HAVE_PRI) */
05706 #if defined(HAVE_SS7)
05707       case SIG_SS7:
05708          sig_ss7_chan_delete(p->sig_pvt);
05709          break;
05710 #endif   /* defined(HAVE_SS7) */
05711       default:
05712          break;
05713       }
05714    }
05715    ast_free(p->cidspill);
05716    if (p->use_smdi)
05717       ast_smdi_interface_unref(p->smdi_iface);
05718    if (p->mwi_event_sub)
05719       ast_event_unsubscribe(p->mwi_event_sub);
05720    if (p->vars) {
05721       ast_variables_destroy(p->vars);
05722    }
05723    if (p->cc_params) {
05724       ast_cc_config_params_destroy(p->cc_params);
05725    }
05726    ast_mutex_destroy(&p->lock);
05727    dahdi_close_sub(p, SUB_REAL);
05728    if (p->owner)
05729       p->owner->tech_pvt = NULL;
05730    ast_free(p);
05731 }
05732 
05733 static void destroy_channel(struct dahdi_pvt *cur, int now)
05734 {
05735    int i;
05736 
05737    if (!now) {
05738       /* Do not destroy the channel now if it is owned by someone. */
05739       if (cur->owner) {
05740          return;
05741       }
05742       for (i = 0; i < 3; i++) {
05743          if (cur->subs[i].owner) {
05744             return;
05745          }
05746       }
05747    }
05748    destroy_dahdi_pvt(cur);
05749 }
05750 
05751 static void destroy_all_channels(void)
05752 {
05753    int chan;
05754 #if defined(HAVE_PRI)
05755    unsigned span;
05756    struct sig_pri_span *pri;
05757 #endif   /* defined(HAVE_PRI) */
05758    struct dahdi_pvt *p;
05759 
05760    while (num_restart_pending) {
05761       usleep(1);
05762    }
05763 
05764    ast_mutex_lock(&iflock);
05765    /* Destroy all the interfaces and free their memory */
05766    while (iflist) {
05767       p = iflist;
05768 
05769       chan = p->channel;
05770 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05771       {
05772          char db_chan_name[20];
05773          char db_answer[5];
05774          char state;
05775          int why = -1;
05776 
05777          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05778          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05779             sscanf(db_answer, "%1c:%30d", &state, &why);
05780          }
05781          if (!why) {
05782             /* SRVST persistence is not required */
05783             ast_db_del(db_chan_name, SRVST_DBKEY);
05784          }
05785       }
05786 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05787       /* Free associated memory */
05788       destroy_dahdi_pvt(p);
05789       ast_verb(3, "Unregistered channel %d\n", chan);
05790    }
05791    ifcount = 0;
05792    ast_mutex_unlock(&iflock);
05793 
05794 #if defined(HAVE_PRI)
05795    /* Destroy all of the no B channel interface lists */
05796    for (span = 0; span < NUM_SPANS; ++span) {
05797       if (!pris[span].dchannels[0]) {
05798          break;
05799       }
05800       pri = &pris[span].pri;
05801       ast_mutex_lock(&pri->lock);
05802       while (pri->no_b_chan_iflist) {
05803          p = pri->no_b_chan_iflist;
05804 
05805          /* Free associated memory */
05806          destroy_dahdi_pvt(p);
05807       }
05808       ast_mutex_unlock(&pri->lock);
05809    }
05810 #endif   /* defined(HAVE_PRI) */
05811 }
05812 
05813 #if defined(HAVE_PRI)
05814 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05815 
05816 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05817 {
05818    /* Data will be our digit string */
05819    struct dahdi_pvt *p;
05820 
05821    if (ast_strlen_zero(digits)) {
05822       ast_debug(1, "No digit string sent to application!\n");
05823       return -1;
05824    }
05825 
05826    p = (struct dahdi_pvt *)chan->tech_pvt;
05827 
05828    if (!p) {
05829       ast_debug(1, "Unable to find technology private\n");
05830       return -1;
05831    }
05832 
05833    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05834 
05835    return 0;
05836 }
05837 #endif   /* defined(HAVE_PRI) */
05838 
05839 #if defined(HAVE_PRI)
05840 #if defined(HAVE_PRI_PROG_W_CAUSE)
05841 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05842 
05843 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05844 {
05845    /* Data will be our digit string */
05846    struct dahdi_pvt *pvt;
05847    char *parse;
05848    int res = -1;
05849    AST_DECLARE_APP_ARGS(args,
05850       AST_APP_ARG(destination);
05851       AST_APP_ARG(original);
05852       AST_APP_ARG(reason);
05853    );
05854 
05855    if (ast_strlen_zero(data)) {
05856       ast_log(LOG_DEBUG, "No data sent to application!\n");
05857       return -1;
05858    }
05859    if (chan->tech != &dahdi_tech) {
05860       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05861       return -1;
05862    }
05863    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05864    if (!pvt) {
05865       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05866       return -1;
05867    }
05868    switch (pvt->sig) {
05869    case SIG_PRI_LIB_HANDLE_CASES:
05870       break;
05871    default:
05872       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05873          chan->name);
05874       return -1;
05875    }
05876 
05877    parse = ast_strdupa(data);
05878    AST_STANDARD_APP_ARGS(args, parse);
05879 
05880    if (ast_strlen_zero(args.destination)) {
05881       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05882       return -1;
05883    }
05884 
05885    if (ast_strlen_zero(args.original)) {
05886       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05887       args.original = NULL;
05888    }
05889 
05890    if (ast_strlen_zero(args.reason)) {
05891       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05892       args.reason = NULL;
05893    }
05894 
05895    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05896       args.original, args.reason);
05897 
05898    return res;
05899 }
05900 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05901 #endif   /* defined(HAVE_PRI) */
05902 
05903 #if defined(HAVE_OPENR2)
05904 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05905 
05906 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05907 {
05908    /* data is whether to accept with charge or no charge */
05909    openr2_call_mode_t accept_mode;
05910    int res, timeout, maxloops;
05911    struct ast_frame *f;
05912    struct dahdi_pvt *p;
05913    char *parse;
05914    AST_DECLARE_APP_ARGS(args,
05915          AST_APP_ARG(charge);
05916    );
05917 
05918    if (ast_strlen_zero(data)) {
05919       ast_log(LOG_DEBUG, "No data sent to application!\n");
05920       return -1;
05921    }
05922 
05923    if (chan->tech != &dahdi_tech) {
05924       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05925       return -1;
05926    }
05927 
05928    p = (struct dahdi_pvt *)chan->tech_pvt;
05929    if (!p) {
05930       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05931       return -1;
05932    }
05933 
05934    parse = ast_strdupa(data);
05935    AST_STANDARD_APP_ARGS(args, parse);
05936 
05937    if (ast_strlen_zero(args.charge)) {
05938       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05939       return -1;
05940    }
05941 
05942    ast_mutex_lock(&p->lock);
05943    if (!p->mfcr2 || !p->mfcr2call) {
05944       ast_mutex_unlock(&p->lock);
05945       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05946       return -1;
05947    }
05948 
05949    if (p->mfcr2_call_accepted) {
05950       ast_mutex_unlock(&p->lock);
05951       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05952       return 0;
05953    }
05954    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05955    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05956       ast_mutex_unlock(&p->lock);
05957       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05958       return -1;
05959    }
05960    ast_mutex_unlock(&p->lock);
05961 
05962    res = 0;
05963    timeout = 100;
05964    maxloops = 50; /* wait up to 5 seconds */
05965    /* we need to read() until the call is accepted */
05966    while (maxloops > 0) {
05967       maxloops--;
05968       if (ast_check_hangup(chan)) {
05969          break;
05970       }
05971       res = ast_waitfor(chan, timeout);
05972       if (res < 0) {
05973          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05974          res = -1;
05975          break;
05976       }
05977       if (res == 0) {
05978          continue;
05979       }
05980       f = ast_read(chan);
05981       if (!f) {
05982          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05983          res = -1;
05984          break;
05985       }
05986       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05987          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05988          ast_frfree(f);
05989          res = -1;
05990          break;
05991       }
05992       ast_frfree(f);
05993       ast_mutex_lock(&p->lock);
05994       if (p->mfcr2_call_accepted) {
05995          ast_mutex_unlock(&p->lock);
05996          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05997          break;
05998       }
05999       ast_mutex_unlock(&p->lock);
06000    }
06001    if (res == -1) {
06002       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06003    }
06004    return res;
06005 }
06006 
06007 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06008 {
06009    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06010    switch (cause) {
06011    case AST_CAUSE_USER_BUSY:
06012    case AST_CAUSE_CALL_REJECTED:
06013    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06014       r2cause = OR2_CAUSE_BUSY_NUMBER;
06015       break;
06016 
06017    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06018    case AST_CAUSE_SWITCH_CONGESTION:
06019       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06020       break;
06021 
06022    case AST_CAUSE_UNALLOCATED:
06023       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06024       break;
06025 
06026    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06027    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06028       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06029       break;
06030 
06031    case AST_CAUSE_NO_ANSWER:
06032    case AST_CAUSE_NO_USER_RESPONSE:
06033       r2cause = OR2_CAUSE_NO_ANSWER;
06034       break;
06035 
06036    default:
06037       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06038       break;
06039    }
06040    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06041          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06042    return r2cause;
06043 }
06044 #endif
06045 
06046 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06047 {
06048    if (p->bufferoverrideinuse) {
06049       /* faxbuffers are in use, revert them */
06050       struct dahdi_bufferinfo bi = {
06051          .txbufpolicy = p->buf_policy,
06052          .rxbufpolicy = p->buf_policy,
06053          .bufsize = p->bufsize,
06054          .numbufs = p->buf_no
06055       };
06056       int bpres;
06057 
06058       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06059          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06060       }
06061       p->bufferoverrideinuse = 0;
06062       return bpres;
06063    }
06064 
06065    return -1;
06066 }
06067 
06068 static int dahdi_hangup(struct ast_channel *ast)
06069 {
06070    int res = 0;
06071    int idx,x;
06072    int law;
06073    /*static int restore_gains(struct dahdi_pvt *p);*/
06074    struct dahdi_pvt *p = ast->tech_pvt;
06075    struct dahdi_params par;
06076 
06077    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06078    if (!ast->tech_pvt) {
06079       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06080       return 0;
06081    }
06082 
06083    ast_mutex_lock(&p->lock);
06084    p->exten[0] = '\0';
06085    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06086       dahdi_confmute(p, 0);
06087       restore_gains(p);
06088       p->ignoredtmf = 0;
06089       p->waitingfordt.tv_sec = 0;
06090 
06091       res = analog_hangup(p->sig_pvt, ast);
06092       revert_fax_buffers(p, ast);
06093 
06094       goto hangup_out;
06095    } else {
06096       p->cid_num[0] = '\0';
06097       p->cid_name[0] = '\0';
06098       p->cid_subaddr[0] = '\0';
06099    }
06100 
06101 #if defined(HAVE_PRI)
06102    if (dahdi_sig_pri_lib_handles(p->sig)) {
06103       x = 1;
06104       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06105 
06106       dahdi_confmute(p, 0);
06107       p->muting = 0;
06108       restore_gains(p);
06109       if (p->dsp) {
06110          ast_dsp_free(p->dsp);
06111          p->dsp = NULL;
06112       }
06113       p->ignoredtmf = 0;
06114 
06115       /* Real channel, do some fixup */
06116       p->subs[SUB_REAL].owner = NULL;
06117       p->subs[SUB_REAL].needbusy = 0;
06118       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06119 
06120       p->owner = NULL;
06121       p->cid_tag[0] = '\0';
06122       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06123       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06124       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06125       p->outgoing = 0;
06126       p->digital = 0;
06127       p->faxhandled = 0;
06128       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06129 
06130       revert_fax_buffers(p, ast);
06131 
06132       p->law = p->law_default;
06133       law = p->law_default;
06134       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06135       if (res < 0) {
06136          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06137             p->channel, strerror(errno));
06138       }
06139 
06140       sig_pri_hangup(p->sig_pvt, ast);
06141 
06142       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06143       dahdi_disable_ec(p);
06144 
06145       x = 0;
06146       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06147       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06148 
06149       p->rdnis[0] = '\0';
06150       update_conf(p);
06151       reset_conf(p);
06152 
06153       /* Restore data mode */
06154       x = 0;
06155       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06156 
06157       if (num_restart_pending == 0) {
06158          restart_monitor();
06159       }
06160       goto hangup_out;
06161    }
06162 #endif   /* defined(HAVE_PRI) */
06163 
06164 #if defined(HAVE_SS7)
06165    if (p->sig == SIG_SS7) {
06166       x = 1;
06167       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06168 
06169       dahdi_confmute(p, 0);
06170       p->muting = 0;
06171       restore_gains(p);
06172       if (p->dsp) {
06173          ast_dsp_free(p->dsp);
06174          p->dsp = NULL;
06175       }
06176       p->ignoredtmf = 0;
06177 
06178       /* Real channel, do some fixup */
06179       p->subs[SUB_REAL].owner = NULL;
06180       p->subs[SUB_REAL].needbusy = 0;
06181       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06182 
06183       p->owner = NULL;
06184       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06185       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06186       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06187       p->outgoing = 0;
06188       p->digital = 0;
06189       p->faxhandled = 0;
06190       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06191 
06192       revert_fax_buffers(p, ast);
06193 
06194       p->law = p->law_default;
06195       law = p->law_default;
06196       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06197       if (res < 0) {
06198          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06199             p->channel, strerror(errno));
06200       }
06201 
06202       sig_ss7_hangup(p->sig_pvt, ast);
06203 
06204       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06205       dahdi_disable_ec(p);
06206 
06207       x = 0;
06208       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06209       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06210 
06211       update_conf(p);
06212       reset_conf(p);
06213 
06214       /* Restore data mode */
06215       x = 0;
06216       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06217 
06218       if (num_restart_pending == 0) {
06219          restart_monitor();
06220       }
06221       goto hangup_out;
06222    }
06223 #endif   /* defined(HAVE_SS7) */
06224 
06225    idx = dahdi_get_index(ast, p, 1);
06226 
06227    dahdi_confmute(p, 0);
06228    p->muting = 0;
06229    restore_gains(p);
06230    if (p->origcid_num) {
06231       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06232       ast_free(p->origcid_num);
06233       p->origcid_num = NULL;
06234    }
06235    if (p->origcid_name) {
06236       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06237       ast_free(p->origcid_name);
06238       p->origcid_name = NULL;
06239    }
06240    if (p->dsp)
06241       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06242 
06243    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06244       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06245    p->ignoredtmf = 0;
06246 
06247    if (idx > -1) {
06248       /* Real channel, do some fixup */
06249       p->subs[idx].owner = NULL;
06250       p->subs[idx].needanswer = 0;
06251       p->subs[idx].needflash = 0;
06252       p->subs[idx].needringing = 0;
06253       p->subs[idx].needbusy = 0;
06254       p->subs[idx].needcongestion = 0;
06255       p->subs[idx].linear = 0;
06256       p->polarity = POLARITY_IDLE;
06257       dahdi_setlinear(p->subs[idx].dfd, 0);
06258       if (idx == SUB_REAL) {
06259          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06260             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06261             if (p->subs[SUB_CALLWAIT].inthreeway) {
06262                /* We had flipped over to answer a callwait and now it's gone */
06263                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06264                /* Move to the call-wait, but un-own us until they flip back. */
06265                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06266                unalloc_sub(p, SUB_CALLWAIT);
06267                p->owner = NULL;
06268             } else {
06269                /* The three way hung up, but we still have a call wait */
06270                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06271                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06272                unalloc_sub(p, SUB_THREEWAY);
06273                if (p->subs[SUB_REAL].inthreeway) {
06274                   /* This was part of a three way call.  Immediately make way for
06275                      another call */
06276                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06277                   p->owner = p->subs[SUB_REAL].owner;
06278                } else {
06279                   /* This call hasn't been completed yet...  Set owner to NULL */
06280                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06281                   p->owner = NULL;
06282                }
06283                p->subs[SUB_REAL].inthreeway = 0;
06284             }
06285          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06286             /* Move to the call-wait and switch back to them. */
06287             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06288             unalloc_sub(p, SUB_CALLWAIT);
06289             p->owner = p->subs[SUB_REAL].owner;
06290             if (p->owner->_state != AST_STATE_UP)
06291                p->subs[SUB_REAL].needanswer = 1;
06292             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06293                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06294          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06295             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06296             unalloc_sub(p, SUB_THREEWAY);
06297             if (p->subs[SUB_REAL].inthreeway) {
06298                /* This was part of a three way call.  Immediately make way for
06299                   another call */
06300                ast_debug(1, "Call was complete, setting owner to former third call\n");
06301                p->owner = p->subs[SUB_REAL].owner;
06302             } else {
06303                /* This call hasn't been completed yet...  Set owner to NULL */
06304                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06305                p->owner = NULL;
06306             }
06307             p->subs[SUB_REAL].inthreeway = 0;
06308          }
06309       } else if (idx == SUB_CALLWAIT) {
06310          /* Ditch the holding callwait call, and immediately make it availabe */
06311          if (p->subs[SUB_CALLWAIT].inthreeway) {
06312             /* This is actually part of a three way, placed on hold.  Place the third part
06313                on music on hold now */
06314             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06315                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06316                   S_OR(p->mohsuggest, NULL),
06317                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06318             }
06319             p->subs[SUB_THREEWAY].inthreeway = 0;
06320             /* Make it the call wait now */
06321             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06322             unalloc_sub(p, SUB_THREEWAY);
06323          } else
06324             unalloc_sub(p, SUB_CALLWAIT);
06325       } else if (idx == SUB_THREEWAY) {
06326          if (p->subs[SUB_CALLWAIT].inthreeway) {
06327             /* The other party of the three way call is currently in a call-wait state.
06328                Start music on hold for them, and take the main guy out of the third call */
06329             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06330                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06331                   S_OR(p->mohsuggest, NULL),
06332                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06333             }
06334             p->subs[SUB_CALLWAIT].inthreeway = 0;
06335          }
06336          p->subs[SUB_REAL].inthreeway = 0;
06337          /* If this was part of a three way call index, let us make
06338             another three way call */
06339          unalloc_sub(p, SUB_THREEWAY);
06340       } else {
06341          /* This wasn't any sort of call, but how are we an index? */
06342          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06343       }
06344    }
06345 
06346    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06347       p->owner = NULL;
06348       p->ringt = 0;
06349       p->distinctivering = 0;
06350       p->confirmanswer = 0;
06351       p->outgoing = 0;
06352       p->digital = 0;
06353       p->faxhandled = 0;
06354       p->pulsedial = 0;
06355       if (p->dsp) {
06356          ast_dsp_free(p->dsp);
06357          p->dsp = NULL;
06358       }
06359 
06360       revert_fax_buffers(p, ast);
06361 
06362       p->law = p->law_default;
06363       law = p->law_default;
06364       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06365       if (res < 0)
06366          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06367       /* Perform low level hangup if no owner left */
06368 #ifdef HAVE_OPENR2
06369       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06370          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06371          /* If it's an incoming call, check the mfcr2_forced_release setting */
06372          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06373             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06374          } else {
06375             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06376             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06377             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06378                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06379             dahdi_r2_disconnect_call(p, r2cause);
06380          }
06381       } else if (p->mfcr2call) {
06382          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06383          /* since ast_request() was called but not ast_call() we have not yet dialed
06384          and the openr2 stack will not call on_call_end callback, we need to unset
06385          the mfcr2call flag and bump the monitor count so the monitor thread can take
06386          care of this channel events from now on */
06387          p->mfcr2call = 0;
06388       }
06389 #endif
06390       switch (p->sig) {
06391       case SIG_SS7:
06392       case SIG_MFCR2:
06393       case SIG_PRI_LIB_HANDLE_CASES:
06394       case 0:
06395          break;
06396       default:
06397          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06398          break;
06399       }
06400       if (res < 0) {
06401          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06402       }
06403       switch (p->sig) {
06404       case SIG_FXOGS:
06405       case SIG_FXOLS:
06406       case SIG_FXOKS:
06407          memset(&par, 0, sizeof(par));
06408          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06409          if (!res) {
06410             struct analog_pvt *analog_p = p->sig_pvt;
06411 #if 0
06412             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06413 #endif
06414             /* If they're off hook, try playing congestion */
06415             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06416                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06417             else
06418                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06419             analog_p->fxsoffhookstate = par.rxisoffhook;
06420          }
06421          break;
06422       case SIG_FXSGS:
06423       case SIG_FXSLS:
06424       case SIG_FXSKS:
06425          /* Make sure we're not made available for at least two seconds assuming
06426          we were actually used for an inbound or outbound call. */
06427          if (ast->_state != AST_STATE_RESERVED) {
06428             time(&p->guardtime);
06429             p->guardtime += 2;
06430          }
06431          break;
06432       default:
06433          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06434          break;
06435       }
06436       if (p->sig)
06437          dahdi_disable_ec(p);
06438       x = 0;
06439       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06440       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06441       p->didtdd = 0;
06442       p->callwaitcas = 0;
06443       p->callwaiting = p->permcallwaiting;
06444       p->hidecallerid = p->permhidecallerid;
06445       p->waitingfordt.tv_sec = 0;
06446       p->dialing = 0;
06447       p->rdnis[0] = '\0';
06448       update_conf(p);
06449       reset_conf(p);
06450       /* Restore data mode */
06451       switch (p->sig) {
06452       case SIG_PRI_LIB_HANDLE_CASES:
06453       case SIG_SS7:
06454          x = 0;
06455          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06456          break;
06457       default:
06458          break;
06459       }
06460       if (num_restart_pending == 0)
06461          restart_monitor();
06462    }
06463 
06464    p->callwaitingrepeat = 0;
06465    p->cidcwexpire = 0;
06466    p->cid_suppress_expire = 0;
06467    p->oprmode = 0;
06468 hangup_out:
06469    ast->tech_pvt = NULL;
06470    ast_free(p->cidspill);
06471    p->cidspill = NULL;
06472 
06473    ast_mutex_unlock(&p->lock);
06474    ast_verb(3, "Hungup '%s'\n", ast->name);
06475 
06476    ast_mutex_lock(&iflock);
06477    if (p->restartpending) {
06478       num_restart_pending--;
06479    }
06480 
06481    if (p->destroy) {
06482       destroy_channel(p, 0);
06483    }
06484    ast_mutex_unlock(&iflock);
06485 
06486    ast_module_unref(ast_module_info->self);
06487    return 0;
06488 }
06489 
06490 static int dahdi_answer(struct ast_channel *ast)
06491 {
06492    struct dahdi_pvt *p = ast->tech_pvt;
06493    int res = 0;
06494    int idx;
06495    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06496    ast_mutex_lock(&p->lock);
06497    idx = dahdi_get_index(ast, p, 0);
06498    if (idx < 0)
06499       idx = SUB_REAL;
06500    /* nothing to do if a radio channel */
06501    if ((p->radio || (p->oprmode < 0))) {
06502       ast_mutex_unlock(&p->lock);
06503       return 0;
06504    }
06505 
06506    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06507       res = analog_answer(p->sig_pvt, ast);
06508       ast_mutex_unlock(&p->lock);
06509       return res;
06510    }
06511 
06512    switch (p->sig) {
06513 #if defined(HAVE_PRI)
06514    case SIG_PRI_LIB_HANDLE_CASES:
06515       res = sig_pri_answer(p->sig_pvt, ast);
06516       break;
06517 #endif   /* defined(HAVE_PRI) */
06518 #if defined(HAVE_SS7)
06519    case SIG_SS7:
06520       res = sig_ss7_answer(p->sig_pvt, ast);
06521       break;
06522 #endif   /* defined(HAVE_SS7) */
06523 #ifdef HAVE_OPENR2
06524    case SIG_MFCR2:
06525       if (!p->mfcr2_call_accepted) {
06526          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06527             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06528          p->mfcr2_answer_pending = 1;
06529          if (p->mfcr2_charge_calls) {
06530             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06531             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06532          } else {
06533             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06534             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06535          }
06536       } else {
06537          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06538          dahdi_r2_answer(p);
06539       }
06540       break;
06541 #endif
06542    case 0:
06543       ast_mutex_unlock(&p->lock);
06544       return 0;
06545    default:
06546       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06547       res = -1;
06548       break;
06549    }
06550    ast_mutex_unlock(&p->lock);
06551    return res;
06552 }
06553 
06554 static void disable_dtmf_detect(struct dahdi_pvt *p)
06555 {
06556    int val = 0;
06557 
06558    p->ignoredtmf = 1;
06559 
06560    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06561 
06562    if (!p->hardwaredtmf && p->dsp) {
06563       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06564       ast_dsp_set_features(p->dsp, p->dsp_features);
06565    }
06566 }
06567 
06568 static void enable_dtmf_detect(struct dahdi_pvt *p)
06569 {
06570    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06571 
06572    if (p->channel == CHAN_PSEUDO)
06573       return;
06574 
06575    p->ignoredtmf = 0;
06576 
06577    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06578 
06579    if (!p->hardwaredtmf && p->dsp) {
06580       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06581       ast_dsp_set_features(p->dsp, p->dsp_features);
06582    }
06583 }
06584 
06585 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06586 {
06587    char *cp;
06588    struct dahdi_pvt *p = chan->tech_pvt;
06589 
06590    /* all supported options require data */
06591    if (!data || (*datalen < 1)) {
06592       errno = EINVAL;
06593       return -1;
06594    }
06595 
06596    switch (option) {
06597    case AST_OPTION_DIGIT_DETECT:
06598       cp = (char *) data;
06599       *cp = p->ignoredtmf ? 0 : 1;
06600       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06601       break;
06602    case AST_OPTION_FAX_DETECT:
06603       cp = (char *) data;
06604       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06605       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06606       break;
06607    case AST_OPTION_CC_AGENT_TYPE:
06608 #if defined(HAVE_PRI)
06609 #if defined(HAVE_PRI_CCSS)
06610       if (dahdi_sig_pri_lib_handles(p->sig)) {
06611          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06612          break;
06613       }
06614 #endif   /* defined(HAVE_PRI_CCSS) */
06615 #endif   /* defined(HAVE_PRI) */
06616       return -1;
06617    default:
06618       return -1;
06619    }
06620 
06621    errno = 0;
06622 
06623    return 0;
06624 }
06625 
06626 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06627 {
06628    char *cp;
06629    signed char *scp;
06630    int x;
06631    int idx;
06632    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06633    struct oprmode *oprmode;
06634 
06635 
06636    /* all supported options require data */
06637    if (!data || (datalen < 1)) {
06638       errno = EINVAL;
06639       return -1;
06640    }
06641 
06642    switch (option) {
06643    case AST_OPTION_TXGAIN:
06644       scp = (signed char *) data;
06645       idx = dahdi_get_index(chan, p, 0);
06646       if (idx < 0) {
06647          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06648          return -1;
06649       }
06650       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06651       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06652    case AST_OPTION_RXGAIN:
06653       scp = (signed char *) data;
06654       idx = dahdi_get_index(chan, p, 0);
06655       if (idx < 0) {
06656          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06657          return -1;
06658       }
06659       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06660       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06661    case AST_OPTION_TONE_VERIFY:
06662       if (!p->dsp)
06663          break;
06664       cp = (char *) data;
06665       switch (*cp) {
06666       case 1:
06667          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06668          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06669          break;
06670       case 2:
06671          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06672          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06673          break;
06674       default:
06675          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06676          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06677          break;
06678       }
06679       break;
06680    case AST_OPTION_TDD:
06681       /* turn on or off TDD */
06682       cp = (char *) data;
06683       p->mate = 0;
06684       if (!*cp) { /* turn it off */
06685          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06686          if (p->tdd)
06687             tdd_free(p->tdd);
06688          p->tdd = 0;
06689          break;
06690       }
06691       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06692          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06693       dahdi_disable_ec(p);
06694       /* otherwise, turn it on */
06695       if (!p->didtdd) { /* if havent done it yet */
06696          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06697          unsigned char *buf;
06698          int size, res, fd, len;
06699          struct pollfd fds[1];
06700 
06701          buf = mybuf;
06702          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06703          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06704          len = 40000;
06705          idx = dahdi_get_index(chan, p, 0);
06706          if (idx < 0) {
06707             ast_log(LOG_WARNING, "No index in TDD?\n");
06708             return -1;
06709          }
06710          fd = p->subs[idx].dfd;
06711          while (len) {
06712             if (ast_check_hangup(chan))
06713                return -1;
06714             size = len;
06715             if (size > READ_SIZE)
06716                size = READ_SIZE;
06717             fds[0].fd = fd;
06718             fds[0].events = POLLPRI | POLLOUT;
06719             fds[0].revents = 0;
06720             res = poll(fds, 1, -1);
06721             if (!res) {
06722                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06723                continue;
06724             }
06725             /* if got exception */
06726             if (fds[0].revents & POLLPRI)
06727                return -1;
06728             if (!(fds[0].revents & POLLOUT)) {
06729                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06730                continue;
06731             }
06732             res = write(fd, buf, size);
06733             if (res != size) {
06734                if (res == -1) return -1;
06735                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06736                break;
06737             }
06738             len -= size;
06739             buf += size;
06740          }
06741          p->didtdd = 1; /* set to have done it now */
06742       }
06743       if (*cp == 2) { /* Mate mode */
06744          if (p->tdd)
06745             tdd_free(p->tdd);
06746          p->tdd = 0;
06747          p->mate = 1;
06748          break;
06749       }
06750       if (!p->tdd) { /* if we don't have one yet */
06751          p->tdd = tdd_new(); /* allocate one */
06752       }
06753       break;
06754    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06755       if (!p->dsp)
06756          break;
06757       cp = (char *) data;
06758       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06759          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06760       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06761       break;
06762    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06763 #if defined(HAVE_PRI)
06764       if (dahdi_sig_pri_lib_handles(p->sig)
06765          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06766          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06767          break;
06768       }
06769 #endif   /* defined(HAVE_PRI) */
06770 
06771       cp = (char *) data;
06772       if (!*cp) {
06773          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06774          x = 0;
06775          dahdi_disable_ec(p);
06776       } else {
06777          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06778          x = 1;
06779       }
06780       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06781          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06782       break;
06783    case AST_OPTION_OPRMODE:  /* Operator services mode */
06784       oprmode = (struct oprmode *) data;
06785       /* We don't support operator mode across technologies */
06786       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06787          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06788                chan->tech->type, oprmode->peer->tech->type);
06789          errno = EINVAL;
06790          return -1;
06791       }
06792       pp = oprmode->peer->tech_pvt;
06793       p->oprmode = pp->oprmode = 0;
06794       /* setup peers */
06795       p->oprpeer = pp;
06796       pp->oprpeer = p;
06797       /* setup modes, if any */
06798       if (oprmode->mode)
06799       {
06800          pp->oprmode = oprmode->mode;
06801          p->oprmode = -oprmode->mode;
06802       }
06803       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06804          oprmode->mode, chan->name,oprmode->peer->name);
06805       break;
06806    case AST_OPTION_ECHOCAN:
06807       cp = (char *) data;
06808       if (*cp) {
06809          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06810          dahdi_enable_ec(p);
06811       } else {
06812          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06813          dahdi_disable_ec(p);
06814       }
06815       break;
06816    case AST_OPTION_DIGIT_DETECT:
06817       cp = (char *) data;
06818       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06819       if (*cp) {
06820          enable_dtmf_detect(p);
06821       } else {
06822          disable_dtmf_detect(p);
06823       }
06824       break;
06825    case AST_OPTION_FAX_DETECT:
06826       cp = (char *) data;
06827       if (p->dsp) {
06828          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06829          if (*cp) {
06830             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06831          } else {
06832             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06833          }
06834          ast_dsp_set_features(p->dsp, p->dsp_features);
06835       }
06836       break;
06837    default:
06838       return -1;
06839    }
06840    errno = 0;
06841 
06842    return 0;
06843 }
06844 
06845 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06846 {
06847    struct dahdi_pvt *p = chan->tech_pvt;
06848    int res = 0;
06849 
06850    if (!strcasecmp(data, "rxgain")) {
06851       ast_mutex_lock(&p->lock);
06852       snprintf(buf, len, "%f", p->rxgain);
06853       ast_mutex_unlock(&p->lock);
06854    } else if (!strcasecmp(data, "txgain")) {
06855       ast_mutex_lock(&p->lock);
06856       snprintf(buf, len, "%f", p->txgain);
06857       ast_mutex_unlock(&p->lock);
06858    } else if (!strcasecmp(data, "dahdi_channel")) {
06859       ast_mutex_lock(&p->lock);
06860       snprintf(buf, len, "%d", p->channel);
06861       ast_mutex_unlock(&p->lock);
06862    } else if (!strcasecmp(data, "dahdi_span")) {
06863       ast_mutex_lock(&p->lock);
06864       snprintf(buf, len, "%d", p->span);
06865       ast_mutex_unlock(&p->lock);
06866    } else if (!strcasecmp(data, "dahdi_type")) {
06867       ast_mutex_lock(&p->lock);
06868       switch (p->sig) {
06869 #if defined(HAVE_OPENR2)
06870       case SIG_MFCR2:
06871          ast_copy_string(buf, "mfc/r2", len);
06872          break;
06873 #endif   /* defined(HAVE_OPENR2) */
06874 #if defined(HAVE_PRI)
06875       case SIG_PRI_LIB_HANDLE_CASES:
06876          ast_copy_string(buf, "pri", len);
06877          break;
06878 #endif   /* defined(HAVE_PRI) */
06879       case 0:
06880          ast_copy_string(buf, "pseudo", len);
06881          break;
06882 #if defined(HAVE_SS7)
06883       case SIG_SS7:
06884          ast_copy_string(buf, "ss7", len);
06885          break;
06886 #endif   /* defined(HAVE_SS7) */
06887       default:
06888          /* The only thing left is analog ports. */
06889          ast_copy_string(buf, "analog", len);
06890          break;
06891       }
06892       ast_mutex_unlock(&p->lock);
06893 #if defined(HAVE_PRI)
06894 #if defined(HAVE_PRI_REVERSE_CHARGE)
06895    } else if (!strcasecmp(data, "reversecharge")) {
06896       ast_mutex_lock(&p->lock);
06897       switch (p->sig) {
06898       case SIG_PRI_LIB_HANDLE_CASES:
06899          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06900          break;
06901       default:
06902          *buf = '\0';
06903          res = -1;
06904          break;
06905       }
06906       ast_mutex_unlock(&p->lock);
06907 #endif
06908 #if defined(HAVE_PRI_SETUP_KEYPAD)
06909    } else if (!strcasecmp(data, "keypad_digits")) {
06910       ast_mutex_lock(&p->lock);
06911       switch (p->sig) {
06912       case SIG_PRI_LIB_HANDLE_CASES:
06913          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06914             len);
06915          break;
06916       default:
06917          *buf = '\0';
06918          res = -1;
06919          break;
06920       }
06921       ast_mutex_unlock(&p->lock);
06922 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06923    } else if (!strcasecmp(data, "no_media_path")) {
06924       ast_mutex_lock(&p->lock);
06925       switch (p->sig) {
06926       case SIG_PRI_LIB_HANDLE_CASES:
06927          /*
06928           * TRUE if the call is on hold or is call waiting because
06929           * there is no media path available.
06930           */
06931          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06932          break;
06933       default:
06934          *buf = '\0';
06935          res = -1;
06936          break;
06937       }
06938       ast_mutex_unlock(&p->lock);
06939 #endif   /* defined(HAVE_PRI) */
06940    } else {
06941       *buf = '\0';
06942       res = -1;
06943    }
06944 
06945    return res;
06946 }
06947 
06948 
06949 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06950 {
06951    int res;
06952    char policy_str[21] = "";
06953 
06954    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06955       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06956       return 1;
06957    }
06958    if (*num_buffers < 0) {
06959       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06960       return -1;
06961    }
06962    if (!strcasecmp(policy_str, "full")) {
06963       *policy = DAHDI_POLICY_WHEN_FULL;
06964    } else if (!strcasecmp(policy_str, "immediate")) {
06965       *policy = DAHDI_POLICY_IMMEDIATE;
06966 #if defined(HAVE_DAHDI_HALF_FULL)
06967    } else if (!strcasecmp(policy_str, "half")) {
06968       *policy = DAHDI_POLICY_HALF_FULL;
06969 #endif
06970    } else {
06971       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06972       return -1;
06973    }
06974 
06975    return 0;
06976 }
06977 
06978 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06979 {
06980    struct dahdi_pvt *p = chan->tech_pvt;
06981    int res = 0;
06982 
06983    if (!strcasecmp(data, "buffers")) {
06984       int num_bufs, policy;
06985 
06986       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06987          struct dahdi_bufferinfo bi = {
06988             .txbufpolicy = policy,
06989             .rxbufpolicy = policy,
06990             .bufsize = p->bufsize,
06991             .numbufs = num_bufs,
06992          };
06993          int bpres;
06994 
06995          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06996             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06997          } else {
06998             p->bufferoverrideinuse = 1;
06999          }
07000       } else {
07001          res = -1;
07002       }
07003    } else if (!strcasecmp(data, "echocan_mode")) {
07004       if (!strcasecmp(value, "on")) {
07005          ast_mutex_lock(&p->lock);
07006          dahdi_enable_ec(p);
07007          ast_mutex_unlock(&p->lock);
07008       } else if (!strcasecmp(value, "off")) {
07009          ast_mutex_lock(&p->lock);
07010          dahdi_disable_ec(p);
07011          ast_mutex_unlock(&p->lock);
07012 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07013       } else if (!strcasecmp(value, "fax")) {
07014          int blah = 1;
07015 
07016          ast_mutex_lock(&p->lock);
07017          if (!p->echocanon) {
07018             dahdi_enable_ec(p);
07019          }
07020          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07021             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07022          }
07023          ast_mutex_unlock(&p->lock);
07024       } else if (!strcasecmp(value, "voice")) {
07025          int blah = 0;
07026 
07027          ast_mutex_lock(&p->lock);
07028          if (!p->echocanon) {
07029             dahdi_enable_ec(p);
07030          }
07031          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07032             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07033          }
07034          ast_mutex_unlock(&p->lock);
07035 #endif
07036       } else {
07037          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07038          res = -1;
07039       }
07040    } else {
07041       res = -1;
07042    }
07043 
07044    return res;
07045 }
07046 
07047 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07048 {
07049    /* Unlink a specific slave or all slaves/masters from a given master */
07050    int x;
07051    int hasslaves;
07052    if (!master)
07053       return;
07054    if (needlock) {
07055       ast_mutex_lock(&master->lock);
07056       if (slave) {
07057          while (ast_mutex_trylock(&slave->lock)) {
07058             DEADLOCK_AVOIDANCE(&master->lock);
07059          }
07060       }
07061    }
07062    hasslaves = 0;
07063    for (x = 0; x < MAX_SLAVES; x++) {
07064       if (master->slaves[x]) {
07065          if (!slave || (master->slaves[x] == slave)) {
07066             /* Take slave out of the conference */
07067             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07068             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07069             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07070             master->slaves[x]->master = NULL;
07071             master->slaves[x] = NULL;
07072          } else
07073             hasslaves = 1;
07074       }
07075       if (!hasslaves)
07076          master->inconference = 0;
07077    }
07078    if (!slave) {
07079       if (master->master) {
07080          /* Take master out of the conference */
07081          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07082          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07083          hasslaves = 0;
07084          for (x = 0; x < MAX_SLAVES; x++) {
07085             if (master->master->slaves[x] == master)
07086                master->master->slaves[x] = NULL;
07087             else if (master->master->slaves[x])
07088                hasslaves = 1;
07089          }
07090          if (!hasslaves)
07091             master->master->inconference = 0;
07092       }
07093       master->master = NULL;
07094    }
07095    update_conf(master);
07096    if (needlock) {
07097       if (slave)
07098          ast_mutex_unlock(&slave->lock);
07099       ast_mutex_unlock(&master->lock);
07100    }
07101 }
07102 
07103 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07104    int x;
07105    if (!slave || !master) {
07106       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07107       return;
07108    }
07109    for (x = 0; x < MAX_SLAVES; x++) {
07110       if (!master->slaves[x]) {
07111          master->slaves[x] = slave;
07112          break;
07113       }
07114    }
07115    if (x >= MAX_SLAVES) {
07116       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07117       master->slaves[MAX_SLAVES - 1] = slave;
07118    }
07119    if (slave->master)
07120       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07121    slave->master = master;
07122 
07123    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07124 }
07125 
07126 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)
07127 {
07128    struct ast_channel *who;
07129    struct dahdi_pvt *p0, *p1, *op0, *op1;
07130    struct dahdi_pvt *master = NULL, *slave = NULL;
07131    struct ast_frame *f;
07132    int inconf = 0;
07133    int nothingok = 1;
07134    int ofd0, ofd1;
07135    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07136    int os0 = -1, os1 = -1;
07137    int priority = 0;
07138    struct ast_channel *oc0, *oc1;
07139    enum ast_bridge_result res;
07140 #ifdef PRI_2BCT
07141    int triedtopribridge = 0;
07142    q931_call *q931c0;
07143    q931_call *q931c1;
07144 #endif
07145 
07146    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07147       There is code below to handle it properly until DTMF is actually seen,
07148       but due to currently unresolved issues it's ignored...
07149    */
07150 
07151    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07152       return AST_BRIDGE_FAILED_NOWARN;
07153 
07154    ast_channel_lock(c0);
07155    while (ast_channel_trylock(c1)) {
07156       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07157    }
07158 
07159    p0 = c0->tech_pvt;
07160    p1 = c1->tech_pvt;
07161    /* cant do pseudo-channels here */
07162    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07163       ast_channel_unlock(c0);
07164       ast_channel_unlock(c1);
07165       return AST_BRIDGE_FAILED_NOWARN;
07166    }
07167 
07168    oi0 = dahdi_get_index(c0, p0, 0);
07169    oi1 = dahdi_get_index(c1, p1, 0);
07170    if ((oi0 < 0) || (oi1 < 0)) {
07171       ast_channel_unlock(c0);
07172       ast_channel_unlock(c1);
07173       return AST_BRIDGE_FAILED;
07174    }
07175 
07176    op0 = p0 = c0->tech_pvt;
07177    op1 = p1 = c1->tech_pvt;
07178    ofd0 = c0->fds[0];
07179    ofd1 = c1->fds[0];
07180    oc0 = p0->owner;
07181    oc1 = p1->owner;
07182 
07183    if (ast_mutex_trylock(&p0->lock)) {
07184       /* Don't block, due to potential for deadlock */
07185       ast_channel_unlock(c0);
07186       ast_channel_unlock(c1);
07187       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07188       return AST_BRIDGE_RETRY;
07189    }
07190    if (ast_mutex_trylock(&p1->lock)) {
07191       /* Don't block, due to potential for deadlock */
07192       ast_mutex_unlock(&p0->lock);
07193       ast_channel_unlock(c0);
07194       ast_channel_unlock(c1);
07195       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07196       return AST_BRIDGE_RETRY;
07197    }
07198 
07199    if ((p0->callwaiting && p0->callwaitingcallerid)
07200       || (p1->callwaiting && p1->callwaitingcallerid)) {
07201       /*
07202        * Call Waiting Caller ID requires DTMF detection to know if it
07203        * can send the CID spill.
07204        *
07205        * For now, don't attempt to native bridge if either channel
07206        * needs DTMF detection.  There is code below to handle it
07207        * properly until DTMF is actually seen, but due to currently
07208        * unresolved issues it's ignored...
07209        */
07210       ast_mutex_unlock(&p0->lock);
07211       ast_mutex_unlock(&p1->lock);
07212       ast_channel_unlock(c0);
07213       ast_channel_unlock(c1);
07214       return AST_BRIDGE_FAILED_NOWARN;
07215    }
07216 
07217 #if defined(HAVE_PRI)
07218    if ((dahdi_sig_pri_lib_handles(p0->sig)
07219          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07220       || (dahdi_sig_pri_lib_handles(p1->sig)
07221          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07222       /*
07223        * PRI nobch channels (hold and call waiting) are equivalent to
07224        * pseudo channels and cannot be done here.
07225        */
07226       ast_mutex_unlock(&p0->lock);
07227       ast_mutex_unlock(&p1->lock);
07228       ast_channel_unlock(c0);
07229       ast_channel_unlock(c1);
07230       return AST_BRIDGE_FAILED_NOWARN;
07231    }
07232 #endif   /* defined(HAVE_PRI) */
07233 
07234    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07235       if (p0->owner && p1->owner) {
07236          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07237          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07238             master = p0;
07239             slave = p1;
07240             inconf = 1;
07241          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07242             master = p1;
07243             slave = p0;
07244             inconf = 1;
07245          } else {
07246             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07247             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07248                p0->channel,
07249                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07250                p0->subs[SUB_REAL].inthreeway, p0->channel,
07251                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07252                p1->subs[SUB_REAL].inthreeway);
07253          }
07254          nothingok = 0;
07255       }
07256    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07257       if (p1->subs[SUB_THREEWAY].inthreeway) {
07258          master = p1;
07259          slave = p0;
07260          nothingok = 0;
07261       }
07262    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07263       if (p0->subs[SUB_THREEWAY].inthreeway) {
07264          master = p0;
07265          slave = p1;
07266          nothingok = 0;
07267       }
07268    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07269       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07270          don't put us in anything */
07271       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07272          master = p1;
07273          slave = p0;
07274          nothingok = 0;
07275       }
07276    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07277       /* Same as previous */
07278       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07279          master = p0;
07280          slave = p1;
07281          nothingok = 0;
07282       }
07283    }
07284    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07285       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07286    if (master && slave) {
07287       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07288          in an active threeway call with a channel that is ringing, we should
07289          indicate ringing. */
07290       if ((oi1 == SUB_THREEWAY) &&
07291          p1->subs[SUB_THREEWAY].inthreeway &&
07292          p1->subs[SUB_REAL].owner &&
07293          p1->subs[SUB_REAL].inthreeway &&
07294          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07295          ast_debug(1,
07296             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07297             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07298          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07299          os1 = p1->subs[SUB_REAL].owner->_state;
07300       } else {
07301          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07302             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07303          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07304       }
07305       if ((oi0 == SUB_THREEWAY) &&
07306          p0->subs[SUB_THREEWAY].inthreeway &&
07307          p0->subs[SUB_REAL].owner &&
07308          p0->subs[SUB_REAL].inthreeway &&
07309          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07310          ast_debug(1,
07311             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07312             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07313          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07314          os0 = p0->subs[SUB_REAL].owner->_state;
07315       } else {
07316          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07317             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07318          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07319       }
07320       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07321          if (!p0->echocanbridged || !p1->echocanbridged) {
07322             /* Disable echo cancellation if appropriate */
07323             dahdi_disable_ec(p0);
07324             dahdi_disable_ec(p1);
07325          }
07326       }
07327       dahdi_link(slave, master);
07328       master->inconference = inconf;
07329    } else if (!nothingok)
07330       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07331 
07332    update_conf(p0);
07333    update_conf(p1);
07334    t0 = p0->subs[SUB_REAL].inthreeway;
07335    t1 = p1->subs[SUB_REAL].inthreeway;
07336 
07337    ast_mutex_unlock(&p0->lock);
07338    ast_mutex_unlock(&p1->lock);
07339 
07340    ast_channel_unlock(c0);
07341    ast_channel_unlock(c1);
07342 
07343    /* Native bridge failed */
07344    if ((!master || !slave) && !nothingok) {
07345       dahdi_enable_ec(p0);
07346       dahdi_enable_ec(p1);
07347       return AST_BRIDGE_FAILED;
07348    }
07349 
07350    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07351 
07352    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07353       disable_dtmf_detect(op0);
07354 
07355    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07356       disable_dtmf_detect(op1);
07357 
07358    for (;;) {
07359       struct ast_channel *c0_priority[2] = {c0, c1};
07360       struct ast_channel *c1_priority[2] = {c1, c0};
07361 
07362       /* Here's our main loop...  Start by locking things, looking for private parts,
07363          and then balking if anything is wrong */
07364 
07365       ast_channel_lock(c0);
07366       while (ast_channel_trylock(c1)) {
07367          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07368       }
07369 
07370       p0 = c0->tech_pvt;
07371       p1 = c1->tech_pvt;
07372 
07373       if (op0 == p0)
07374          i0 = dahdi_get_index(c0, p0, 1);
07375       if (op1 == p1)
07376          i1 = dahdi_get_index(c1, p1, 1);
07377 
07378       ast_channel_unlock(c0);
07379       ast_channel_unlock(c1);
07380 
07381       if (!timeoutms ||
07382          (op0 != p0) ||
07383          (op1 != p1) ||
07384          (ofd0 != c0->fds[0]) ||
07385          (ofd1 != c1->fds[0]) ||
07386          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07387          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07388          (oc0 != p0->owner) ||
07389          (oc1 != p1->owner) ||
07390          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07391          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07392          (oi0 != i0) ||
07393          (oi1 != i1)) {
07394          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07395             op0->channel, oi0, op1->channel, oi1);
07396          res = AST_BRIDGE_RETRY;
07397          goto return_from_bridge;
07398       }
07399 
07400 #ifdef PRI_2BCT
07401       if (!triedtopribridge) {
07402          triedtopribridge = 1;
07403          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07404             ast_mutex_lock(&p0->pri->lock);
07405             switch (p0->sig) {
07406             case SIG_PRI_LIB_HANDLE_CASES:
07407                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07408                break;
07409             default:
07410                q931c0 = NULL;
07411                break;
07412             }
07413             switch (p1->sig) {
07414             case SIG_PRI_LIB_HANDLE_CASES:
07415                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07416                break;
07417             default:
07418                q931c1 = NULL;
07419                break;
07420             }
07421             if (q931c0 && q931c1) {
07422                pri_channel_bridge(q931c0, q931c1);
07423             }
07424             ast_mutex_unlock(&p0->pri->lock);
07425          }
07426       }
07427 #endif
07428 
07429       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07430       if (!who) {
07431          ast_debug(1, "Ooh, empty read...\n");
07432          continue;
07433       }
07434       f = ast_read(who);
07435       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07436          *fo = f;
07437          *rc = who;
07438          res = AST_BRIDGE_COMPLETE;
07439          goto return_from_bridge;
07440       }
07441       if (f->frametype == AST_FRAME_DTMF) {
07442          if ((who == c0) && p0->pulsedial) {
07443             ast_write(c1, f);
07444          } else if ((who == c1) && p1->pulsedial) {
07445             ast_write(c0, f);
07446          } else {
07447             *fo = f;
07448             *rc = who;
07449             res = AST_BRIDGE_COMPLETE;
07450             goto return_from_bridge;
07451          }
07452       }
07453       ast_frfree(f);
07454 
07455       /* Swap who gets priority */
07456       priority = !priority;
07457    }
07458 
07459 return_from_bridge:
07460    if (op0 == p0)
07461       dahdi_enable_ec(p0);
07462 
07463    if (op1 == p1)
07464       dahdi_enable_ec(p1);
07465 
07466    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07467       enable_dtmf_detect(op0);
07468 
07469    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07470       enable_dtmf_detect(op1);
07471 
07472    dahdi_unlink(slave, master, 1);
07473 
07474    return res;
07475 }
07476 
07477 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07478 {
07479    struct dahdi_pvt *p = newchan->tech_pvt;
07480    int x;
07481 
07482    ast_mutex_lock(&p->lock);
07483 
07484    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07485    if (p->owner == oldchan) {
07486       p->owner = newchan;
07487    }
07488    for (x = 0; x < 3; x++) {
07489       if (p->subs[x].owner == oldchan) {
07490          if (!x) {
07491             dahdi_unlink(NULL, p, 0);
07492          }
07493          p->subs[x].owner = newchan;
07494       }
07495    }
07496    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07497       analog_fixup(oldchan, newchan, p->sig_pvt);
07498 #if defined(HAVE_PRI)
07499    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07500       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07501 #endif   /* defined(HAVE_PRI) */
07502 #if defined(HAVE_SS7)
07503    } else if (p->sig == SIG_SS7) {
07504       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07505 #endif   /* defined(HAVE_SS7) */
07506    }
07507    update_conf(p);
07508 
07509    ast_mutex_unlock(&p->lock);
07510 
07511    if (newchan->_state == AST_STATE_RINGING) {
07512       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07513    }
07514    return 0;
07515 }
07516 
07517 static int dahdi_ring_phone(struct dahdi_pvt *p)
07518 {
07519    int x;
07520    int res;
07521    /* Make sure our transmit state is on hook */
07522    x = 0;
07523    x = DAHDI_ONHOOK;
07524    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07525    do {
07526       x = DAHDI_RING;
07527       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07528       if (res) {
07529          switch (errno) {
07530          case EBUSY:
07531          case EINTR:
07532             /* Wait just in case */
07533             usleep(10000);
07534             continue;
07535          case EINPROGRESS:
07536             res = 0;
07537             break;
07538          default:
07539             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07540             res = 0;
07541          }
07542       }
07543    } while (res);
07544    return res;
07545 }
07546 
07547 static void *analog_ss_thread(void *data);
07548 
07549 static int attempt_transfer(struct dahdi_pvt *p)
07550 {
07551    /* In order to transfer, we need at least one of the channels to
07552       actually be in a call bridge.  We can't conference two applications
07553       together (but then, why would we want to?) */
07554    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07555       /* The three-way person we're about to transfer to could still be in MOH, so
07556          stop if now if appropriate */
07557       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07558          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07559       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07560          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07561       }
07562       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07563          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07564       }
07565        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07566          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07567                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07568          return -1;
07569       }
07570       /* Orphan the channel after releasing the lock */
07571       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07572       unalloc_sub(p, SUB_THREEWAY);
07573    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07574       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07575       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07576          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07577       }
07578       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07579          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07580       }
07581       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07582          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07583                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07584          return -1;
07585       }
07586       /* Three-way is now the REAL */
07587       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07588       ast_channel_unlock(p->subs[SUB_REAL].owner);
07589       unalloc_sub(p, SUB_THREEWAY);
07590       /* Tell the caller not to hangup */
07591       return 1;
07592    } else {
07593       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07594          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07595       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07596       return -1;
07597    }
07598    return 0;
07599 }
07600 
07601 static int check_for_conference(struct dahdi_pvt *p)
07602 {
07603    struct dahdi_confinfo ci;
07604    /* Fine if we already have a master, etc */
07605    if (p->master || (p->confno > -1))
07606       return 0;
07607    memset(&ci, 0, sizeof(ci));
07608    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07609       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07610       return 0;
07611    }
07612    /* If we have no master and don't have a confno, then
07613       if we're in a conference, it's probably a MeetMe room or
07614       some such, so don't let us 3-way out! */
07615    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07616       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07617       return 1;
07618    }
07619    return 0;
07620 }
07621 
07622 /*! Checks channel for alarms
07623  * \param p a channel to check for alarms.
07624  * \returns the alarms on the span to which the channel belongs, or alarms on
07625  *          the channel if no span alarms.
07626  */
07627 static int get_alarms(struct dahdi_pvt *p)
07628 {
07629    int res;
07630    struct dahdi_spaninfo zi;
07631    struct dahdi_params params;
07632 
07633    memset(&zi, 0, sizeof(zi));
07634    zi.spanno = p->span;
07635 
07636    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07637       if (zi.alarms != DAHDI_ALARM_NONE)
07638          return zi.alarms;
07639    } else {
07640       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07641       return 0;
07642    }
07643 
07644    /* No alarms on the span. Check for channel alarms. */
07645    memset(&params, 0, sizeof(params));
07646    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07647       return params.chan_alarms;
07648 
07649    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07650 
07651    return DAHDI_ALARM_NONE;
07652 }
07653 
07654 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07655 {
07656    struct dahdi_pvt *p = ast->tech_pvt;
07657    struct ast_frame *f = *dest;
07658 
07659    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07660       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07661       f->subclass.integer, f->subclass.integer, ast->name);
07662 
07663    if (p->confirmanswer) {
07664       if (f->frametype == AST_FRAME_DTMF_END) {
07665          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07666          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07667             of a DTMF digit */
07668          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07669          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07670          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07671          p->confirmanswer = 0;
07672       } else {
07673          p->subs[idx].f.frametype = AST_FRAME_NULL;
07674          p->subs[idx].f.subclass.integer = 0;
07675       }
07676       *dest = &p->subs[idx].f;
07677    } else if (p->callwaitcas) {
07678       if (f->frametype == AST_FRAME_DTMF_END) {
07679          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07680             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07681             ast_free(p->cidspill);
07682             p->cidspill = NULL;
07683             send_cwcidspill(p);
07684          }
07685          p->callwaitcas = 0;
07686       }
07687       p->subs[idx].f.frametype = AST_FRAME_NULL;
07688       p->subs[idx].f.subclass.integer = 0;
07689       *dest = &p->subs[idx].f;
07690    } else if (f->subclass.integer == 'f') {
07691       if (f->frametype == AST_FRAME_DTMF_END) {
07692          /* Fax tone -- Handle and return NULL */
07693          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07694             /* If faxbuffers are configured, use them for the fax transmission */
07695             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07696                struct dahdi_bufferinfo bi = {
07697                   .txbufpolicy = p->faxbuf_policy,
07698                   .bufsize = p->bufsize,
07699                   .numbufs = p->faxbuf_no
07700                };
07701                int res;
07702 
07703                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07704                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07705                } else {
07706                   p->bufferoverrideinuse = 1;
07707                }
07708             }
07709             p->faxhandled = 1;
07710             if (p->dsp) {
07711                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07712                ast_dsp_set_features(p->dsp, p->dsp_features);
07713                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07714             }
07715             if (strcmp(ast->exten, "fax")) {
07716                const char *target_context = S_OR(ast->macrocontext, ast->context);
07717 
07718                /* We need to unlock 'ast' here because ast_exists_extension has the
07719                 * potential to start autoservice on the channel. Such action is prone
07720                 * to deadlock.
07721                 */
07722                ast_mutex_unlock(&p->lock);
07723                ast_channel_unlock(ast);
07724                if (ast_exists_extension(ast, target_context, "fax", 1,
07725                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07726                   ast_channel_lock(ast);
07727                   ast_mutex_lock(&p->lock);
07728                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07729                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07730                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07731                   if (ast_async_goto(ast, target_context, "fax", 1))
07732                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07733                } else {
07734                   ast_channel_lock(ast);
07735                   ast_mutex_lock(&p->lock);
07736                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07737                }
07738             } else {
07739                ast_debug(1, "Already in a fax extension, not redirecting\n");
07740             }
07741          } else {
07742             ast_debug(1, "Fax already handled\n");
07743          }
07744          dahdi_confmute(p, 0);
07745       }
07746       p->subs[idx].f.frametype = AST_FRAME_NULL;
07747       p->subs[idx].f.subclass.integer = 0;
07748       *dest = &p->subs[idx].f;
07749    }
07750 }
07751 
07752 static void handle_alarms(struct dahdi_pvt *p, int alms)
07753 {
07754    const char *alarm_str = alarm2str(alms);
07755 
07756    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07757       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07758       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07759                  "Alarm: %s\r\n"
07760                  "Channel: %d\r\n",
07761                  alarm_str, p->channel);
07762    }
07763 
07764    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07765       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07766       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07767                  "Alarm: %s\r\n"
07768                  "Span: %d\r\n",
07769                  alarm_str, p->span);
07770    }
07771 }
07772 
07773 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07774 {
07775    int res, x;
07776    int idx, mysig;
07777    char *c;
07778    struct dahdi_pvt *p = ast->tech_pvt;
07779    pthread_t threadid;
07780    struct ast_channel *chan;
07781    struct ast_frame *f;
07782 
07783    idx = dahdi_get_index(ast, p, 0);
07784    mysig = p->sig;
07785    if (p->outsigmod > -1)
07786       mysig = p->outsigmod;
07787    p->subs[idx].f.frametype = AST_FRAME_NULL;
07788    p->subs[idx].f.subclass.integer = 0;
07789    p->subs[idx].f.datalen = 0;
07790    p->subs[idx].f.samples = 0;
07791    p->subs[idx].f.mallocd = 0;
07792    p->subs[idx].f.offset = 0;
07793    p->subs[idx].f.src = "dahdi_handle_event";
07794    p->subs[idx].f.data.ptr = NULL;
07795    f = &p->subs[idx].f;
07796 
07797    if (idx < 0)
07798       return &p->subs[idx].f;
07799    if (p->fake_event) {
07800       res = p->fake_event;
07801       p->fake_event = 0;
07802    } else
07803       res = dahdi_get_event(p->subs[idx].dfd);
07804 
07805    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07806 
07807    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07808       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07809       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07810 #if defined(HAVE_PRI)
07811       if (dahdi_sig_pri_lib_handles(p->sig)
07812          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07813          && p->pri
07814          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07815          /* absorb event */
07816       } else
07817 #endif   /* defined(HAVE_PRI) */
07818       {
07819          /* Unmute conference */
07820          dahdi_confmute(p, 0);
07821          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07822          p->subs[idx].f.subclass.integer = res & 0xff;
07823          dahdi_handle_dtmf(ast, idx, &f);
07824       }
07825       return f;
07826    }
07827 
07828    if (res & DAHDI_EVENT_DTMFDOWN) {
07829       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07830 #if defined(HAVE_PRI)
07831       if (dahdi_sig_pri_lib_handles(p->sig)
07832          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07833          && p->pri
07834          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07835          /* absorb event */
07836       } else
07837 #endif   /* defined(HAVE_PRI) */
07838       {
07839          /* Mute conference */
07840          dahdi_confmute(p, 1);
07841          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07842          p->subs[idx].f.subclass.integer = res & 0xff;
07843          dahdi_handle_dtmf(ast, idx, &f);
07844       }
07845       return &p->subs[idx].f;
07846    }
07847 
07848    switch (res) {
07849    case DAHDI_EVENT_EC_DISABLED:
07850       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07851       p->echocanon = 0;
07852       break;
07853 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07854    case DAHDI_EVENT_TX_CED_DETECTED:
07855       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07856       break;
07857    case DAHDI_EVENT_RX_CED_DETECTED:
07858       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07859       break;
07860    case DAHDI_EVENT_EC_NLP_DISABLED:
07861       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07862       break;
07863    case DAHDI_EVENT_EC_NLP_ENABLED:
07864       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07865       break;
07866 #endif
07867    case DAHDI_EVENT_BITSCHANGED:
07868 #ifdef HAVE_OPENR2
07869       if (p->sig != SIG_MFCR2) {
07870          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07871       } else {
07872          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07873          openr2_chan_handle_cas(p->r2chan);
07874       }
07875 #else
07876       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07877 #endif
07878    case DAHDI_EVENT_PULSE_START:
07879       /* Stop tone if there's a pulse start and the PBX isn't started */
07880       if (!ast->pbx)
07881          tone_zone_play_tone(p->subs[idx].dfd, -1);
07882       break;
07883    case DAHDI_EVENT_DIALCOMPLETE:
07884 #ifdef HAVE_OPENR2
07885       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07886          /* we don't need to do anything for this event for R2 signaling
07887             if the call is being setup */
07888          break;
07889       }
07890 #endif
07891       if (p->inalarm) break;
07892       if ((p->radio || (p->oprmode < 0))) break;
07893       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07894          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07895          return NULL;
07896       }
07897       if (!x) { /* if not still dialing in driver */
07898          dahdi_enable_ec(p);
07899          if (p->echobreak) {
07900             dahdi_train_ec(p);
07901             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07902             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07903             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07904             p->echobreak = 0;
07905          } else {
07906             p->dialing = 0;
07907             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07908                /* if thru with dialing after offhook */
07909                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07910                   ast_setstate(ast, AST_STATE_UP);
07911                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07912                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07913                   break;
07914                } else { /* if to state wait for offhook to dial rest */
07915                   /* we now wait for off hook */
07916                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07917                }
07918             }
07919             if (ast->_state == AST_STATE_DIALING) {
07920                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07921                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07922                } else if (p->confirmanswer || (!p->dialednone
07923                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07924                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07925                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07926                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07927                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07928                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07929                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07930                      || (mysig == SIG_SF_FEATB)))) {
07931                   ast_setstate(ast, AST_STATE_RINGING);
07932                } else if (!p->answeronpolarityswitch) {
07933                   ast_setstate(ast, AST_STATE_UP);
07934                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07935                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07936                   /* If aops=0 and hops=1, this is necessary */
07937                   p->polarity = POLARITY_REV;
07938                } else {
07939                   /* Start clean, so we can catch the change to REV polarity when party answers */
07940                   p->polarity = POLARITY_IDLE;
07941                }
07942             }
07943          }
07944       }
07945       break;
07946    case DAHDI_EVENT_ALARM:
07947       switch (p->sig) {
07948 #if defined(HAVE_PRI)
07949       case SIG_PRI_LIB_HANDLE_CASES:
07950          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07951          break;
07952 #endif   /* defined(HAVE_PRI) */
07953 #if defined(HAVE_SS7)
07954       case SIG_SS7:
07955          sig_ss7_set_alarm(p->sig_pvt, 1);
07956          break;
07957 #endif   /* defined(HAVE_SS7) */
07958       default:
07959          p->inalarm = 1;
07960          break;
07961       }
07962       res = get_alarms(p);
07963       handle_alarms(p, res);
07964 #ifdef HAVE_PRI
07965       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07966          /* fall through intentionally */
07967       } else {
07968          break;
07969       }
07970 #endif
07971 #if defined(HAVE_SS7)
07972       if (p->sig == SIG_SS7)
07973          break;
07974 #endif   /* defined(HAVE_SS7) */
07975 #ifdef HAVE_OPENR2
07976       if (p->sig == SIG_MFCR2)
07977          break;
07978 #endif
07979    case DAHDI_EVENT_ONHOOK:
07980       if (p->radio) {
07981          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07982          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07983          break;
07984       }
07985       if (p->oprmode < 0)
07986       {
07987          if (p->oprmode != -1) break;
07988          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07989          {
07990             /* Make sure it starts ringing */
07991             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07992             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07993             save_conference(p->oprpeer);
07994             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07995          }
07996          break;
07997       }
07998       switch (p->sig) {
07999       case SIG_FXOLS:
08000       case SIG_FXOGS:
08001       case SIG_FXOKS:
08002          /* Check for some special conditions regarding call waiting */
08003          if (idx == SUB_REAL) {
08004             /* The normal line was hung up */
08005             if (p->subs[SUB_CALLWAIT].owner) {
08006                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08007                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08008                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08009                unalloc_sub(p, SUB_CALLWAIT);
08010 #if 0
08011                p->subs[idx].needanswer = 0;
08012                p->subs[idx].needringing = 0;
08013 #endif
08014                p->callwaitingrepeat = 0;
08015                p->cidcwexpire = 0;
08016                p->cid_suppress_expire = 0;
08017                p->owner = NULL;
08018                /* Don't start streaming audio yet if the incoming call isn't up yet */
08019                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08020                   p->dialing = 1;
08021                dahdi_ring_phone(p);
08022             } else if (p->subs[SUB_THREEWAY].owner) {
08023                unsigned int mssinceflash;
08024                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08025                   the private structure -- not especially easy or clean */
08026                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08027                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08028                   DLA_UNLOCK(&p->lock);
08029                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08030                   /* We can grab ast and p in that order, without worry.  We should make sure
08031                      nothing seriously bad has happened though like some sort of bizarre double
08032                      masquerade! */
08033                   DLA_LOCK(&p->lock);
08034                   if (p->owner != ast) {
08035                      ast_log(LOG_WARNING, "This isn't good...\n");
08036                      return NULL;
08037                   }
08038                }
08039                if (!p->subs[SUB_THREEWAY].owner) {
08040                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08041                   return NULL;
08042                }
08043                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08044                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08045                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08046                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08047                      hanging up.  Hangup both channels now */
08048                   if (p->subs[SUB_THREEWAY].owner)
08049                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08050                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08051                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08052                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08053                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08054                   if (p->transfer) {
08055                      /* In any case this isn't a threeway call anymore */
08056                      p->subs[SUB_REAL].inthreeway = 0;
08057                      p->subs[SUB_THREEWAY].inthreeway = 0;
08058                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08059                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08060                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08061                         /* Swap subs and dis-own channel */
08062                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08063                         p->owner = NULL;
08064                         /* Ring the phone */
08065                         dahdi_ring_phone(p);
08066                      } else {
08067                         if ((res = attempt_transfer(p)) < 0) {
08068                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08069                            if (p->subs[SUB_THREEWAY].owner)
08070                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08071                         } else if (res) {
08072                            /* Don't actually hang up at this point */
08073                            if (p->subs[SUB_THREEWAY].owner)
08074                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08075                            break;
08076                         }
08077                      }
08078                   } else {
08079                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08080                      if (p->subs[SUB_THREEWAY].owner)
08081                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08082                   }
08083                } else {
08084                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08085                   /* Swap subs and dis-own channel */
08086                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08087                   p->owner = NULL;
08088                   /* Ring the phone */
08089                   dahdi_ring_phone(p);
08090                }
08091             }
08092          } else {
08093             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08094          }
08095          /* Fall through */
08096       default:
08097          dahdi_disable_ec(p);
08098          return NULL;
08099       }
08100       break;
08101    case DAHDI_EVENT_RINGOFFHOOK:
08102       if (p->inalarm) break;
08103       if (p->oprmode < 0)
08104       {
08105          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08106          {
08107             /* Make sure it stops ringing */
08108             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08109             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08110             restore_conference(p->oprpeer);
08111          }
08112          break;
08113       }
08114       if (p->radio)
08115       {
08116          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08117          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08118          break;
08119       }
08120       /* for E911, its supposed to wait for offhook then dial
08121          the second half of the dial string */
08122       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08123          c = strchr(p->dialdest, '/');
08124          if (c)
08125             c++;
08126          else
08127             c = p->dialdest;
08128          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08129          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08130          if (strlen(p->dop.dialstr) > 4) {
08131             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08132             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08133             p->echorest[sizeof(p->echorest) - 1] = '\0';
08134             p->echobreak = 1;
08135             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08136          } else
08137             p->echobreak = 0;
08138          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08139             int saveerr = errno;
08140 
08141             x = DAHDI_ONHOOK;
08142             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08143             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08144             return NULL;
08145             }
08146          p->dialing = 1;
08147          return &p->subs[idx].f;
08148       }
08149       switch (p->sig) {
08150       case SIG_FXOLS:
08151       case SIG_FXOGS:
08152       case SIG_FXOKS:
08153          switch (ast->_state) {
08154          case AST_STATE_RINGING:
08155             dahdi_enable_ec(p);
08156             dahdi_train_ec(p);
08157             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08158             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08159             /* Make sure it stops ringing */
08160             p->subs[SUB_REAL].needringing = 0;
08161             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08162             ast_debug(1, "channel %d answered\n", p->channel);
08163 
08164             /* Cancel any running CallerID spill */
08165             ast_free(p->cidspill);
08166             p->cidspill = NULL;
08167             restore_conference(p);
08168 
08169             p->dialing = 0;
08170             p->callwaitcas = 0;
08171             if (p->confirmanswer) {
08172                /* Ignore answer if "confirm answer" is enabled */
08173                p->subs[idx].f.frametype = AST_FRAME_NULL;
08174                p->subs[idx].f.subclass.integer = 0;
08175             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08176                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08177                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08178                if (res < 0) {
08179                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08180                   p->dop.dialstr[0] = '\0';
08181                   return NULL;
08182                } else {
08183                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08184                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08185                   p->subs[idx].f.subclass.integer = 0;
08186                   p->dialing = 1;
08187                }
08188                p->dop.dialstr[0] = '\0';
08189                ast_setstate(ast, AST_STATE_DIALING);
08190             } else
08191                ast_setstate(ast, AST_STATE_UP);
08192             return &p->subs[idx].f;
08193          case AST_STATE_DOWN:
08194             ast_setstate(ast, AST_STATE_RING);
08195             ast->rings = 1;
08196             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08197             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08198             ast_debug(1, "channel %d picked up\n", p->channel);
08199             return &p->subs[idx].f;
08200          case AST_STATE_UP:
08201             /* Make sure it stops ringing */
08202             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08203             /* Okay -- probably call waiting*/
08204             if (ast_bridged_channel(p->owner))
08205                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08206             p->subs[idx].needunhold = 1;
08207             break;
08208          case AST_STATE_RESERVED:
08209             /* Start up dialtone */
08210             if (has_voicemail(p))
08211                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08212             else
08213                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08214             break;
08215          default:
08216             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08217          }
08218          break;
08219       case SIG_FXSLS:
08220       case SIG_FXSGS:
08221       case SIG_FXSKS:
08222          if (ast->_state == AST_STATE_RING) {
08223             p->ringt = p->ringt_base;
08224          }
08225 
08226          /* If we get a ring then we cannot be in
08227           * reversed polarity. So we reset to idle */
08228          ast_debug(1, "Setting IDLE polarity due "
08229             "to ring. Old polarity was %d\n",
08230             p->polarity);
08231          p->polarity = POLARITY_IDLE;
08232 
08233          /* Fall through */
08234       case SIG_EM:
08235       case SIG_EM_E1:
08236       case SIG_EMWINK:
08237       case SIG_FEATD:
08238       case SIG_FEATDMF:
08239       case SIG_FEATDMF_TA:
08240       case SIG_E911:
08241       case SIG_FGC_CAMA:
08242       case SIG_FGC_CAMAMF:
08243       case SIG_FEATB:
08244       case SIG_SF:
08245       case SIG_SFWINK:
08246       case SIG_SF_FEATD:
08247       case SIG_SF_FEATDMF:
08248       case SIG_SF_FEATB:
08249          if (ast->_state == AST_STATE_PRERING)
08250             ast_setstate(ast, AST_STATE_RING);
08251          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08252             ast_debug(1, "Ring detected\n");
08253             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08254             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08255          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08256             ast_debug(1, "Line answered\n");
08257             if (p->confirmanswer) {
08258                p->subs[idx].f.frametype = AST_FRAME_NULL;
08259                p->subs[idx].f.subclass.integer = 0;
08260             } else {
08261                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08262                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08263                ast_setstate(ast, AST_STATE_UP);
08264             }
08265          } else if (ast->_state != AST_STATE_RING)
08266             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08267          break;
08268       default:
08269          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08270       }
08271       break;
08272    case DAHDI_EVENT_RINGBEGIN:
08273       switch (p->sig) {
08274       case SIG_FXSLS:
08275       case SIG_FXSGS:
08276       case SIG_FXSKS:
08277          if (ast->_state == AST_STATE_RING) {
08278             p->ringt = p->ringt_base;
08279          }
08280          break;
08281       }
08282       break;
08283    case DAHDI_EVENT_RINGERON:
08284       break;
08285    case DAHDI_EVENT_NOALARM:
08286       switch (p->sig) {
08287 #if defined(HAVE_PRI)
08288       case SIG_PRI_LIB_HANDLE_CASES:
08289          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08290          break;
08291 #endif   /* defined(HAVE_PRI) */
08292 #if defined(HAVE_SS7)
08293       case SIG_SS7:
08294          sig_ss7_set_alarm(p->sig_pvt, 0);
08295          break;
08296 #endif   /* defined(HAVE_SS7) */
08297       default:
08298          p->inalarm = 0;
08299          break;
08300       }
08301       handle_clear_alarms(p);
08302       break;
08303    case DAHDI_EVENT_WINKFLASH:
08304       if (p->inalarm) break;
08305       if (p->radio) break;
08306       if (p->oprmode < 0) break;
08307       if (p->oprmode > 1)
08308       {
08309          struct dahdi_params par;
08310 
08311          memset(&par, 0, sizeof(par));
08312          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08313          {
08314             if (!par.rxisoffhook)
08315             {
08316                /* Make sure it stops ringing */
08317                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08318                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08319                save_conference(p);
08320                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08321             }
08322          }
08323          break;
08324       }
08325       /* Remember last time we got a flash-hook */
08326       p->flashtime = ast_tvnow();
08327       switch (mysig) {
08328       case SIG_FXOLS:
08329       case SIG_FXOGS:
08330       case SIG_FXOKS:
08331          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08332             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08333 
08334          /* Cancel any running CallerID spill */
08335          ast_free(p->cidspill);
08336          p->cidspill = NULL;
08337          restore_conference(p);
08338          p->callwaitcas = 0;
08339 
08340          if (idx != SUB_REAL) {
08341             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08342             goto winkflashdone;
08343          }
08344 
08345          if (p->subs[SUB_CALLWAIT].owner) {
08346             /* Swap to call-wait */
08347             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08348             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08349             p->owner = p->subs[SUB_REAL].owner;
08350             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08351             if (p->owner->_state == AST_STATE_RINGING) {
08352                ast_setstate(p->owner, AST_STATE_UP);
08353                p->subs[SUB_REAL].needanswer = 1;
08354             }
08355             p->callwaitingrepeat = 0;
08356             p->cidcwexpire = 0;
08357             p->cid_suppress_expire = 0;
08358             /* Start music on hold if appropriate */
08359             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08360                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08361                   S_OR(p->mohsuggest, NULL),
08362                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08363             }
08364             p->subs[SUB_CALLWAIT].needhold = 1;
08365             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08366                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08367                   S_OR(p->mohsuggest, NULL),
08368                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08369             }
08370             p->subs[SUB_REAL].needunhold = 1;
08371          } else if (!p->subs[SUB_THREEWAY].owner) {
08372             if (!p->threewaycalling) {
08373                /* Just send a flash if no 3-way calling */
08374                p->subs[SUB_REAL].needflash = 1;
08375                goto winkflashdone;
08376             } else if (!check_for_conference(p)) {
08377                char cid_num[256];
08378                char cid_name[256];
08379 
08380                cid_num[0] = 0;
08381                cid_name[0] = 0;
08382                if (p->dahditrcallerid && p->owner) {
08383                   if (p->owner->caller.id.number.valid
08384                      && p->owner->caller.id.number.str) {
08385                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08386                         sizeof(cid_num));
08387                   }
08388                   if (p->owner->caller.id.name.valid
08389                      && p->owner->caller.id.name.str) {
08390                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08391                         sizeof(cid_name));
08392                   }
08393                }
08394                /* XXX This section needs much more error checking!!! XXX */
08395                /* Start a 3-way call if feasible */
08396                if (!((ast->pbx) ||
08397                   (ast->_state == AST_STATE_UP) ||
08398                   (ast->_state == AST_STATE_RING))) {
08399                   ast_debug(1, "Flash when call not up or ringing\n");
08400                   goto winkflashdone;
08401                }
08402                if (alloc_sub(p, SUB_THREEWAY)) {
08403                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08404                   goto winkflashdone;
08405                }
08406                /* Make new channel */
08407                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08408                if (p->dahditrcallerid) {
08409                   if (!p->origcid_num)
08410                      p->origcid_num = ast_strdup(p->cid_num);
08411                   if (!p->origcid_name)
08412                      p->origcid_name = ast_strdup(p->cid_name);
08413                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08414                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08415                }
08416                /* Swap things around between the three-way and real call */
08417                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08418                /* Disable echo canceller for better dialing */
08419                dahdi_disable_ec(p);
08420                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08421                if (res)
08422                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08423                p->owner = chan;
08424                if (!chan) {
08425                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08426                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08427                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08428                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08429                   dahdi_enable_ec(p);
08430                   ast_hangup(chan);
08431                } else {
08432                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08433 
08434                   /* Start music on hold if appropriate */
08435                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08436                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08437                         S_OR(p->mohsuggest, NULL),
08438                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08439                   }
08440                   p->subs[SUB_THREEWAY].needhold = 1;
08441                }
08442             }
08443          } else {
08444             /* Already have a 3 way call */
08445             if (p->subs[SUB_THREEWAY].inthreeway) {
08446                /* Call is already up, drop the last person */
08447                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08448                /* If the primary call isn't answered yet, use it */
08449                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08450                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08451                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08452                   p->owner = p->subs[SUB_REAL].owner;
08453                }
08454                /* Drop the last call and stop the conference */
08455                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08456                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08457                p->subs[SUB_REAL].inthreeway = 0;
08458                p->subs[SUB_THREEWAY].inthreeway = 0;
08459             } else {
08460                /* Lets see what we're up to */
08461                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08462                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08463                   int otherindex = SUB_THREEWAY;
08464 
08465                   ast_verb(3, "Building conference call with %s and %s\n",
08466                      p->subs[SUB_THREEWAY].owner->name,
08467                      p->subs[SUB_REAL].owner->name);
08468                   /* Put them in the threeway, and flip */
08469                   p->subs[SUB_THREEWAY].inthreeway = 1;
08470                   p->subs[SUB_REAL].inthreeway = 1;
08471                   if (ast->_state == AST_STATE_UP) {
08472                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08473                      otherindex = SUB_REAL;
08474                   }
08475                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08476                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08477                   p->subs[otherindex].needunhold = 1;
08478                   p->owner = p->subs[SUB_REAL].owner;
08479                } else {
08480                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08481                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08482                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08483                   p->owner = p->subs[SUB_REAL].owner;
08484                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08485                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08486                   p->subs[SUB_REAL].needunhold = 1;
08487                   dahdi_enable_ec(p);
08488                }
08489             }
08490          }
08491 winkflashdone:
08492          update_conf(p);
08493          break;
08494       case SIG_EM:
08495       case SIG_EM_E1:
08496       case SIG_FEATD:
08497       case SIG_SF:
08498       case SIG_SFWINK:
08499       case SIG_SF_FEATD:
08500       case SIG_FXSLS:
08501       case SIG_FXSGS:
08502          if (p->dialing)
08503             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08504          else
08505             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08506          break;
08507       case SIG_FEATDMF_TA:
08508          switch (p->whichwink) {
08509          case 0:
08510             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08511                S_COR(p->owner->caller.ani.number.valid,
08512                   p->owner->caller.ani.number.str, ""));
08513             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08514                p->owner->caller.ani2,
08515                S_COR(p->owner->caller.ani.number.valid,
08516                   p->owner->caller.ani.number.str, ""));
08517             break;
08518          case 1:
08519             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08520             break;
08521          case 2:
08522             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08523             return NULL;
08524          }
08525          p->whichwink++;
08526          /* Fall through */
08527       case SIG_FEATDMF:
08528       case SIG_E911:
08529       case SIG_FGC_CAMAMF:
08530       case SIG_FGC_CAMA:
08531       case SIG_FEATB:
08532       case SIG_SF_FEATDMF:
08533       case SIG_SF_FEATB:
08534       case SIG_EMWINK:
08535          /* FGD MF and EMWINK *Must* wait for wink */
08536          if (!ast_strlen_zero(p->dop.dialstr)) {
08537             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08538             if (res < 0) {
08539                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08540                p->dop.dialstr[0] = '\0';
08541                return NULL;
08542             } else
08543                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08544          }
08545          p->dop.dialstr[0] = '\0';
08546          break;
08547       default:
08548          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08549       }
08550       break;
08551    case DAHDI_EVENT_HOOKCOMPLETE:
08552       if (p->inalarm) break;
08553       if ((p->radio || (p->oprmode < 0))) break;
08554       if (p->waitingfordt.tv_sec) break;
08555       switch (mysig) {
08556       case SIG_FXSLS:  /* only interesting for FXS */
08557       case SIG_FXSGS:
08558       case SIG_FXSKS:
08559       case SIG_EM:
08560       case SIG_EM_E1:
08561       case SIG_EMWINK:
08562       case SIG_FEATD:
08563       case SIG_SF:
08564       case SIG_SFWINK:
08565       case SIG_SF_FEATD:
08566          if (!ast_strlen_zero(p->dop.dialstr)) {
08567             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08568             if (res < 0) {
08569                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08570                p->dop.dialstr[0] = '\0';
08571                return NULL;
08572             } else
08573                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08574          }
08575          p->dop.dialstr[0] = '\0';
08576          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08577          break;
08578       case SIG_FEATDMF:
08579       case SIG_FEATDMF_TA:
08580       case SIG_E911:
08581       case SIG_FGC_CAMA:
08582       case SIG_FGC_CAMAMF:
08583       case SIG_FEATB:
08584       case SIG_SF_FEATDMF:
08585       case SIG_SF_FEATB:
08586          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08587          break;
08588       default:
08589          break;
08590       }
08591       break;
08592    case DAHDI_EVENT_POLARITY:
08593       /*
08594        * If we get a Polarity Switch event, check to see
08595        * if we should change the polarity state and
08596        * mark the channel as UP or if this is an indication
08597        * of remote end disconnect.
08598        */
08599       if (p->polarity == POLARITY_IDLE) {
08600          p->polarity = POLARITY_REV;
08601          if (p->answeronpolarityswitch &&
08602             ((ast->_state == AST_STATE_DIALING) ||
08603             (ast->_state == AST_STATE_RINGING))) {
08604             ast_debug(1, "Answering on polarity switch!\n");
08605             ast_setstate(p->owner, AST_STATE_UP);
08606             if (p->hanguponpolarityswitch) {
08607                p->polaritydelaytv = ast_tvnow();
08608             }
08609          } else
08610             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08611       }
08612       /* Removed else statement from here as it was preventing hangups from ever happening*/
08613       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08614       if (p->hanguponpolarityswitch &&
08615          (p->polarityonanswerdelay > 0) &&
08616          (p->polarity == POLARITY_REV) &&
08617          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08618          /* Added log_debug information below to provide a better indication of what is going on */
08619          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) );
08620 
08621          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08622             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08623             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08624             p->polarity = POLARITY_IDLE;
08625          } else
08626             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);
08627 
08628       } else {
08629          p->polarity = POLARITY_IDLE;
08630          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08631       }
08632       /* Added more log_debug information below to provide a better indication of what is going on */
08633       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) );
08634       break;
08635    default:
08636       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08637    }
08638    return &p->subs[idx].f;
08639 }
08640 
08641 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08642 {
08643    int res;
08644    int idx;
08645    struct ast_frame *f;
08646    int usedindex = -1;
08647    struct dahdi_pvt *p = ast->tech_pvt;
08648 
08649    idx = dahdi_get_index(ast, p, 1);
08650 
08651    p->subs[idx].f.frametype = AST_FRAME_NULL;
08652    p->subs[idx].f.datalen = 0;
08653    p->subs[idx].f.samples = 0;
08654    p->subs[idx].f.mallocd = 0;
08655    p->subs[idx].f.offset = 0;
08656    p->subs[idx].f.subclass.integer = 0;
08657    p->subs[idx].f.delivery = ast_tv(0,0);
08658    p->subs[idx].f.src = "dahdi_exception";
08659    p->subs[idx].f.data.ptr = NULL;
08660 
08661 
08662    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08663       /* If nobody owns us, absorb the event appropriately, otherwise
08664          we loop indefinitely.  This occurs when, during call waiting, the
08665          other end hangs up our channel so that it no longer exists, but we
08666          have neither FLASH'd nor ONHOOK'd to signify our desire to
08667          change to the other channel. */
08668       if (p->fake_event) {
08669          res = p->fake_event;
08670          p->fake_event = 0;
08671       } else
08672          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08673       /* Switch to real if there is one and this isn't something really silly... */
08674       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08675          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08676          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08677          p->owner = p->subs[SUB_REAL].owner;
08678          if (p->owner && ast_bridged_channel(p->owner))
08679             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08680          p->subs[SUB_REAL].needunhold = 1;
08681       }
08682       switch (res) {
08683       case DAHDI_EVENT_ONHOOK:
08684          dahdi_disable_ec(p);
08685          if (p->owner) {
08686             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08687             dahdi_ring_phone(p);
08688             p->callwaitingrepeat = 0;
08689             p->cidcwexpire = 0;
08690             p->cid_suppress_expire = 0;
08691          } else
08692             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08693          update_conf(p);
08694          break;
08695       case DAHDI_EVENT_RINGOFFHOOK:
08696          dahdi_enable_ec(p);
08697          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08698          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08699             p->subs[SUB_REAL].needanswer = 1;
08700             p->dialing = 0;
08701          }
08702          break;
08703       case DAHDI_EVENT_HOOKCOMPLETE:
08704       case DAHDI_EVENT_RINGERON:
08705       case DAHDI_EVENT_RINGEROFF:
08706          /* Do nothing */
08707          break;
08708       case DAHDI_EVENT_WINKFLASH:
08709          p->flashtime = ast_tvnow();
08710          if (p->owner) {
08711             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08712             if (p->owner->_state != AST_STATE_UP) {
08713                /* Answer if necessary */
08714                usedindex = dahdi_get_index(p->owner, p, 0);
08715                if (usedindex > -1) {
08716                   p->subs[usedindex].needanswer = 1;
08717                }
08718                ast_setstate(p->owner, AST_STATE_UP);
08719             }
08720             p->callwaitingrepeat = 0;
08721             p->cidcwexpire = 0;
08722             p->cid_suppress_expire = 0;
08723             if (ast_bridged_channel(p->owner))
08724                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08725             p->subs[SUB_REAL].needunhold = 1;
08726          } else
08727             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08728          update_conf(p);
08729          break;
08730       default:
08731          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08732       }
08733       f = &p->subs[idx].f;
08734       return f;
08735    }
08736    if (!(p->radio || (p->oprmode < 0)))
08737       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08738    /* If it's not us, return NULL immediately */
08739    if (ast != p->owner) {
08740       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08741       f = &p->subs[idx].f;
08742       return f;
08743    }
08744    f = dahdi_handle_event(ast);
08745 
08746    /* tell the cdr this zap device hung up */
08747    if (f == NULL) {
08748       ast_set_hangupsource(ast, ast->name, 0);
08749    }
08750 
08751    return f;
08752 }
08753 
08754 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08755 {
08756    struct dahdi_pvt *p = ast->tech_pvt;
08757    struct ast_frame *f;
08758    ast_mutex_lock(&p->lock);
08759    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08760       struct analog_pvt *analog_p = p->sig_pvt;
08761       f = analog_exception(analog_p, ast);
08762    } else {
08763       f = __dahdi_exception(ast);
08764    }
08765    ast_mutex_unlock(&p->lock);
08766    return f;
08767 }
08768 
08769 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08770 {
08771    struct dahdi_pvt *p;
08772    int res;
08773    int idx;
08774    void *readbuf;
08775    struct ast_frame *f;
08776 
08777    /*
08778     * For analog channels, we must do deadlock avoidance because
08779     * analog ports can have more than one Asterisk channel using
08780     * the same private structure.
08781     */
08782    p = ast->tech_pvt;
08783    while (ast_mutex_trylock(&p->lock)) {
08784       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08785 
08786       /*
08787        * For PRI channels, we must refresh the private pointer because
08788        * the call could move to another B channel while the Asterisk
08789        * channel is unlocked.
08790        */
08791       p = ast->tech_pvt;
08792    }
08793 
08794    idx = dahdi_get_index(ast, p, 0);
08795 
08796    /* Hang up if we don't really exist */
08797    if (idx < 0)   {
08798       ast_log(LOG_WARNING, "We don't exist?\n");
08799       ast_mutex_unlock(&p->lock);
08800       return NULL;
08801    }
08802 
08803    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08804       ast_mutex_unlock(&p->lock);
08805       return NULL;
08806    }
08807 
08808    p->subs[idx].f.frametype = AST_FRAME_NULL;
08809    p->subs[idx].f.datalen = 0;
08810    p->subs[idx].f.samples = 0;
08811    p->subs[idx].f.mallocd = 0;
08812    p->subs[idx].f.offset = 0;
08813    p->subs[idx].f.subclass.integer = 0;
08814    p->subs[idx].f.delivery = ast_tv(0,0);
08815    p->subs[idx].f.src = "dahdi_read";
08816    p->subs[idx].f.data.ptr = NULL;
08817 
08818    /* make sure it sends initial key state as first frame */
08819    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08820    {
08821       struct dahdi_params ps;
08822 
08823       memset(&ps, 0, sizeof(ps));
08824       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08825          ast_mutex_unlock(&p->lock);
08826          return NULL;
08827       }
08828       p->firstradio = 1;
08829       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08830       if (ps.rxisoffhook)
08831       {
08832          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08833       }
08834       else
08835       {
08836          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08837       }
08838       ast_mutex_unlock(&p->lock);
08839       return &p->subs[idx].f;
08840    }
08841    if (p->ringt > 0) {
08842       if (!(--p->ringt)) {
08843          ast_mutex_unlock(&p->lock);
08844          return NULL;
08845       }
08846    }
08847 
08848 #ifdef HAVE_OPENR2
08849    if (p->mfcr2) {
08850       openr2_chan_process_event(p->r2chan);
08851       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08852          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08853          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08854           * now enqueue a progress frame to bridge the media up */
08855          if (p->mfcr2_call_accepted &&
08856              !p->mfcr2_progress && 
08857              ast->_state == AST_STATE_RINGING) {
08858             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08859             ast_queue_frame(p->owner, &f);
08860             p->mfcr2_progress = 1;
08861          }
08862       }
08863    }
08864 #endif
08865 
08866    if (p->subs[idx].needringing) {
08867       /* Send ringing frame if requested */
08868       p->subs[idx].needringing = 0;
08869       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08870       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08871       ast_setstate(ast, AST_STATE_RINGING);
08872       ast_mutex_unlock(&p->lock);
08873       return &p->subs[idx].f;
08874    }
08875 
08876    if (p->subs[idx].needbusy) {
08877       /* Send busy frame if requested */
08878       p->subs[idx].needbusy = 0;
08879       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08880       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08881       ast_mutex_unlock(&p->lock);
08882       return &p->subs[idx].f;
08883    }
08884 
08885    if (p->subs[idx].needcongestion) {
08886       /* Send congestion frame if requested */
08887       p->subs[idx].needcongestion = 0;
08888       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08889       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08890       ast_mutex_unlock(&p->lock);
08891       return &p->subs[idx].f;
08892    }
08893 
08894    if (p->subs[idx].needanswer) {
08895       /* Send answer frame if requested */
08896       p->subs[idx].needanswer = 0;
08897       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08898       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08899       ast_mutex_unlock(&p->lock);
08900       return &p->subs[idx].f;
08901    }
08902 #ifdef HAVE_OPENR2
08903    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08904       /* openr2 took care of reading and handling any event
08905         (needanswer, needbusy etc), if we continue we will read()
08906         twice, lets just return a null frame. This should only
08907         happen when openr2 is dialing out */
08908       ast_mutex_unlock(&p->lock);
08909       return &ast_null_frame;
08910    }
08911 #endif
08912 
08913    if (p->subs[idx].needflash) {
08914       /* Send answer frame if requested */
08915       p->subs[idx].needflash = 0;
08916       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08917       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08918       ast_mutex_unlock(&p->lock);
08919       return &p->subs[idx].f;
08920    }
08921 
08922    if (p->subs[idx].needhold) {
08923       /* Send answer frame if requested */
08924       p->subs[idx].needhold = 0;
08925       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08926       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08927       ast_mutex_unlock(&p->lock);
08928       ast_debug(1, "Sending hold on '%s'\n", ast->name);
08929       return &p->subs[idx].f;
08930    }
08931 
08932    if (p->subs[idx].needunhold) {
08933       /* Send answer frame if requested */
08934       p->subs[idx].needunhold = 0;
08935       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08936       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08937       ast_mutex_unlock(&p->lock);
08938       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08939       return &p->subs[idx].f;
08940    }
08941 
08942    /*
08943     * If we have a fake_event, fake an exception to handle it only
08944     * if this channel owns the private.
08945     */
08946    if (p->fake_event && p->owner == ast) {
08947       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08948          struct analog_pvt *analog_p = p->sig_pvt;
08949 
08950          f = analog_exception(analog_p, ast);
08951       } else {
08952          f = __dahdi_exception(ast);
08953       }
08954       ast_mutex_unlock(&p->lock);
08955       return f;
08956    }
08957 
08958    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08959       if (!p->subs[idx].linear) {
08960          p->subs[idx].linear = 1;
08961          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08962          if (res)
08963             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08964       }
08965    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08966       (ast->rawreadformat == AST_FORMAT_ALAW)) {
08967       if (p->subs[idx].linear) {
08968          p->subs[idx].linear = 0;
08969          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08970          if (res)
08971             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08972       }
08973    } else {
08974       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08975       ast_mutex_unlock(&p->lock);
08976       return NULL;
08977    }
08978    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08979    CHECK_BLOCKING(ast);
08980    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08981    ast_clear_flag(ast, AST_FLAG_BLOCKING);
08982    /* Check for hangup */
08983    if (res < 0) {
08984       f = NULL;
08985       if (res == -1) {
08986          if (errno == EAGAIN) {
08987             /* Return "NULL" frame if there is nobody there */
08988             ast_mutex_unlock(&p->lock);
08989             return &p->subs[idx].f;
08990          } else if (errno == ELAST) {
08991             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08992                struct analog_pvt *analog_p = p->sig_pvt;
08993                f = analog_exception(analog_p, ast);
08994             } else {
08995                f = __dahdi_exception(ast);
08996             }
08997          } else
08998             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08999       }
09000       ast_mutex_unlock(&p->lock);
09001       return f;
09002    }
09003    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09004       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09005       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09006          struct analog_pvt *analog_p = p->sig_pvt;
09007          f = analog_exception(analog_p, ast);
09008       } else {
09009          f = __dahdi_exception(ast);
09010       }
09011       ast_mutex_unlock(&p->lock);
09012       return f;
09013    }
09014    if (p->tdd) { /* if in TDD mode, see if we receive that */
09015       int c;
09016 
09017       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09018       if (c < 0) {
09019          ast_debug(1,"tdd_feed failed\n");
09020          ast_mutex_unlock(&p->lock);
09021          return NULL;
09022       }
09023       if (c) { /* if a char to return */
09024          p->subs[idx].f.subclass.integer = 0;
09025          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09026          p->subs[idx].f.mallocd = 0;
09027          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09028          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09029          p->subs[idx].f.datalen = 1;
09030          *((char *) p->subs[idx].f.data.ptr) = c;
09031          ast_mutex_unlock(&p->lock);
09032          return &p->subs[idx].f;
09033       }
09034    }
09035    if (idx == SUB_REAL) {
09036       /* Ensure the CW timers decrement only on a single subchannel */
09037       if (p->cidcwexpire) {
09038          if (!--p->cidcwexpire) {
09039             /* Expired CID/CW */
09040             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09041             restore_conference(p);
09042          }
09043       }
09044       if (p->cid_suppress_expire) {
09045          --p->cid_suppress_expire;
09046       }
09047       if (p->callwaitingrepeat) {
09048          if (!--p->callwaitingrepeat) {
09049             /* Expired, Repeat callwaiting tone */
09050             ++p->callwaitrings;
09051             dahdi_callwait(ast);
09052          }
09053       }
09054    }
09055    if (p->subs[idx].linear) {
09056       p->subs[idx].f.datalen = READ_SIZE * 2;
09057    } else
09058       p->subs[idx].f.datalen = READ_SIZE;
09059 
09060    /* Handle CallerID Transmission */
09061    if ((p->owner == ast) && p->cidspill) {
09062       send_callerid(p);
09063    }
09064 
09065    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09066    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09067    p->subs[idx].f.samples = READ_SIZE;
09068    p->subs[idx].f.mallocd = 0;
09069    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09070    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09071 #if 0
09072    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09073 #endif
09074    if (p->dialing ||  p->radio || /* Transmitting something */
09075       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09076       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09077       ) {
09078       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09079          don't send anything */
09080       p->subs[idx].f.frametype = AST_FRAME_NULL;
09081       p->subs[idx].f.subclass.integer = 0;
09082       p->subs[idx].f.samples = 0;
09083       p->subs[idx].f.mallocd = 0;
09084       p->subs[idx].f.offset = 0;
09085       p->subs[idx].f.data.ptr = NULL;
09086       p->subs[idx].f.datalen= 0;
09087    }
09088    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09089       /* Perform busy detection etc on the dahdi line */
09090       int mute;
09091 
09092       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09093 
09094       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09095       mute = ast_dsp_was_muted(p->dsp);
09096       if (p->muting != mute) {
09097          p->muting = mute;
09098          dahdi_confmute(p, mute);
09099       }
09100 
09101       if (f) {
09102          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09103             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09104                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09105                   a busy */
09106                f = NULL;
09107             }
09108          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09109             || f->frametype == AST_FRAME_DTMF_END) {
09110 #ifdef HAVE_PRI
09111             if (dahdi_sig_pri_lib_handles(p->sig)
09112                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09113                && p->pri
09114                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09115                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09116                /* Don't accept in-band DTMF when in overlap dial mode */
09117                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09118                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09119                   f->subclass.integer, f->subclass.integer, ast->name);
09120 
09121                f->frametype = AST_FRAME_NULL;
09122                f->subclass.integer = 0;
09123             }
09124 #endif
09125             /* DSP clears us of being pulse */
09126             p->pulsedial = 0;
09127          } else if (p->waitingfordt.tv_sec) {
09128             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09129                p->waitingfordt.tv_sec = 0;
09130                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09131                f=NULL;
09132             } else if (f->frametype == AST_FRAME_VOICE) {
09133                f->frametype = AST_FRAME_NULL;
09134                f->subclass.integer = 0;
09135                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) {
09136                   p->waitingfordt.tv_sec = 0;
09137                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09138                   ast_dsp_set_features(p->dsp, p->dsp_features);
09139                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09140                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09141                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09142                      if (res < 0) {
09143                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09144                         p->dop.dialstr[0] = '\0';
09145                         ast_mutex_unlock(&p->lock);
09146                         return NULL;
09147                      } else {
09148                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09149                         p->dialing = 1;
09150                         p->dop.dialstr[0] = '\0';
09151                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09152                         ast_setstate(ast, AST_STATE_DIALING);
09153                      }
09154                   }
09155                }
09156             }
09157          }
09158       }
09159    } else
09160       f = &p->subs[idx].f;
09161 
09162    if (f) {
09163       switch (f->frametype) {
09164       case AST_FRAME_DTMF_BEGIN:
09165       case AST_FRAME_DTMF_END:
09166          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09167             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09168          } else {
09169             dahdi_handle_dtmf(ast, idx, &f);
09170          }
09171          break;
09172       case AST_FRAME_VOICE:
09173          if (p->cidspill || p->cid_suppress_expire) {
09174             /* We are/were sending a caller id spill.  Suppress any echo. */
09175             p->subs[idx].f.frametype = AST_FRAME_NULL;
09176             p->subs[idx].f.subclass.integer = 0;
09177             p->subs[idx].f.samples = 0;
09178             p->subs[idx].f.mallocd = 0;
09179             p->subs[idx].f.offset = 0;
09180             p->subs[idx].f.data.ptr = NULL;
09181             p->subs[idx].f.datalen= 0;
09182          }
09183          break;
09184       default:
09185          break;
09186       }
09187    }
09188 
09189    ast_mutex_unlock(&p->lock);
09190    return f;
09191 }
09192 
09193 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09194 {
09195    int sent=0;
09196    int size;
09197    int res;
09198    int fd;
09199    fd = p->subs[idx].dfd;
09200    while (len) {
09201       size = len;
09202       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09203          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09204       res = write(fd, buf, size);
09205       if (res != size) {
09206          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09207          return sent;
09208       }
09209       len -= size;
09210       buf += size;
09211    }
09212    return sent;
09213 }
09214 
09215 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09216 {
09217    struct dahdi_pvt *p = ast->tech_pvt;
09218    int res;
09219    int idx;
09220    idx = dahdi_get_index(ast, p, 0);
09221    if (idx < 0) {
09222       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09223       return -1;
09224    }
09225 
09226    /* Write a frame of (presumably voice) data */
09227    if (frame->frametype != AST_FRAME_VOICE) {
09228       if (frame->frametype != AST_FRAME_IMAGE)
09229          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09230       return 0;
09231    }
09232    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09233       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09234       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09235       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09236       return -1;
09237    }
09238    if (p->dialing) {
09239       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09240       return 0;
09241    }
09242    if (!p->owner) {
09243       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09244       return 0;
09245    }
09246    if (p->cidspill) {
09247       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09248          ast->name);
09249       return 0;
09250    }
09251    /* Return if it's not valid data */
09252    if (!frame->data.ptr || !frame->datalen)
09253       return 0;
09254 
09255    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09256       if (!p->subs[idx].linear) {
09257          p->subs[idx].linear = 1;
09258          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09259          if (res)
09260             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09261       }
09262       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09263    } else {
09264       /* x-law already */
09265       if (p->subs[idx].linear) {
09266          p->subs[idx].linear = 0;
09267          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09268          if (res)
09269             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09270       }
09271       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09272    }
09273    if (res < 0) {
09274       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09275       return -1;
09276    }
09277    return 0;
09278 }
09279 
09280 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09281 {
09282    struct dahdi_pvt *p = chan->tech_pvt;
09283    int res=-1;
09284    int idx;
09285    int func = DAHDI_FLASH;
09286 
09287    ast_mutex_lock(&p->lock);
09288    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09289    switch (p->sig) {
09290 #if defined(HAVE_PRI)
09291    case SIG_PRI_LIB_HANDLE_CASES:
09292       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09293       ast_mutex_unlock(&p->lock);
09294       return res;
09295 #endif   /* defined(HAVE_PRI) */
09296 #if defined(HAVE_SS7)
09297    case SIG_SS7:
09298       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09299       ast_mutex_unlock(&p->lock);
09300       return res;
09301 #endif   /* defined(HAVE_SS7) */
09302    default:
09303       break;
09304    }
09305 #ifdef HAVE_OPENR2
09306    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09307       ast_mutex_unlock(&p->lock);
09308       /* if this is an R2 call and the call is not yet accepted, we don't want the
09309          tone indications to mess up with the MF tones */
09310       return 0;
09311    }
09312 #endif
09313    idx = dahdi_get_index(chan, p, 0);
09314    if (idx == SUB_REAL) {
09315       switch (condition) {
09316       case AST_CONTROL_BUSY:
09317          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09318          break;
09319       case AST_CONTROL_RINGING:
09320          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09321 
09322          if (chan->_state != AST_STATE_UP) {
09323             if ((chan->_state != AST_STATE_RING) ||
09324                ((p->sig != SIG_FXSKS) &&
09325              (p->sig != SIG_FXSLS) &&
09326              (p->sig != SIG_FXSGS)))
09327             ast_setstate(chan, AST_STATE_RINGING);
09328          }
09329          break;
09330       case AST_CONTROL_INCOMPLETE:
09331          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09332          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09333          res = 0;
09334          break;
09335       case AST_CONTROL_PROCEEDING:
09336          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09337          /* don't continue in ast_indicate */
09338          res = 0;
09339          break;
09340       case AST_CONTROL_PROGRESS:
09341          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09342          /* don't continue in ast_indicate */
09343          res = 0;
09344          break;
09345       case AST_CONTROL_CONGESTION:
09346          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09347          switch (chan->hangupcause) {
09348          case AST_CAUSE_USER_BUSY:
09349          case AST_CAUSE_NORMAL_CLEARING:
09350          case 0:/* Cause has not been set. */
09351             /* Supply a more appropriate cause. */
09352             chan->hangupcause = AST_CAUSE_CONGESTION;
09353             break;
09354          default:
09355             break;
09356          }
09357          break;
09358       case AST_CONTROL_HOLD:
09359          ast_moh_start(chan, data, p->mohinterpret);
09360          break;
09361       case AST_CONTROL_UNHOLD:
09362          ast_moh_stop(chan);
09363          break;
09364       case AST_CONTROL_RADIO_KEY:
09365          if (p->radio)
09366             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09367          res = 0;
09368          break;
09369       case AST_CONTROL_RADIO_UNKEY:
09370          if (p->radio)
09371             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09372          res = 0;
09373          break;
09374       case AST_CONTROL_FLASH:
09375          /* flash hookswitch */
09376          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09377             /* Clear out the dial buffer */
09378             p->dop.dialstr[0] = '\0';
09379             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09380                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09381                   chan->name, strerror(errno));
09382             } else
09383                res = 0;
09384          } else
09385             res = 0;
09386          break;
09387       case AST_CONTROL_SRCUPDATE:
09388          res = 0;
09389          break;
09390       case -1:
09391          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09392          break;
09393       }
09394    } else {
09395       res = 0;
09396    }
09397    ast_mutex_unlock(&p->lock);
09398    return res;
09399 }
09400 
09401 #if defined(HAVE_PRI)
09402 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09403 #else
09404 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09405 #endif   /* defined(HAVE_PRI) */
09406 {
09407    struct ast_str *chan_name;
09408    int x, y;
09409 
09410    /* Create the new channel name tail. */
09411    if (!(chan_name = ast_str_create(32))) {
09412       return NULL;
09413    }
09414    if (i->channel == CHAN_PSEUDO) {
09415       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09416 #if defined(HAVE_PRI)
09417    } else if (i->pri) {
09418       ast_mutex_lock(&i->pri->lock);
09419       y = ++i->pri->new_chan_seq;
09420       if (is_outgoing) {
09421          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09422          address[0] = '\0';
09423       } else if (ast_strlen_zero(i->cid_subaddr)) {
09424          /* Put in caller-id number only since there is no subaddress. */
09425          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09426       } else {
09427          /* Put in caller-id number and subaddress. */
09428          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09429             i->cid_subaddr, y);
09430       }
09431       ast_mutex_unlock(&i->pri->lock);
09432 #endif   /* defined(HAVE_PRI) */
09433    } else {
09434       y = 1;
09435       do {
09436          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09437          for (x = 0; x < 3; ++x) {
09438             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09439                i->subs[x].owner->name + 6)) {
09440                break;
09441             }
09442          }
09443          ++y;
09444       } while (x < 3);
09445    }
09446    return chan_name;
09447 }
09448 
09449 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09450 {
09451    struct ast_channel *tmp;
09452    format_t deflaw;
09453    int x;
09454    int features;
09455    struct ast_str *chan_name;
09456    struct ast_variable *v;
09457    char *dashptr;
09458    char device_name[AST_CHANNEL_NAME];
09459 
09460    if (i->subs[idx].owner) {
09461       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09462       return NULL;
09463    }
09464 
09465 #if defined(HAVE_PRI)
09466    /*
09467     * The dnid has been stuffed with the called-number[:subaddress]
09468     * by dahdi_request() for outgoing calls.
09469     */
09470    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09471 #else
09472    chan_name = create_channel_name(i);
09473 #endif   /* defined(HAVE_PRI) */
09474    if (!chan_name) {
09475       return NULL;
09476    }
09477 
09478    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));
09479    ast_free(chan_name);
09480    if (!tmp)
09481       return NULL;
09482    tmp->tech = &dahdi_tech;
09483 #if defined(HAVE_PRI)
09484    if (i->pri) {
09485       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09486    }
09487 #endif   /* defined(HAVE_PRI) */
09488    ast_channel_cc_params_init(tmp, i->cc_params);
09489    if (law) {
09490       i->law = law;
09491       if (law == DAHDI_LAW_ALAW) {
09492          deflaw = AST_FORMAT_ALAW;
09493       } else {
09494          deflaw = AST_FORMAT_ULAW;
09495       }
09496    } else {
09497       switch (i->sig) {
09498       case SIG_PRI_LIB_HANDLE_CASES:
09499          /* Make sure companding law is known. */
09500          i->law = (i->law_default == DAHDI_LAW_ALAW)
09501             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09502          break;
09503       default:
09504          i->law = i->law_default;
09505          break;
09506       }
09507       if (i->law_default == DAHDI_LAW_ALAW) {
09508          deflaw = AST_FORMAT_ALAW;
09509       } else {
09510          deflaw = AST_FORMAT_ULAW;
09511       }
09512    }
09513    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09514    tmp->nativeformats = deflaw;
09515    /* Start out assuming ulaw since it's smaller :) */
09516    tmp->rawreadformat = deflaw;
09517    tmp->readformat = deflaw;
09518    tmp->rawwriteformat = deflaw;
09519    tmp->writeformat = deflaw;
09520    i->subs[idx].linear = 0;
09521    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09522    features = 0;
09523    if (idx == SUB_REAL) {
09524       if (i->busydetect && CANBUSYDETECT(i))
09525          features |= DSP_FEATURE_BUSY_DETECT;
09526       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09527          features |= DSP_FEATURE_CALL_PROGRESS;
09528       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09529          features |= DSP_FEATURE_WAITDIALTONE;
09530       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09531          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09532          features |= DSP_FEATURE_FAX_DETECT;
09533       }
09534       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09535       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09536          i->hardwaredtmf = 0;
09537          features |= DSP_FEATURE_DIGIT_DETECT;
09538       } else if (NEED_MFDETECT(i)) {
09539          i->hardwaredtmf = 1;
09540          features |= DSP_FEATURE_DIGIT_DETECT;
09541       }
09542    }
09543    if (features) {
09544       if (i->dsp) {
09545          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09546       } else {
09547          if (i->channel != CHAN_PSEUDO)
09548             i->dsp = ast_dsp_new();
09549          else
09550             i->dsp = NULL;
09551          if (i->dsp) {
09552             i->dsp_features = features;
09553 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09554             /* We cannot do progress detection until receive PROGRESS message */
09555             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09556                /* Remember requested DSP features, don't treat
09557                   talking as ANSWER */
09558                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09559                features = 0;
09560             }
09561 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09562             ast_dsp_set_features(i->dsp, features);
09563             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09564             if (!ast_strlen_zero(progzone))
09565                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09566             if (i->busydetect && CANBUSYDETECT(i)) {
09567                ast_dsp_set_busy_count(i->dsp, i->busycount);
09568                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09569             }
09570          }
09571       }
09572    }
09573 
09574    if (state == AST_STATE_RING)
09575       tmp->rings = 1;
09576    tmp->tech_pvt = i;
09577    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09578       /* Only FXO signalled stuff can be picked up */
09579       tmp->callgroup = i->callgroup;
09580       tmp->pickupgroup = i->pickupgroup;
09581    }
09582    if (!ast_strlen_zero(i->parkinglot))
09583       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09584    if (!ast_strlen_zero(i->language))
09585       ast_string_field_set(tmp, language, i->language);
09586    if (!i->owner)
09587       i->owner = tmp;
09588    if (!ast_strlen_zero(i->accountcode))
09589       ast_string_field_set(tmp, accountcode, i->accountcode);
09590    if (i->amaflags)
09591       tmp->amaflags = i->amaflags;
09592    i->subs[idx].owner = tmp;
09593    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09594    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09595       ast_string_field_set(tmp, call_forward, i->call_forward);
09596    }
09597    /* If we've been told "no ADSI" then enforce it */
09598    if (!i->adsi)
09599       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09600    if (!ast_strlen_zero(i->exten))
09601       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09602    if (!ast_strlen_zero(i->rdnis)) {
09603       tmp->redirecting.from.number.valid = 1;
09604       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09605    }
09606    if (!ast_strlen_zero(i->dnid)) {
09607       tmp->dialed.number.str = ast_strdup(i->dnid);
09608    }
09609 
09610    /* Don't use ast_set_callerid() here because it will
09611     * generate a needless NewCallerID event */
09612 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09613    if (!ast_strlen_zero(i->cid_ani)) {
09614       tmp->caller.ani.number.valid = 1;
09615       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09616    } else if (!ast_strlen_zero(i->cid_num)) {
09617       tmp->caller.ani.number.valid = 1;
09618       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09619    }
09620 #else
09621    if (!ast_strlen_zero(i->cid_num)) {
09622       tmp->caller.ani.number.valid = 1;
09623       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09624    }
09625 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09626    tmp->caller.id.name.presentation = i->callingpres;
09627    tmp->caller.id.number.presentation = i->callingpres;
09628    tmp->caller.id.number.plan = i->cid_ton;
09629    tmp->caller.ani2 = i->cid_ani2;
09630    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09631    /* clear the fake event in case we posted one before we had ast_channel */
09632    i->fake_event = 0;
09633    /* Assure there is no confmute on this channel */
09634    dahdi_confmute(i, 0);
09635    i->muting = 0;
09636    /* Configure the new channel jb */
09637    ast_jb_configure(tmp, &global_jbconf);
09638 
09639    /* Set initial device state */
09640    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09641    dashptr = strrchr(device_name, '-');
09642    if (dashptr) {
09643       *dashptr = '\0';
09644    }
09645    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09646 
09647    for (v = i->vars ; v ; v = v->next)
09648       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09649 
09650    ast_module_ref(ast_module_info->self);
09651 
09652    dahdi_ami_channel_event(i, tmp);
09653    if (startpbx) {
09654 #ifdef HAVE_OPENR2
09655       if (i->mfcr2call) {
09656          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09657       }
09658 #endif
09659       if (ast_pbx_start(tmp)) {
09660          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09661          ast_hangup(tmp);
09662          return NULL;
09663       }
09664    }
09665    return tmp;
09666 }
09667 
09668 
09669 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09670 {
09671    char c;
09672 
09673    *str = 0; /* start with empty output buffer */
09674    for (;;)
09675    {
09676       /* Wait for the first digit (up to specified ms). */
09677       c = ast_waitfordigit(chan, ms);
09678       /* if timeout, hangup or error, return as such */
09679       if (c < 1)
09680          return c;
09681       *str++ = c;
09682       *str = 0;
09683       if (strchr(term, c))
09684          return 1;
09685    }
09686 }
09687 
09688 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09689 {
09690    int j;
09691    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09692    for (;;)
09693    {
09694       /* set bits of interest */
09695       j = DAHDI_IOMUX_SIGEVENT;
09696       /* wait for some happening */
09697       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09698       /* exit loop if we have it */
09699       if (j & DAHDI_IOMUX_SIGEVENT) break;
09700    }
09701    /* get the event info */
09702    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09703    return 0;
09704 }
09705 
09706 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09707  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09708  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09709  *
09710  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09711  * DAHDI channel). Use this to enable or disable it.
09712  *
09713  * \bug the use of the word "channel" for those dahdichans is really confusing.
09714  */
09715 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09716 {
09717    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09718       return analog_dnd(dahdichan->sig_pvt, flag);
09719    }
09720 
09721    if (flag == -1) {
09722       return dahdichan->dnd;
09723    }
09724 
09725    /* Do not disturb */
09726    dahdichan->dnd = flag;
09727    ast_verb(3, "%s DND on channel %d\n",
09728          flag? "Enabled" : "Disabled",
09729          dahdichan->channel);
09730    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09731          "Channel: DAHDI/%d\r\n"
09732          "Status: %s\r\n", dahdichan->channel,
09733          flag? "enabled" : "disabled");
09734 
09735    return 0;
09736 }
09737 
09738 static int canmatch_featurecode(const char *exten)
09739 {
09740    int extlen = strlen(exten);
09741    const char *pickup_ext;
09742    if (!extlen) {
09743       return 1;
09744    }
09745    pickup_ext = ast_pickup_ext();
09746    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09747       return 1;
09748    }
09749    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09750    if (exten[0] == '*' && extlen < 3) {
09751       if (extlen == 1) {
09752          return 1;
09753       }
09754       /* "*0" should be processed before it gets here */
09755       switch (exten[1]) {
09756       case '6':
09757       case '7':
09758       case '8':
09759          return 1;
09760       }
09761    }
09762    return 0;
09763 }
09764 
09765 static void *analog_ss_thread(void *data)
09766 {
09767    struct ast_channel *chan = data;
09768    struct dahdi_pvt *p = chan->tech_pvt;
09769    char exten[AST_MAX_EXTENSION] = "";
09770    char exten2[AST_MAX_EXTENSION] = "";
09771    unsigned char buf[256];
09772    char dtmfcid[300];
09773    char dtmfbuf[300];
09774    struct callerid_state *cs = NULL;
09775    char *name = NULL, *number = NULL;
09776    int distMatches;
09777    int curRingData[3];
09778    int receivedRingT;
09779    int counter1;
09780    int counter;
09781    int samples = 0;
09782    struct ast_smdi_md_message *smdi_msg = NULL;
09783    int flags = 0;
09784    int i;
09785    int timeout;
09786    int getforward = 0;
09787    char *s1, *s2;
09788    int len = 0;
09789    int res;
09790    int idx;
09791 
09792    ast_mutex_lock(&ss_thread_lock);
09793    ss_thread_count++;
09794    ast_mutex_unlock(&ss_thread_lock);
09795    /* in the bizarre case where the channel has become a zombie before we
09796       even get started here, abort safely
09797    */
09798    if (!p) {
09799       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09800       ast_hangup(chan);
09801       goto quit;
09802    }
09803    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09804    idx = dahdi_get_index(chan, p, 1);
09805    if (idx < 0) {
09806       ast_log(LOG_WARNING, "Huh?\n");
09807       ast_hangup(chan);
09808       goto quit;
09809    }
09810    if (p->dsp)
09811       ast_dsp_digitreset(p->dsp);
09812    switch (p->sig) {
09813    case SIG_FEATD:
09814    case SIG_FEATDMF:
09815    case SIG_FEATDMF_TA:
09816    case SIG_E911:
09817    case SIG_FGC_CAMAMF:
09818    case SIG_FEATB:
09819    case SIG_EMWINK:
09820    case SIG_SF_FEATD:
09821    case SIG_SF_FEATDMF:
09822    case SIG_SF_FEATB:
09823    case SIG_SFWINK:
09824       if (dahdi_wink(p, idx))
09825          goto quit;
09826       /* Fall through */
09827    case SIG_EM:
09828    case SIG_EM_E1:
09829    case SIG_SF:
09830    case SIG_FGC_CAMA:
09831       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09832       if (p->dsp)
09833          ast_dsp_digitreset(p->dsp);
09834       /* set digit mode appropriately */
09835       if (p->dsp) {
09836          if (NEED_MFDETECT(p))
09837             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09838          else
09839             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09840       }
09841       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09842       /* Wait for the first digit only if immediate=no */
09843       if (!p->immediate)
09844          /* Wait for the first digit (up to 5 seconds). */
09845          res = ast_waitfordigit(chan, 5000);
09846       else
09847          res = 0;
09848       if (res > 0) {
09849          /* save first char */
09850          dtmfbuf[0] = res;
09851          switch (p->sig) {
09852          case SIG_FEATD:
09853          case SIG_SF_FEATD:
09854             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09855             if (res > 0)
09856                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09857             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09858             break;
09859          case SIG_FEATDMF_TA:
09860             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09861             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09862             if (dahdi_wink(p, idx)) goto quit;
09863             dtmfbuf[0] = 0;
09864             /* Wait for the first digit (up to 5 seconds). */
09865             res = ast_waitfordigit(chan, 5000);
09866             if (res <= 0) break;
09867             dtmfbuf[0] = res;
09868             /* fall through intentionally */
09869          case SIG_FEATDMF:
09870          case SIG_E911:
09871          case SIG_FGC_CAMAMF:
09872          case SIG_SF_FEATDMF:
09873             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09874             /* if international caca, do it again to get real ANO */
09875             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09876             {
09877                if (dahdi_wink(p, idx)) goto quit;
09878                dtmfbuf[0] = 0;
09879                /* Wait for the first digit (up to 5 seconds). */
09880                res = ast_waitfordigit(chan, 5000);
09881                if (res <= 0) break;
09882                dtmfbuf[0] = res;
09883                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09884             }
09885             if (res > 0) {
09886                /* if E911, take off hook */
09887                if (p->sig == SIG_E911)
09888                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09889                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09890             }
09891             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09892             break;
09893          case SIG_FEATB:
09894          case SIG_SF_FEATB:
09895             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09896             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09897             break;
09898          case SIG_EMWINK:
09899             /* if we received a '*', we are actually receiving Feature Group D
09900                dial syntax, so use that mode; otherwise, fall through to normal
09901                mode
09902             */
09903             if (res == '*') {
09904                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09905                if (res > 0)
09906                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09907                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09908                break;
09909             }
09910          default:
09911             /* If we got the first digit, get the rest */
09912             len = 1;
09913             dtmfbuf[len] = '\0';
09914             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09915                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09916                   timeout = matchdigittimeout;
09917                } else {
09918                   timeout = gendigittimeout;
09919                }
09920                res = ast_waitfordigit(chan, timeout);
09921                if (res < 0) {
09922                   ast_debug(1, "waitfordigit returned < 0...\n");
09923                   ast_hangup(chan);
09924                   goto quit;
09925                } else if (res) {
09926                   dtmfbuf[len++] = res;
09927                   dtmfbuf[len] = '\0';
09928                } else {
09929                   break;
09930                }
09931             }
09932             break;
09933          }
09934       }
09935       if (res == -1) {
09936          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09937          ast_hangup(chan);
09938          goto quit;
09939       } else if (res < 0) {
09940          ast_debug(1, "Got hung up before digits finished\n");
09941          ast_hangup(chan);
09942          goto quit;
09943       }
09944 
09945       if (p->sig == SIG_FGC_CAMA) {
09946          char anibuf[100];
09947 
09948          if (ast_safe_sleep(chan,1000) == -1) {
09949             ast_hangup(chan);
09950             goto quit;
09951          }
09952          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09953          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09954          res = my_getsigstr(chan, anibuf, "#", 10000);
09955          if ((res > 0) && (strlen(anibuf) > 2)) {
09956             if (anibuf[strlen(anibuf) - 1] == '#')
09957                anibuf[strlen(anibuf) - 1] = 0;
09958             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09959          }
09960          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09961       }
09962 
09963       ast_copy_string(exten, dtmfbuf, sizeof(exten));
09964       if (ast_strlen_zero(exten))
09965          ast_copy_string(exten, "s", sizeof(exten));
09966       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09967          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
09968          if (exten[0] == '*') {
09969             char *stringp=NULL;
09970             ast_copy_string(exten2, exten, sizeof(exten2));
09971             /* Parse out extension and callerid */
09972             stringp=exten2 +1;
09973             s1 = strsep(&stringp, "*");
09974             s2 = strsep(&stringp, "*");
09975             if (s2) {
09976                if (!ast_strlen_zero(p->cid_num))
09977                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09978                else
09979                   ast_set_callerid(chan, s1, NULL, s1);
09980                ast_copy_string(exten, s2, sizeof(exten));
09981             } else
09982                ast_copy_string(exten, s1, sizeof(exten));
09983          } else if (p->sig == SIG_FEATD)
09984             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09985       }
09986       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09987          if (exten[0] == '*') {
09988             char *stringp=NULL;
09989             ast_copy_string(exten2, exten, sizeof(exten2));
09990             /* Parse out extension and callerid */
09991             stringp=exten2 +1;
09992             s1 = strsep(&stringp, "#");
09993             s2 = strsep(&stringp, "#");
09994             if (s2) {
09995                if (!ast_strlen_zero(p->cid_num))
09996                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09997                else
09998                   if (*(s1 + 2))
09999                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10000                ast_copy_string(exten, s2 + 1, sizeof(exten));
10001             } else
10002                ast_copy_string(exten, s1 + 2, sizeof(exten));
10003          } else
10004             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10005       }
10006       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
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             s2 = strsep(&stringp, "#");
10014             if (s2 && (*(s2 + 1) == '0')) {
10015                if (*(s2 + 2))
10016                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10017             }
10018             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10019             else ast_copy_string(exten, "911", sizeof(exten));
10020          } else
10021             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10022       }
10023       if (p->sig == SIG_FEATB) {
10024          if (exten[0] == '*') {
10025             char *stringp=NULL;
10026             ast_copy_string(exten2, exten, sizeof(exten2));
10027             /* Parse out extension and callerid */
10028             stringp=exten2 +1;
10029             s1 = strsep(&stringp, "#");
10030             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10031          } else
10032             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10033       }
10034       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10035          dahdi_wink(p, idx);
10036          /* some switches require a minimum guard time between
10037             the last FGD wink and something that answers
10038             immediately. This ensures it */
10039          if (ast_safe_sleep(chan, 100)) {
10040             ast_hangup(chan);
10041             goto quit;
10042          }
10043       }
10044       dahdi_enable_ec(p);
10045       if (NEED_MFDETECT(p)) {
10046          if (p->dsp) {
10047             if (!p->hardwaredtmf)
10048                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10049             else {
10050                ast_dsp_free(p->dsp);
10051                p->dsp = NULL;
10052             }
10053          }
10054       }
10055 
10056       if (ast_exists_extension(chan, chan->context, exten, 1,
10057          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10058          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10059          if (p->dsp) ast_dsp_digitreset(p->dsp);
10060          res = ast_pbx_run(chan);
10061          if (res) {
10062             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10063             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10064          }
10065          goto quit;
10066       } else {
10067          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10068          sleep(2);
10069          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10070          if (res < 0)
10071             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10072          else
10073             sleep(1);
10074          res = ast_streamfile(chan, "ss-noservice", chan->language);
10075          if (res >= 0)
10076             ast_waitstream(chan, "");
10077          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10078          ast_hangup(chan);
10079          goto quit;
10080       }
10081       break;
10082    case SIG_FXOLS:
10083    case SIG_FXOGS:
10084    case SIG_FXOKS:
10085       /* Read the first digit */
10086       timeout = firstdigittimeout;
10087       /* If starting a threeway call, never timeout on the first digit so someone
10088          can use flash-hook as a "hold" feature */
10089       if (p->subs[SUB_THREEWAY].owner)
10090          timeout = 999999;
10091       while (len < AST_MAX_EXTENSION-1) {
10092          /* Read digit unless it's supposed to be immediate, in which case the
10093             only answer is 's' */
10094          if (p->immediate)
10095             res = 's';
10096          else
10097             res = ast_waitfordigit(chan, timeout);
10098          timeout = 0;
10099          if (res < 0) {
10100             ast_debug(1, "waitfordigit returned < 0...\n");
10101             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10102             ast_hangup(chan);
10103             goto quit;
10104          } else if (res) {
10105             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10106             exten[len++]=res;
10107             exten[len] = '\0';
10108          }
10109          if (!ast_ignore_pattern(chan->context, exten))
10110             tone_zone_play_tone(p->subs[idx].dfd, -1);
10111          else
10112             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10113          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10114             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10115                if (getforward) {
10116                   /* Record this as the forwarding extension */
10117                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10118                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10119                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10120                   if (res)
10121                      break;
10122                   usleep(500000);
10123                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10124                   sleep(1);
10125                   memset(exten, 0, sizeof(exten));
10126                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10127                   len = 0;
10128                   getforward = 0;
10129                } else {
10130                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10131                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10132                   if (!ast_strlen_zero(p->cid_num)) {
10133                      if (!p->hidecallerid)
10134                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10135                      else
10136                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10137                   }
10138                   if (!ast_strlen_zero(p->cid_name)) {
10139                      if (!p->hidecallerid)
10140                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10141                   }
10142                   ast_setstate(chan, AST_STATE_RING);
10143                   dahdi_enable_ec(p);
10144                   res = ast_pbx_run(chan);
10145                   if (res) {
10146                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10147                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10148                   }
10149                   goto quit;
10150                }
10151             } else {
10152                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10153                   so just set the timeout to matchdigittimeout and wait some more */
10154                timeout = matchdigittimeout;
10155             }
10156          } else if (res == 0) {
10157             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10158             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10159             dahdi_wait_event(p->subs[idx].dfd);
10160             ast_hangup(chan);
10161             goto quit;
10162          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10163             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10164             /* Disable call waiting if enabled */
10165             p->callwaiting = 0;
10166             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10167             if (res) {
10168                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10169                   chan->name, strerror(errno));
10170             }
10171             len = 0;
10172             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10173             memset(exten, 0, sizeof(exten));
10174             timeout = firstdigittimeout;
10175 
10176          } else if (!strcmp(exten,ast_pickup_ext())) {
10177             /* Scan all channels and see if there are any
10178              * ringing channels that have call groups
10179              * that equal this channels pickup group
10180              */
10181             if (idx == SUB_REAL) {
10182                /* Switch us from Third call to Call Wait */
10183                if (p->subs[SUB_THREEWAY].owner) {
10184                   /* If you make a threeway call and the *8# a call, it should actually
10185                      look like a callwait */
10186                   alloc_sub(p, SUB_CALLWAIT);
10187                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10188                   unalloc_sub(p, SUB_THREEWAY);
10189                }
10190                dahdi_enable_ec(p);
10191                if (ast_pickup_call(chan)) {
10192                   ast_debug(1, "No call pickup possible...\n");
10193                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10194                   dahdi_wait_event(p->subs[idx].dfd);
10195                }
10196                ast_hangup(chan);
10197                goto quit;
10198             } else {
10199                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10200                ast_hangup(chan);
10201                goto quit;
10202             }
10203 
10204          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10205             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10206             /* Disable Caller*ID if enabled */
10207             p->hidecallerid = 1;
10208             ast_party_number_free(&chan->caller.id.number);
10209             ast_party_number_init(&chan->caller.id.number);
10210             ast_party_name_free(&chan->caller.id.name);
10211             ast_party_name_init(&chan->caller.id.name);
10212             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10213             if (res) {
10214                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10215                   chan->name, strerror(errno));
10216             }
10217             len = 0;
10218             memset(exten, 0, sizeof(exten));
10219             timeout = firstdigittimeout;
10220          } else if (p->callreturn && !strcmp(exten, "*69")) {
10221             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10222             break;
10223          } else if (!strcmp(exten, "*78")) {
10224             dahdi_dnd(p, 1);
10225             /* Do not disturb */
10226             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10227             getforward = 0;
10228             memset(exten, 0, sizeof(exten));
10229             len = 0;
10230          } else if (!strcmp(exten, "*79")) {
10231             dahdi_dnd(p, 0);
10232             /* Do not disturb */
10233             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10234             getforward = 0;
10235             memset(exten, 0, sizeof(exten));
10236             len = 0;
10237          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10238             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10239             getforward = 1;
10240             memset(exten, 0, sizeof(exten));
10241             len = 0;
10242          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10243             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10244             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10245             memset(p->call_forward, 0, sizeof(p->call_forward));
10246             getforward = 0;
10247             memset(exten, 0, sizeof(exten));
10248             len = 0;
10249          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10250                   p->subs[SUB_THREEWAY].owner &&
10251                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10252             /* This is a three way call, the main call being a real channel,
10253                and we're parking the first call. */
10254             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10255                chan, exten, chan->context, 0, NULL);
10256             ast_verb(3, "Parking call to '%s'\n", chan->name);
10257             break;
10258          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10259             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10260             /* Enable Caller*ID if enabled */
10261             p->hidecallerid = 0;
10262             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10263             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10264             if (res) {
10265                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10266                   chan->name, strerror(errno));
10267             }
10268             len = 0;
10269             memset(exten, 0, sizeof(exten));
10270             timeout = firstdigittimeout;
10271          } else if (!strcmp(exten, "*0")) {
10272             struct ast_channel *nbridge =
10273                p->subs[SUB_THREEWAY].owner;
10274             struct dahdi_pvt *pbridge = NULL;
10275             /* set up the private struct of the bridged one, if any */
10276             if (nbridge && ast_bridged_channel(nbridge))
10277                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10278             if (nbridge && pbridge &&
10279                (nbridge->tech == &dahdi_tech) &&
10280                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10281                ISTRUNK(pbridge)) {
10282                int func = DAHDI_FLASH;
10283                /* Clear out the dial buffer */
10284                p->dop.dialstr[0] = '\0';
10285                /* flash hookswitch */
10286                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10287                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10288                      nbridge->name, strerror(errno));
10289                }
10290                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10291                unalloc_sub(p, SUB_THREEWAY);
10292                p->owner = p->subs[SUB_REAL].owner;
10293                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10294                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10295                ast_hangup(chan);
10296                goto quit;
10297             } else {
10298                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10299                dahdi_wait_event(p->subs[idx].dfd);
10300                tone_zone_play_tone(p->subs[idx].dfd, -1);
10301                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10302                unalloc_sub(p, SUB_THREEWAY);
10303                p->owner = p->subs[SUB_REAL].owner;
10304                ast_hangup(chan);
10305                goto quit;
10306             }
10307          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10308             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10309             && !canmatch_featurecode(exten)) {
10310             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10311                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10312                chan->context);
10313             break;
10314          }
10315          if (!timeout)
10316             timeout = gendigittimeout;
10317          if (len && !ast_ignore_pattern(chan->context, exten))
10318             tone_zone_play_tone(p->subs[idx].dfd, -1);
10319       }
10320       break;
10321    case SIG_FXSLS:
10322    case SIG_FXSGS:
10323    case SIG_FXSKS:
10324       /* check for SMDI messages */
10325       if (p->use_smdi && p->smdi_iface) {
10326          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10327 
10328          if (smdi_msg != NULL) {
10329             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10330 
10331             if (smdi_msg->type == 'B')
10332                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10333             else if (smdi_msg->type == 'N')
10334                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10335 
10336             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10337          } else {
10338             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10339          }
10340       }
10341 
10342       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10343          number = smdi_msg->calling_st;
10344 
10345       /* If we want caller id, we're in a prering state due to a polarity reversal
10346        * and we're set to use a polarity reversal to trigger the start of caller id,
10347        * grab the caller id and wait for ringing to start... */
10348       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10349                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10350          /* If set to use DTMF CID signalling, listen for DTMF */
10351          if (p->cid_signalling == CID_SIG_DTMF) {
10352             int k = 0;
10353             cs = NULL;
10354             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10355             dahdi_setlinear(p->subs[idx].dfd, 0);
10356             /*
10357              * We are the only party interested in the Rx stream since
10358              * we have not answered yet.  We don't need or even want DTMF
10359              * emulation.  The DTMF digits can come so fast that emulation
10360              * can drop some of them.
10361              */
10362             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10363             res = 4000;/* This is a typical OFF time between rings. */
10364             for (;;) {
10365                struct ast_frame *f;
10366                res = ast_waitfor(chan, res);
10367                if (res <= 0) {
10368                   /*
10369                    * We do not need to restore the dahdi_setlinear()
10370                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10371                    * are hanging up the channel.
10372                    */
10373                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10374                      "Exiting simple switch\n");
10375                   ast_hangup(chan);
10376                   goto quit;
10377                }
10378                f = ast_read(chan);
10379                if (!f)
10380                   break;
10381                if (f->frametype == AST_FRAME_DTMF) {
10382                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10383                      dtmfbuf[k++] = f->subclass.integer;
10384                   }
10385                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10386                   res = 4000;/* This is a typical OFF time between rings. */
10387                }
10388                ast_frfree(f);
10389                if (chan->_state == AST_STATE_RING ||
10390                   chan->_state == AST_STATE_RINGING)
10391                   break; /* Got ring */
10392             }
10393             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10394             dtmfbuf[k] = '\0';
10395             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10396             /* Got cid and ring. */
10397             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10398             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10399             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10400             /* If first byte is NULL, we have no cid */
10401             if (!ast_strlen_zero(dtmfcid))
10402                number = dtmfcid;
10403             else
10404                number = NULL;
10405          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10406          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10407             cs = callerid_new(p->cid_signalling);
10408             if (cs) {
10409                samples = 0;
10410 #if 1
10411                bump_gains(p);
10412 #endif
10413                /* Take out of linear mode for Caller*ID processing */
10414                dahdi_setlinear(p->subs[idx].dfd, 0);
10415 
10416                /* First we wait and listen for the Caller*ID */
10417                for (;;) {
10418                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10419                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10420                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10421                      callerid_free(cs);
10422                      ast_hangup(chan);
10423                      goto quit;
10424                   }
10425                   if (i & DAHDI_IOMUX_SIGEVENT) {
10426                      res = dahdi_get_event(p->subs[idx].dfd);
10427                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10428                      if (res == DAHDI_EVENT_NOALARM) {
10429                         p->inalarm = 0;
10430                      }
10431 
10432                      if (p->cid_signalling == CID_SIG_V23_JP) {
10433                         if (res == DAHDI_EVENT_RINGBEGIN) {
10434                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10435                            usleep(1);
10436                         }
10437                      } else {
10438                         res = 0;
10439                         break;
10440                      }
10441                   } else if (i & DAHDI_IOMUX_READ) {
10442                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10443                      if (res < 0) {
10444                         if (errno != ELAST) {
10445                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10446                            callerid_free(cs);
10447                            ast_hangup(chan);
10448                            goto quit;
10449                         }
10450                         break;
10451                      }
10452                      samples += res;
10453 
10454                      if (p->cid_signalling == CID_SIG_V23_JP) {
10455                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10456                      } else {
10457                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10458                      }
10459                      if (res < 0) {
10460                         /*
10461                          * The previous diagnostic message output likely
10462                          * explains why it failed.
10463                          */
10464                         ast_log(LOG_WARNING,
10465                            "Failed to decode CallerID on channel '%s'\n",
10466                            chan->name);
10467                         break;
10468                      } else if (res)
10469                         break;
10470                      else if (samples > (8000 * 10))
10471                         break;
10472                   }
10473                }
10474                if (res == 1) {
10475                   callerid_get(cs, &name, &number, &flags);
10476                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10477                }
10478 
10479                if (p->cid_signalling == CID_SIG_V23_JP) {
10480                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10481                   usleep(1);
10482                }
10483 
10484                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10485                res = 4000;/* This is a typical OFF time between rings. */
10486                for (;;) {
10487                   struct ast_frame *f;
10488                   res = ast_waitfor(chan, res);
10489                   if (res <= 0) {
10490                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10491                         "Exiting simple switch\n");
10492                      ast_hangup(chan);
10493                      goto quit;
10494                   }
10495                   if (!(f = ast_read(chan))) {
10496                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10497                      ast_hangup(chan);
10498                      goto quit;
10499                   }
10500                   ast_frfree(f);
10501                   if (chan->_state == AST_STATE_RING ||
10502                      chan->_state == AST_STATE_RINGING)
10503                      break; /* Got ring */
10504                }
10505 
10506                /* We must have a ring by now, so, if configured, lets try to listen for
10507                 * distinctive ringing */
10508                if (p->usedistinctiveringdetection) {
10509                   len = 0;
10510                   distMatches = 0;
10511                   /* Clear the current ring data array so we don't have old data in it. */
10512                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10513                      curRingData[receivedRingT] = 0;
10514                   receivedRingT = 0;
10515                   counter = 0;
10516                   counter1 = 0;
10517                   /* Check to see if context is what it should be, if not set to be. */
10518                   if (strcmp(p->context,p->defcontext) != 0) {
10519                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10520                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10521                   }
10522 
10523                   for (;;) {
10524                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10525                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10526                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10527                         callerid_free(cs);
10528                         ast_hangup(chan);
10529                         goto quit;
10530                      }
10531                      if (i & DAHDI_IOMUX_SIGEVENT) {
10532                         res = dahdi_get_event(p->subs[idx].dfd);
10533                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10534                         if (res == DAHDI_EVENT_NOALARM) {
10535                            p->inalarm = 0;
10536                         }
10537                         res = 0;
10538                         /* Let us detect distinctive ring */
10539 
10540                         curRingData[receivedRingT] = p->ringt;
10541 
10542                         if (p->ringt < p->ringt_base/2)
10543                            break;
10544                         /* Increment the ringT counter so we can match it against
10545                            values in chan_dahdi.conf for distinctive ring */
10546                         if (++receivedRingT == ARRAY_LEN(curRingData))
10547                            break;
10548                      } else if (i & DAHDI_IOMUX_READ) {
10549                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10550                         if (res < 0) {
10551                            if (errno != ELAST) {
10552                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10553                               callerid_free(cs);
10554                               ast_hangup(chan);
10555                               goto quit;
10556                            }
10557                            break;
10558                         }
10559                         if (p->ringt > 0) {
10560                            if (!(--p->ringt)) {
10561                               res = -1;
10562                               break;
10563                            }
10564                         }
10565                      }
10566                   }
10567                      /* this only shows up if you have n of the dring patterns filled in */
10568                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10569                   for (counter = 0; counter < 3; counter++) {
10570                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10571                      channel */
10572                      distMatches = 0;
10573                      for (counter1 = 0; counter1 < 3; counter1++) {
10574                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10575                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10576                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10577                            curRingData[counter1]);
10578                            distMatches++;
10579                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10580                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10581                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10582                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10583                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10584                            distMatches++;
10585                         }
10586                      }
10587 
10588                      if (distMatches == 3) {
10589                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10590                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10591                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10592                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10593                         break;
10594                      }
10595                   }
10596                }
10597                /* Restore linear mode (if appropriate) for Caller*ID processing */
10598                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10599 #if 1
10600                restore_gains(p);
10601 #endif
10602             } else
10603                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10604          } else {
10605             ast_log(LOG_WARNING, "Channel %s in prering "
10606                "state, but I have nothing to do. "
10607                "Terminating simple switch, should be "
10608                "restarted by the actual ring.\n",
10609                chan->name);
10610             ast_hangup(chan);
10611             goto quit;
10612          }
10613       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10614          if (p->cid_signalling == CID_SIG_DTMF) {
10615             int k = 0;
10616             cs = NULL;
10617             dahdi_setlinear(p->subs[idx].dfd, 0);
10618             res = 2000;
10619             for (;;) {
10620                struct ast_frame *f;
10621                res = ast_waitfor(chan, res);
10622                if (res <= 0) {
10623                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10624                      "Exiting simple switch\n");
10625                   ast_hangup(chan);
10626                   goto quit;
10627                }
10628                f = ast_read(chan);
10629                if (!f) {
10630                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10631                   ast_hangup(chan);
10632                   goto quit;
10633                }
10634                if (f->frametype == AST_FRAME_DTMF) {
10635                   dtmfbuf[k++] = f->subclass.integer;
10636                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10637                   res = 2000;
10638                }
10639                ast_frfree(f);
10640 
10641                if (p->ringt_base == p->ringt)
10642                   break;
10643             }
10644             dtmfbuf[k] = '\0';
10645             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10646             /* Got cid and ring. */
10647             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10648             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10649                dtmfcid, flags);
10650             /* If first byte is NULL, we have no cid */
10651             if (!ast_strlen_zero(dtmfcid))
10652                number = dtmfcid;
10653             else
10654                number = NULL;
10655             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10656          } else {
10657             /* FSK Bell202 callerID */
10658             cs = callerid_new(p->cid_signalling);
10659             if (cs) {
10660 #if 1
10661                bump_gains(p);
10662 #endif
10663                samples = 0;
10664                len = 0;
10665                distMatches = 0;
10666                /* Clear the current ring data array so we don't have old data in it. */
10667                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10668                   curRingData[receivedRingT] = 0;
10669                receivedRingT = 0;
10670                counter = 0;
10671                counter1 = 0;
10672                /* Check to see if context is what it should be, if not set to be. */
10673                if (strcmp(p->context,p->defcontext) != 0) {
10674                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10675                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10676                }
10677 
10678                /* Take out of linear mode for Caller*ID processing */
10679                dahdi_setlinear(p->subs[idx].dfd, 0);
10680                for (;;) {
10681                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10682                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10683                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10684                      callerid_free(cs);
10685                      ast_hangup(chan);
10686                      goto quit;
10687                   }
10688                   if (i & DAHDI_IOMUX_SIGEVENT) {
10689                      res = dahdi_get_event(p->subs[idx].dfd);
10690                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10691                      if (res == DAHDI_EVENT_NOALARM) {
10692                         p->inalarm = 0;
10693                      }
10694                      /* If we get a PR event, they hung up while processing calerid */
10695                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10696                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10697                         p->polarity = POLARITY_IDLE;
10698                         callerid_free(cs);
10699                         ast_hangup(chan);
10700                         goto quit;
10701                      }
10702                      res = 0;
10703                      /* Let us detect callerid when the telco uses distinctive ring */
10704 
10705                      curRingData[receivedRingT] = p->ringt;
10706 
10707                      if (p->ringt < p->ringt_base/2)
10708                         break;
10709                      /* Increment the ringT counter so we can match it against
10710                         values in chan_dahdi.conf for distinctive ring */
10711                      if (++receivedRingT == ARRAY_LEN(curRingData))
10712                         break;
10713                   } else if (i & DAHDI_IOMUX_READ) {
10714                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10715                      if (res < 0) {
10716                         if (errno != ELAST) {
10717                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10718                            callerid_free(cs);
10719                            ast_hangup(chan);
10720                            goto quit;
10721                         }
10722                         break;
10723                      }
10724                      if (p->ringt > 0) {
10725                         if (!(--p->ringt)) {
10726                            res = -1;
10727                            break;
10728                         }
10729                      }
10730                      samples += res;
10731                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10732                      if (res < 0) {
10733                         /*
10734                          * The previous diagnostic message output likely
10735                          * explains why it failed.
10736                          */
10737                         ast_log(LOG_WARNING,
10738                            "Failed to decode CallerID on channel '%s'\n",
10739                            chan->name);
10740                         break;
10741                      } else if (res)
10742                         break;
10743                      else if (samples > (8000 * 10))
10744                         break;
10745                   }
10746                }
10747                if (res == 1) {
10748                   callerid_get(cs, &name, &number, &flags);
10749                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10750                }
10751                if (distinctiveringaftercid == 1) {
10752                   /* Clear the current ring data array so we don't have old data in it. */
10753                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10754                      curRingData[receivedRingT] = 0;
10755                   }
10756                   receivedRingT = 0;
10757                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10758                   for (;;) {
10759                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10760                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10761                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10762                         callerid_free(cs);
10763                         ast_hangup(chan);
10764                         goto quit;
10765                      }
10766                      if (i & DAHDI_IOMUX_SIGEVENT) {
10767                         res = dahdi_get_event(p->subs[idx].dfd);
10768                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10769                         if (res == DAHDI_EVENT_NOALARM) {
10770                            p->inalarm = 0;
10771                         }
10772                         res = 0;
10773                         /* Let us detect callerid when the telco uses distinctive ring */
10774 
10775                         curRingData[receivedRingT] = p->ringt;
10776 
10777                         if (p->ringt < p->ringt_base/2)
10778                            break;
10779                         /* Increment the ringT counter so we can match it against
10780                            values in chan_dahdi.conf for distinctive ring */
10781                         if (++receivedRingT == ARRAY_LEN(curRingData))
10782                            break;
10783                      } else if (i & DAHDI_IOMUX_READ) {
10784                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10785                         if (res < 0) {
10786                            if (errno != ELAST) {
10787                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10788                               callerid_free(cs);
10789                               ast_hangup(chan);
10790                               goto quit;
10791                            }
10792                            break;
10793                         }
10794                         if (p->ringt > 0) {
10795                            if (!(--p->ringt)) {
10796                               res = -1;
10797                               break;
10798                            }
10799                         }
10800                      }
10801                   }
10802                }
10803                if (p->usedistinctiveringdetection) {
10804                   /* this only shows up if you have n of the dring patterns filled in */
10805                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10806 
10807                   for (counter = 0; counter < 3; counter++) {
10808                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10809                      channel */
10810                      /* this only shows up if you have n of the dring patterns filled in */
10811                      ast_verb(3, "Checking %d,%d,%d\n",
10812                            p->drings.ringnum[counter].ring[0],
10813                            p->drings.ringnum[counter].ring[1],
10814                            p->drings.ringnum[counter].ring[2]);
10815                      distMatches = 0;
10816                      for (counter1 = 0; counter1 < 3; counter1++) {
10817                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10818                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10819                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10820                            curRingData[counter1]);
10821                            distMatches++;
10822                         }
10823                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10824                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10825                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10826                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10827                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10828                            distMatches++;
10829                         }
10830                      }
10831                      if (distMatches == 3) {
10832                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10833                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10834                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10835                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10836                         break;
10837                      }
10838                   }
10839                }
10840                /* Restore linear mode (if appropriate) for Caller*ID processing */
10841                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10842 #if 1
10843                restore_gains(p);
10844 #endif
10845                if (res < 0) {
10846                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10847                }
10848             } else
10849                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10850          }
10851       } else
10852          cs = NULL;
10853 
10854       if (number)
10855          ast_shrink_phone_number(number);
10856       ast_set_callerid(chan, number, name, number);
10857 
10858       if (smdi_msg)
10859          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10860 
10861       if (cs)
10862          callerid_free(cs);
10863 
10864       my_handle_notify_message(chan, p, flags, -1);
10865 
10866       ast_setstate(chan, AST_STATE_RING);
10867       chan->rings = 1;
10868       p->ringt = p->ringt_base;
10869       res = ast_pbx_run(chan);
10870       if (res) {
10871          ast_hangup(chan);
10872          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10873       }
10874       goto quit;
10875    default:
10876       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10877       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10878       if (res < 0)
10879             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10880    }
10881    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10882    if (res < 0)
10883          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10884    ast_hangup(chan);
10885 quit:
10886    ast_mutex_lock(&ss_thread_lock);
10887    ss_thread_count--;
10888    ast_cond_signal(&ss_thread_complete);
10889    ast_mutex_unlock(&ss_thread_lock);
10890    return NULL;
10891 }
10892 
10893 struct mwi_thread_data {
10894    struct dahdi_pvt *pvt;
10895    unsigned char buf[READ_SIZE];
10896    size_t len;
10897 };
10898 
10899 static int calc_energy(const unsigned char *buf, int len, format_t law)
10900 {
10901    int x;
10902    int sum = 0;
10903 
10904    if (!len)
10905       return 0;
10906 
10907    for (x = 0; x < len; x++)
10908       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10909 
10910    return sum / len;
10911 }
10912 
10913 static void *mwi_thread(void *data)
10914 {
10915    struct mwi_thread_data *mtd = data;
10916    struct callerid_state *cs;
10917    pthread_t threadid;
10918    int samples = 0;
10919    char *name, *number;
10920    int flags;
10921    int i, res;
10922    unsigned int spill_done = 0;
10923    int spill_result = -1;
10924 
10925    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10926       mtd->pvt->mwimonitoractive = 0;
10927 
10928       return NULL;
10929    }
10930 
10931    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10932 
10933    bump_gains(mtd->pvt);
10934 
10935    for (;;) {
10936       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10937       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10938          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10939          goto quit;
10940       }
10941 
10942       if (i & DAHDI_IOMUX_SIGEVENT) {
10943          struct ast_channel *chan;
10944 
10945          /* If we get an event, screen out events that we do not act on.
10946           * Otherwise, cancel and go to the simple switch to let it deal with it.
10947           */
10948          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10949 
10950          switch (res) {
10951          case DAHDI_EVENT_NEONMWI_ACTIVE:
10952          case DAHDI_EVENT_NEONMWI_INACTIVE:
10953          case DAHDI_EVENT_NONE:
10954          case DAHDI_EVENT_BITSCHANGED:
10955             break;
10956          case DAHDI_EVENT_NOALARM:
10957             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10958                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10959 
10960                analog_p->inalarm = 0;
10961             }
10962             mtd->pvt->inalarm = 0;
10963             handle_clear_alarms(mtd->pvt);
10964             break;
10965          case DAHDI_EVENT_ALARM:
10966             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10967                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10968 
10969                analog_p->inalarm = 1;
10970             }
10971             mtd->pvt->inalarm = 1;
10972             res = get_alarms(mtd->pvt);
10973             handle_alarms(mtd->pvt, res);
10974             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
10975          default:
10976             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
10977             callerid_free(cs);
10978 
10979             restore_gains(mtd->pvt);
10980             mtd->pvt->ringt = mtd->pvt->ringt_base;
10981 
10982             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10983                int result;
10984                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10985                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10986                } else {
10987                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10988                }
10989                if (result) {
10990                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10991                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10992                   if (res < 0)
10993                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10994                   ast_hangup(chan);
10995                   goto quit;
10996                }
10997                goto quit_no_clean;
10998 
10999             } else {
11000                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11001             }
11002          }
11003       } else if (i & DAHDI_IOMUX_READ) {
11004          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11005             if (errno != ELAST) {
11006                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11007                goto quit;
11008             }
11009             break;
11010          }
11011          samples += res;
11012          if (!spill_done) {
11013             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11014                /*
11015                 * The previous diagnostic message output likely
11016                 * explains why it failed.
11017                 */
11018                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11019                break;
11020             } else if (spill_result) {
11021                spill_done = 1;
11022             }
11023          } else {
11024             /* keep reading data until the energy level drops below the threshold
11025                so we don't get another 'trigger' on the remaining carrier signal
11026             */
11027             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11028                break;
11029          }
11030          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11031             break;
11032       }
11033    }
11034 
11035    if (spill_result == 1) {
11036       callerid_get(cs, &name, &number, &flags);
11037       if (flags & CID_MSGWAITING) {
11038          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11039          notify_message(mtd->pvt->mailbox, 1);
11040       } else if (flags & CID_NOMSGWAITING) {
11041          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11042          notify_message(mtd->pvt->mailbox, 0);
11043       } else {
11044          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11045       }
11046    }
11047 
11048 
11049 quit:
11050    callerid_free(cs);
11051 
11052    restore_gains(mtd->pvt);
11053 
11054 quit_no_clean:
11055    mtd->pvt->mwimonitoractive = 0;
11056 
11057    ast_free(mtd);
11058 
11059    return NULL;
11060 }
11061 
11062 /*
11063 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11064 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11065 * that are sent out via FXS port on voicemail state change.  The execution of
11066 * the mwi send is state driven and can either generate a ring pulse prior to
11067 * sending the fsk spill or simply send an fsk spill.
11068 */
11069 static int mwi_send_init(struct dahdi_pvt * pvt)
11070 {
11071    int x;
11072 
11073 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11074    /* Determine how this spill is to be sent */
11075    if (pvt->mwisend_rpas) {
11076       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11077       pvt->mwisendactive = 1;
11078    } else if (pvt->mwisend_fsk) {
11079       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11080       pvt->mwisendactive = 1;
11081    } else {
11082       pvt->mwisendactive = 0;
11083       return 0;
11084    }
11085 #else
11086    if (mwisend_rpas) {
11087       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11088    } else {
11089       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11090    }
11091    pvt->mwisendactive = 1;
11092 #endif
11093 
11094    if (pvt->cidspill) {
11095       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11096       ast_free(pvt->cidspill);
11097       pvt->cidspill = NULL;
11098       pvt->cidpos = 0;
11099       pvt->cidlen = 0;
11100    }
11101    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11102    if (!pvt->cidspill) {
11103       pvt->mwisendactive = 0;
11104       return -1;
11105    }
11106    x = DAHDI_FLUSH_BOTH;
11107    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11108    x = 3000;
11109    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11110 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11111    if (pvt->mwisend_fsk) {
11112 #endif
11113       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11114                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11115       pvt->cidpos = 0;
11116 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11117    }
11118 #endif
11119    return 0;
11120 }
11121 
11122 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11123 {
11124    struct timeval    now;
11125    int         res;
11126 
11127    /* sanity check to catch if this had been interrupted previously
11128    *  i.e. state says there is more to do but there is no spill allocated
11129    */
11130    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11131       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11132    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11133       /* Normal processing -- Perform mwi send action */
11134       switch ( pvt->mwisend_data.mwisend_current) {
11135       case MWI_SEND_SA:
11136          /* Send the Ring Pulse Signal Alert */
11137          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11138          if (res) {
11139             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11140             goto quit;
11141          }
11142          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11143          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11144          break;
11145       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11146          break;
11147       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11148 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11149          if (pvt->mwisend_fsk) {
11150 #endif
11151             gettimeofday(&now, NULL);
11152             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11153                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11154             }
11155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11156          } else { /* support for mwisendtype=nofsk */
11157             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11158          }
11159 #endif
11160          break;
11161       case MWI_SEND_SPILL:
11162          /* We read some number of bytes.  Write an equal amount of data */
11163          if(0 < num_read) {
11164             if (num_read > pvt->cidlen - pvt->cidpos)
11165                num_read = pvt->cidlen - pvt->cidpos;
11166             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11167             if (res > 0) {
11168                pvt->cidpos += res;
11169                if (pvt->cidpos >= pvt->cidlen) {
11170                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11171                }
11172             } else {
11173                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11174                goto quit;
11175             }
11176          }
11177          break;
11178       case MWI_SEND_CLEANUP:
11179          /* For now, do nothing */
11180          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11181          break;
11182       default:
11183          /* Should not get here, punt*/
11184          goto quit;
11185       }
11186    }
11187 
11188    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11189       if (pvt->cidspill) {
11190          ast_free(pvt->cidspill);
11191          pvt->cidspill = NULL;
11192          pvt->cidpos = 0;
11193          pvt->cidlen = 0;
11194       }
11195       pvt->mwisendactive = 0;
11196    }
11197    return 0;
11198 quit:
11199    if (pvt->cidspill) {
11200       ast_free(pvt->cidspill);
11201       pvt->cidspill = NULL;
11202       pvt->cidpos = 0;
11203       pvt->cidlen = 0;
11204    }
11205    pvt->mwisendactive = 0;
11206    return -1;
11207 }
11208 
11209 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11210 {
11211    int handled = 0;
11212 
11213    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11214       switch (event) {
11215       case DAHDI_EVENT_RINGEROFF:
11216          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11217             handled = 1;
11218 
11219             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11220                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11221                ast_free(pvt->cidspill);
11222                pvt->cidspill = NULL;
11223                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11224                pvt->mwisendactive = 0;
11225             } else {
11226                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11227                gettimeofday(&pvt->mwisend_data.pause, NULL);
11228             }
11229          }
11230          break;
11231       /* Going off hook, I need to punt this spill */
11232       case DAHDI_EVENT_RINGOFFHOOK:
11233          if (pvt->cidspill) {
11234             ast_free(pvt->cidspill);
11235             pvt->cidspill = NULL;
11236             pvt->cidpos = 0;
11237             pvt->cidlen = 0;
11238          }
11239          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11240          pvt->mwisendactive = 0;
11241          break;
11242       case DAHDI_EVENT_RINGERON:
11243       case DAHDI_EVENT_HOOKCOMPLETE:
11244          break;
11245       default:
11246          break;
11247       }
11248    }
11249    return handled;
11250 }
11251 
11252 /* destroy a DAHDI channel, identified by its number */
11253 static int dahdi_destroy_channel_bynum(int channel)
11254 {
11255    struct dahdi_pvt *cur;
11256 
11257    ast_mutex_lock(&iflock);
11258    for (cur = iflist; cur; cur = cur->next) {
11259       if (cur->channel == channel) {
11260          int x = DAHDI_FLASH;
11261 
11262          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11263          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11264 
11265          destroy_channel(cur, 1);
11266          ast_mutex_unlock(&iflock);
11267          ast_module_unref(ast_module_info->self);
11268          return RESULT_SUCCESS;
11269       }
11270    }
11271    ast_mutex_unlock(&iflock);
11272    return RESULT_FAILURE;
11273 }
11274 
11275 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11276 {
11277    int res;
11278    pthread_t threadid;
11279    struct ast_channel *chan;
11280 
11281    /* Handle an event on a given channel for the monitor thread. */
11282 
11283    switch (event) {
11284    case DAHDI_EVENT_NONE:
11285    case DAHDI_EVENT_BITSCHANGED:
11286       break;
11287    case DAHDI_EVENT_WINKFLASH:
11288    case DAHDI_EVENT_RINGOFFHOOK:
11289       if (i->inalarm) break;
11290       if (i->radio) break;
11291       /* Got a ring/answer.  What kind of channel are we? */
11292       switch (i->sig) {
11293       case SIG_FXOLS:
11294       case SIG_FXOGS:
11295       case SIG_FXOKS:
11296          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11297          if (res && (errno == EBUSY))
11298             break;
11299 
11300          /* Cancel VMWI spill */
11301          ast_free(i->cidspill);
11302          i->cidspill = NULL;
11303          restore_conference(i);
11304 
11305          if (i->immediate) {
11306             dahdi_enable_ec(i);
11307             /* The channel is immediately up.  Start right away */
11308             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11309             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11310             if (!chan) {
11311                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11312                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11313                if (res < 0)
11314                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11315             }
11316          } else {
11317             /* Check for callerid, digits, etc */
11318             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11319             if (chan) {
11320                if (has_voicemail(i))
11321                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11322                else
11323                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11324                if (res < 0)
11325                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11326                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11327                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11328                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11329                   if (res < 0)
11330                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11331                   ast_hangup(chan);
11332                }
11333             } else
11334                ast_log(LOG_WARNING, "Unable to create channel\n");
11335          }
11336          break;
11337       case SIG_FXSLS:
11338       case SIG_FXSGS:
11339       case SIG_FXSKS:
11340             i->ringt = i->ringt_base;
11341             /* Fall through */
11342       case SIG_EMWINK:
11343       case SIG_FEATD:
11344       case SIG_FEATDMF:
11345       case SIG_FEATDMF_TA:
11346       case SIG_E911:
11347       case SIG_FGC_CAMA:
11348       case SIG_FGC_CAMAMF:
11349       case SIG_FEATB:
11350       case SIG_EM:
11351       case SIG_EM_E1:
11352       case SIG_SFWINK:
11353       case SIG_SF_FEATD:
11354       case SIG_SF_FEATDMF:
11355       case SIG_SF_FEATB:
11356       case SIG_SF:
11357          /* Check for callerid, digits, etc */
11358          if (i->cid_start == CID_START_POLARITY_IN) {
11359             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11360          } else {
11361             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11362          }
11363 
11364          if (!chan) {
11365             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11366          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11367             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11368             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11369             if (res < 0) {
11370                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11371             }
11372             ast_hangup(chan);
11373          }
11374          break;
11375       default:
11376          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11377          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11378          if (res < 0)
11379             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11380          return NULL;
11381       }
11382       break;
11383    case DAHDI_EVENT_NOALARM:
11384       switch (i->sig) {
11385 #if defined(HAVE_PRI)
11386       case SIG_PRI_LIB_HANDLE_CASES:
11387          ast_mutex_lock(&i->lock);
11388          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11389          ast_mutex_unlock(&i->lock);
11390          break;
11391 #endif   /* defined(HAVE_PRI) */
11392 #if defined(HAVE_SS7)
11393       case SIG_SS7:
11394          sig_ss7_set_alarm(i->sig_pvt, 0);
11395          break;
11396 #endif   /* defined(HAVE_SS7) */
11397       default:
11398          i->inalarm = 0;
11399          break;
11400       }
11401       handle_clear_alarms(i);
11402       break;
11403    case DAHDI_EVENT_ALARM:
11404       switch (i->sig) {
11405 #if defined(HAVE_PRI)
11406       case SIG_PRI_LIB_HANDLE_CASES:
11407          ast_mutex_lock(&i->lock);
11408          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11409          ast_mutex_unlock(&i->lock);
11410          break;
11411 #endif   /* defined(HAVE_PRI) */
11412 #if defined(HAVE_SS7)
11413       case SIG_SS7:
11414          sig_ss7_set_alarm(i->sig_pvt, 1);
11415          break;
11416 #endif   /* defined(HAVE_SS7) */
11417       default:
11418          i->inalarm = 1;
11419          break;
11420       }
11421       res = get_alarms(i);
11422       handle_alarms(i, res);
11423       /* fall thru intentionally */
11424    case DAHDI_EVENT_ONHOOK:
11425       if (i->radio)
11426          break;
11427       /* Back on hook.  Hang up. */
11428       switch (i->sig) {
11429       case SIG_FXOLS:
11430       case SIG_FXOGS:
11431       case SIG_FEATD:
11432       case SIG_FEATDMF:
11433       case SIG_FEATDMF_TA:
11434       case SIG_E911:
11435       case SIG_FGC_CAMA:
11436       case SIG_FGC_CAMAMF:
11437       case SIG_FEATB:
11438       case SIG_EM:
11439       case SIG_EM_E1:
11440       case SIG_EMWINK:
11441       case SIG_SF_FEATD:
11442       case SIG_SF_FEATDMF:
11443       case SIG_SF_FEATB:
11444       case SIG_SF:
11445       case SIG_SFWINK:
11446       case SIG_FXSLS:
11447       case SIG_FXSGS:
11448       case SIG_FXSKS:
11449       case SIG_FXOKS:
11450          dahdi_disable_ec(i);
11451          /* Diddle the battery for the zhone */
11452 #ifdef ZHONE_HACK
11453          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11454          usleep(1);
11455 #endif
11456          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11457          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11458          break;
11459       case SIG_SS7:
11460       case SIG_PRI_LIB_HANDLE_CASES:
11461          dahdi_disable_ec(i);
11462          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11463          break;
11464       default:
11465          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11466          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11467          return NULL;
11468       }
11469       break;
11470    case DAHDI_EVENT_POLARITY:
11471       switch (i->sig) {
11472       case SIG_FXSLS:
11473       case SIG_FXSKS:
11474       case SIG_FXSGS:
11475          /* We have already got a PR before the channel was
11476             created, but it wasn't handled. We need polarity
11477             to be REV for remote hangup detection to work.
11478             At least in Spain */
11479          if (i->hanguponpolarityswitch)
11480             i->polarity = POLARITY_REV;
11481          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11482             i->polarity = POLARITY_REV;
11483             ast_verb(2, "Starting post polarity "
11484                "CID detection on channel %d\n",
11485                i->channel);
11486             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11487             if (!chan) {
11488                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11489             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11490                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11491             }
11492          }
11493          break;
11494       default:
11495          ast_log(LOG_WARNING, "handle_init_event detected "
11496             "polarity reversal on non-FXO (SIG_FXS) "
11497             "interface %d\n", i->channel);
11498       }
11499       break;
11500    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11501       ast_log(LOG_NOTICE,
11502             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11503             i->channel);
11504       return i;
11505    case DAHDI_EVENT_NEONMWI_ACTIVE:
11506       if (i->mwimonitor_neon) {
11507          notify_message(i->mailbox, 1);
11508          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11509       }
11510       break;
11511    case DAHDI_EVENT_NEONMWI_INACTIVE:
11512       if (i->mwimonitor_neon) {
11513          notify_message(i->mailbox, 0);
11514          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11515       }
11516       break;
11517    }
11518    return NULL;
11519 }
11520 
11521 static void *do_monitor(void *data)
11522 {
11523    int count, res, res2, spoint, pollres=0;
11524    struct dahdi_pvt *i;
11525    struct dahdi_pvt *last = NULL;
11526    struct dahdi_pvt *doomed;
11527    time_t thispass = 0, lastpass = 0;
11528    int found;
11529    char buf[1024];
11530    struct pollfd *pfds=NULL;
11531    int lastalloc = -1;
11532    /* This thread monitors all the frame relay interfaces which are not yet in use
11533       (and thus do not have a separate thread) indefinitely */
11534    /* From here on out, we die whenever asked */
11535 #if 0
11536    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11537       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11538       return NULL;
11539    }
11540    ast_debug(1, "Monitor starting...\n");
11541 #endif
11542    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11543 
11544    for (;;) {
11545       /* Lock the interface list */
11546       ast_mutex_lock(&iflock);
11547       if (!pfds || (lastalloc != ifcount)) {
11548          if (pfds) {
11549             ast_free(pfds);
11550             pfds = NULL;
11551          }
11552          if (ifcount) {
11553             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11554                ast_mutex_unlock(&iflock);
11555                return NULL;
11556             }
11557          }
11558          lastalloc = ifcount;
11559       }
11560       /* Build the stuff we're going to poll on, that is the socket of every
11561          dahdi_pvt that does not have an associated owner channel */
11562       count = 0;
11563       for (i = iflist; i; i = i->next) {
11564          ast_mutex_lock(&i->lock);
11565          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11566             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11567                struct analog_pvt *p = i->sig_pvt;
11568 
11569                if (!p)
11570                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11571 
11572                if (!p->owner && !p->subs[SUB_REAL].owner) {
11573                   /* This needs to be watched, as it lacks an owner */
11574                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11575                   pfds[count].events = POLLPRI;
11576                   pfds[count].revents = 0;
11577                   /* Message waiting or r2 channels also get watched for reading */
11578                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11579                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11580                      pfds[count].events |= POLLIN;
11581                   }
11582                   count++;
11583                }
11584             } else {
11585                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11586                   /* This needs to be watched, as it lacks an owner */
11587                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11588                   pfds[count].events = POLLPRI;
11589                   pfds[count].revents = 0;
11590                   /* If we are monitoring for VMWI or sending CID, we need to
11591                      read from the channel as well */
11592                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11593                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11594                      pfds[count].events |= POLLIN;
11595                   }
11596                   count++;
11597                }
11598             }
11599          }
11600          ast_mutex_unlock(&i->lock);
11601       }
11602       /* Okay, now that we know what to do, release the interface lock */
11603       ast_mutex_unlock(&iflock);
11604 
11605       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11606       pthread_testcancel();
11607       /* Wait at least a second for something to happen */
11608       res = poll(pfds, count, 1000);
11609       pthread_testcancel();
11610       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11611 
11612       /* Okay, poll has finished.  Let's see what happened.  */
11613       if (res < 0) {
11614          if ((errno != EAGAIN) && (errno != EINTR))
11615             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11616          continue;
11617       }
11618       /* Alright, lock the interface list again, and let's look and see what has
11619          happened */
11620       ast_mutex_lock(&iflock);
11621       found = 0;
11622       spoint = 0;
11623       lastpass = thispass;
11624       thispass = time(NULL);
11625       doomed = NULL;
11626       for (i = iflist;; i = i->next) {
11627          if (doomed) {
11628             int res;
11629             res = dahdi_destroy_channel_bynum(doomed->channel);
11630             if (res != RESULT_SUCCESS) {
11631                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11632             }
11633             doomed = NULL;
11634          }
11635          if (!i) {
11636             break;
11637          }
11638 
11639          if (thispass != lastpass) {
11640             if (!found && ((i == last) || ((i == iflist) && !last))) {
11641                last = i;
11642                if (last) {
11643                   struct analog_pvt *analog_p = last->sig_pvt;
11644                   /* Only allow MWI to be initiated on a quiescent fxs port */
11645                   if (analog_p
11646                      && !last->mwisendactive
11647                      && (last->sig & __DAHDI_SIG_FXO)
11648                      && !analog_p->fxsoffhookstate
11649                      && !last->owner
11650                      && !ast_strlen_zero(last->mailbox)
11651                      && (thispass - analog_p->onhooktime > 3)) {
11652                      res = has_voicemail(last);
11653                      if (analog_p->msgstate != res) {
11654                         /* Set driver resources for signalling VMWI */
11655                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11656                         if (res2) {
11657                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11658                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11659                         }
11660                         /* If enabled for FSK spill then initiate it */
11661                         if (mwi_send_init(last)) {
11662                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11663                         }
11664                         analog_p->msgstate = res;
11665                         found ++;
11666                      }
11667                   }
11668                   last = last->next;
11669                }
11670             }
11671          }
11672          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11673             if (i->radio && !i->owner)
11674             {
11675                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11676                if (res)
11677                {
11678                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11679                   /* Don't hold iflock while handling init events */
11680                   ast_mutex_unlock(&iflock);
11681                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11682                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11683                   else
11684                      doomed = handle_init_event(i, res);
11685                   ast_mutex_lock(&iflock);
11686                }
11687                continue;
11688             }
11689             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11690             if (pollres & POLLIN) {
11691                if (i->owner || i->subs[SUB_REAL].owner) {
11692 #ifdef HAVE_PRI
11693                   if (!i->pri)
11694 #endif
11695                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11696                   continue;
11697                }
11698                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11699                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11700                   continue;
11701                }
11702                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11703                if (res > 0) {
11704                   if (i->mwimonitor_fsk) {
11705                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11706                         pthread_attr_t attr;
11707                         pthread_t threadid;
11708                         struct mwi_thread_data *mtd;
11709 
11710                         pthread_attr_init(&attr);
11711                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11712 
11713                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11714                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11715                            mtd->pvt = i;
11716                            memcpy(mtd->buf, buf, res);
11717                            mtd->len = res;
11718                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11719                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11720                               ast_free(mtd);
11721                            }
11722                            i->mwimonitoractive = 1;
11723                         }
11724                      }
11725                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11726                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11727                      int energy;
11728                      struct timeval now;
11729                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11730                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11731                      */
11732                      if (1 == i->dtmfcid_holdoff_state) {
11733                         gettimeofday(&i->dtmfcid_delay, NULL);
11734                         i->dtmfcid_holdoff_state = 2;
11735                      } else if (2 == i->dtmfcid_holdoff_state) {
11736                         gettimeofday(&now, NULL);
11737                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11738                            i->dtmfcid_holdoff_state = 0;
11739                         }
11740                      } else {
11741                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11742                         if (!i->mwisendactive && energy > dtmfcid_level) {
11743                            pthread_t threadid;
11744                            struct ast_channel *chan;
11745                            ast_mutex_unlock(&iflock);
11746                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11747                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11748                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11749                               i->dtmfcid_holdoff_state = 1;
11750                            } else {
11751                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11752                               if (!chan) {
11753                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11754                               } else {
11755                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11756                                  if (res) {
11757                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11758                                  } else {
11759                                     i->dtmfcid_holdoff_state = 1;
11760                                  }
11761                               }
11762                            }
11763                            ast_mutex_lock(&iflock);
11764                         }
11765                      }
11766                   }
11767                   if (i->mwisendactive) {
11768                      mwi_send_process_buffer(i, res);
11769                   }
11770                } else {
11771                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11772                }
11773             }
11774             if (pollres & POLLPRI) {
11775                if (i->owner || i->subs[SUB_REAL].owner) {
11776 #ifdef HAVE_PRI
11777                   if (!i->pri)
11778 #endif
11779                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11780                   continue;
11781                }
11782                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11783                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11784                /* Don't hold iflock while handling init events */
11785                ast_mutex_unlock(&iflock);
11786                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11787                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11788                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11789                   else
11790                      doomed = handle_init_event(i, res);
11791                }
11792                ast_mutex_lock(&iflock);
11793             }
11794          }
11795       }
11796       ast_mutex_unlock(&iflock);
11797    }
11798    /* Never reached */
11799    return NULL;
11800 
11801 }
11802 
11803 static int restart_monitor(void)
11804 {
11805    /* If we're supposed to be stopped -- stay stopped */
11806    if (monitor_thread == AST_PTHREADT_STOP)
11807       return 0;
11808    ast_mutex_lock(&monlock);
11809    if (monitor_thread == pthread_self()) {
11810       ast_mutex_unlock(&monlock);
11811       ast_log(LOG_WARNING, "Cannot kill myself\n");
11812       return -1;
11813    }
11814    if (monitor_thread != AST_PTHREADT_NULL) {
11815       /* Wake up the thread */
11816       pthread_kill(monitor_thread, SIGURG);
11817    } else {
11818       /* Start a new monitor */
11819       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11820          ast_mutex_unlock(&monlock);
11821          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11822          return -1;
11823       }
11824    }
11825    ast_mutex_unlock(&monlock);
11826    return 0;
11827 }
11828 
11829 #if defined(HAVE_PRI)
11830 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11831 {
11832    int x;
11833    int trunkgroup;
11834    /* Get appropriate trunk group if there is one */
11835    trunkgroup = pris[*span].mastertrunkgroup;
11836    if (trunkgroup) {
11837       /* Select a specific trunk group */
11838       for (x = 0; x < NUM_SPANS; x++) {
11839          if (pris[x].pri.trunkgroup == trunkgroup) {
11840             *span = x;
11841             return 0;
11842          }
11843       }
11844       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11845       *span = -1;
11846    } else {
11847       if (pris[*span].pri.trunkgroup) {
11848          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);
11849          *span = -1;
11850       } else if (pris[*span].mastertrunkgroup) {
11851          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11852          *span = -1;
11853       } else {
11854          if (si->totalchans == 31) {
11855             /* E1 */
11856             pris[*span].dchannels[0] = 16 + offset;
11857          } else if (si->totalchans == 24) {
11858             /* T1 or J1 */
11859             pris[*span].dchannels[0] = 24 + offset;
11860          } else if (si->totalchans == 3) {
11861             /* BRI */
11862             pris[*span].dchannels[0] = 3 + offset;
11863          } else {
11864             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);
11865             *span = -1;
11866             return 0;
11867          }
11868          pris[*span].pri.span = *span + 1;
11869       }
11870    }
11871    return 0;
11872 }
11873 #endif   /* defined(HAVE_PRI) */
11874 
11875 #if defined(HAVE_PRI)
11876 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11877 {
11878    struct dahdi_spaninfo si;
11879    struct dahdi_params p;
11880    int fd;
11881    int span;
11882    int ospan=0;
11883    int x,y;
11884    for (x = 0; x < NUM_SPANS; x++) {
11885       if (pris[x].pri.trunkgroup == trunkgroup) {
11886          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11887          return -1;
11888       }
11889    }
11890    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11891       if (!channels[y])
11892          break;
11893       memset(&si, 0, sizeof(si));
11894       memset(&p, 0, sizeof(p));
11895       fd = open("/dev/dahdi/channel", O_RDWR);
11896       if (fd < 0) {
11897          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11898          return -1;
11899       }
11900       x = channels[y];
11901       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11902          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11903          close(fd);
11904          return -1;
11905       }
11906       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11907          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11908          return -1;
11909       }
11910       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11911          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11912          close(fd);
11913          return -1;
11914       }
11915       span = p.spanno - 1;
11916       if (pris[span].pri.trunkgroup) {
11917          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11918          close(fd);
11919          return -1;
11920       }
11921       if (pris[span].pri.pvts[0]) {
11922          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11923          close(fd);
11924          return -1;
11925       }
11926       if (!y) {
11927          pris[span].pri.trunkgroup = trunkgroup;
11928          ospan = span;
11929       }
11930       pris[ospan].dchannels[y] = channels[y];
11931       pris[span].pri.span = span + 1;
11932       close(fd);
11933    }
11934    return 0;
11935 }
11936 #endif   /* defined(HAVE_PRI) */
11937 
11938 #if defined(HAVE_PRI)
11939 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11940 {
11941    if (pris[span].mastertrunkgroup) {
11942       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);
11943       return -1;
11944    }
11945    pris[span].mastertrunkgroup = trunkgroup;
11946    pris[span].prilogicalspan = logicalspan;
11947    return 0;
11948 }
11949 #endif   /* defined(HAVE_PRI) */
11950 
11951 #if defined(HAVE_SS7)
11952 static unsigned int parse_pointcode(const char *pcstring)
11953 {
11954    unsigned int code1, code2, code3;
11955    int numvals;
11956 
11957    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11958    if (numvals == 1)
11959       return code1;
11960    if (numvals == 3)
11961       return (code1 << 16) | (code2 << 8) | code3;
11962 
11963    return 0;
11964 }
11965 #endif   /* defined(HAVE_SS7) */
11966 
11967 #if defined(HAVE_SS7)
11968 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11969 {
11970    if ((linkset < 0) || (linkset >= NUM_SPANS))
11971       return NULL;
11972    else
11973       return &linksets[linkset - 1];
11974 }
11975 #endif   /* defined(HAVE_SS7) */
11976 
11977 #ifdef HAVE_OPENR2
11978 static void dahdi_r2_destroy_links(void)
11979 {
11980    int i = 0;
11981    if (!r2links) {
11982       return;
11983    }
11984    for (; i < r2links_count; i++) {
11985       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11986          pthread_cancel(r2links[i]->r2master);
11987          pthread_join(r2links[i]->r2master, NULL);
11988          openr2_context_delete(r2links[i]->protocol_context);
11989       }
11990       ast_free(r2links[i]);
11991    }
11992    ast_free(r2links);
11993    r2links = NULL;
11994    r2links_count = 0;
11995 }
11996 
11997 #define R2_LINK_CAPACITY 10
11998 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11999 {
12000    struct dahdi_mfcr2 *new_r2link = NULL;
12001    struct dahdi_mfcr2 **new_r2links = NULL;
12002    /* this function is called just when starting up and no monitor threads have been launched,
12003       no need to lock monitored_count member */
12004    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12005       new_r2link = ast_calloc(1, sizeof(**r2links));
12006       if (!new_r2link) {
12007          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12008          return NULL;
12009       }
12010       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12011       if (!new_r2links) {
12012          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12013          ast_free(new_r2link);
12014          return NULL;
12015       }
12016       r2links = new_r2links;
12017       new_r2link->r2master = AST_PTHREADT_NULL;
12018       r2links[r2links_count] = new_r2link;
12019       r2links_count++;
12020       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12021    }
12022    return r2links[r2links_count - 1];
12023 }
12024 
12025 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12026 {
12027    char tmplogdir[] = "/tmp";
12028    char logdir[OR2_MAX_PATH];
12029    int threshold = 0;
12030    int snres = 0;
12031    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12032          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12033          conf->mfcr2.max_dnis);
12034    if (!r2_link->protocol_context) {
12035       return -1;
12036    }
12037    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12038    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12039 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12040    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12041 #endif
12042    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12043    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12044    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12045    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12046    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12047    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12048       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12049          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12050       }
12051    } else {
12052       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12053       if (snres >= sizeof(logdir)) {
12054          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12055          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12056             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12057          }
12058       } else {
12059          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12060             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12061          }
12062       }
12063    }
12064    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12065       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12066          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12067       }
12068    }
12069    r2_link->monitored_count = 0;
12070    return 0;
12071 }
12072 #endif
12073 
12074 /* converts a DAHDI sigtype to signalling as can be configured from
12075  * chan_dahdi.conf.
12076  * While both have basically the same values, this will later be the
12077  * place to add filters and sanity checks
12078  */
12079 static int sigtype_to_signalling(int sigtype)
12080 {
12081    return sigtype;
12082 }
12083 
12084 /*!
12085  * \internal
12086  * \brief Get file name and channel number from (subdir,number)
12087  *
12088  * \param subdir name of the subdirectory under /dev/dahdi/
12089  * \param channel name of device file under /dev/dahdi/<subdir>/
12090  * \param path buffer to put file name in
12091  * \param pathlen maximal length of path
12092  *
12093  * \retval minor number of dahdi channel.
12094  * \retval -errno on error.
12095  */
12096 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12097 {
12098    struct stat stbuf;
12099    int      num;
12100 
12101    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12102    if (stat(path, &stbuf) < 0) {
12103       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12104       return -errno;
12105    }
12106    if (!S_ISCHR(stbuf.st_mode)) {
12107       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12108       return -EINVAL;
12109    }
12110    num = minor(stbuf.st_rdev);
12111    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12112    return num;
12113 
12114 }
12115 
12116 /*!
12117  * \internal
12118  * \brief Initialize/create a channel interface.
12119  *
12120  * \param channel Channel interface number to initialize/create.
12121  * \param conf Configuration parameters to initialize interface with.
12122  * \param reloading What we are doing now:
12123  * 0 - initial module load,
12124  * 1 - module reload,
12125  * 2 - module restart
12126  *
12127  * \retval Interface-pointer initialized/created
12128  * \retval NULL if error
12129  */
12130 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12131 {
12132    /* Make a dahdi_pvt structure for this interface */
12133    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12134    char fn[80];
12135    struct dahdi_bufferinfo bi;
12136 
12137    int res;
12138 #if defined(HAVE_PRI)
12139    int span = 0;
12140 #endif   /* defined(HAVE_PRI) */
12141    int here = 0;/*!< TRUE if the channel interface already exists. */
12142    int x;
12143    struct analog_pvt *analog_p = NULL;
12144    struct dahdi_params p;
12145 #if defined(HAVE_PRI)
12146    struct dahdi_spaninfo si;
12147    struct sig_pri_chan *pri_chan = NULL;
12148 #endif   /* defined(HAVE_PRI) */
12149 #if defined(HAVE_SS7)
12150    struct sig_ss7_chan *ss7_chan = NULL;
12151 #endif   /* defined(HAVE_SS7) */
12152 
12153    /* Search channel interface list to see if it already exists. */
12154    for (tmp = iflist; tmp; tmp = tmp->next) {
12155       if (!tmp->destroy) {
12156          if (tmp->channel == channel) {
12157             /* The channel interface already exists. */
12158             here = 1;
12159             break;
12160          }
12161          if (tmp->channel > channel) {
12162             /* No way it can be in the sorted list. */
12163             tmp = NULL;
12164             break;
12165          }
12166       }
12167    }
12168 
12169    if (!here && reloading != 1) {
12170       tmp = ast_calloc(1, sizeof(*tmp));
12171       if (!tmp) {
12172          return NULL;
12173       }
12174       tmp->cc_params = ast_cc_config_params_init();
12175       if (!tmp->cc_params) {
12176          ast_free(tmp);
12177          return NULL;
12178       }
12179       ast_mutex_init(&tmp->lock);
12180       ifcount++;
12181       for (x = 0; x < 3; x++)
12182          tmp->subs[x].dfd = -1;
12183       tmp->channel = channel;
12184       tmp->priindication_oob = conf->chan.priindication_oob;
12185    }
12186 
12187    if (tmp) {
12188       int chan_sig = conf->chan.sig;
12189 
12190       /* If there are variables in tmp before it is updated to match the new config, clear them */
12191       if (reloading && tmp->vars) {
12192          ast_variables_destroy(tmp->vars);
12193          tmp->vars = NULL;
12194       }
12195 
12196 
12197       if (!here) {
12198          /* Can only get here if this is a new channel interface being created. */
12199          if ((channel != CHAN_PSEUDO)) {
12200             int count = 0;
12201 
12202             snprintf(fn, sizeof(fn), "%d", channel);
12203             /* Open non-blocking */
12204             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12205             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 */
12206                usleep(1);
12207                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12208                count++;
12209             }
12210             /* Allocate a DAHDI structure */
12211             if (tmp->subs[SUB_REAL].dfd < 0) {
12212                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);
12213                destroy_dahdi_pvt(tmp);
12214                return NULL;
12215             }
12216             memset(&p, 0, sizeof(p));
12217             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12218             if (res < 0) {
12219                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12220                destroy_dahdi_pvt(tmp);
12221                return NULL;
12222             }
12223             if (conf->is_sig_auto)
12224                chan_sig = sigtype_to_signalling(p.sigtype);
12225             if (p.sigtype != (chan_sig & 0x3ffff)) {
12226                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));
12227                destroy_dahdi_pvt(tmp);
12228                return NULL;
12229             }
12230             tmp->law_default = p.curlaw;
12231             tmp->law = p.curlaw;
12232             tmp->span = p.spanno;
12233 #if defined(HAVE_PRI)
12234             span = p.spanno - 1;
12235 #endif   /* defined(HAVE_PRI) */
12236          } else {
12237             chan_sig = 0;
12238          }
12239          tmp->sig = chan_sig;
12240          tmp->outsigmod = conf->chan.outsigmod;
12241 
12242          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12243             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12244             if (!analog_p) {
12245                destroy_dahdi_pvt(tmp);
12246                return NULL;
12247             }
12248             tmp->sig_pvt = analog_p;
12249          }
12250 #if defined(HAVE_SS7)
12251          if (chan_sig == SIG_SS7) {
12252             struct dahdi_ss7 *ss7;
12253             int clear = 0;
12254 
12255             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12256                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12257                destroy_dahdi_pvt(tmp);
12258                return NULL;
12259             }
12260 
12261             ss7 = ss7_resolve_linkset(cur_linkset);
12262             if (!ss7) {
12263                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12264                destroy_dahdi_pvt(tmp);
12265                return NULL;
12266             }
12267             ss7->ss7.span = cur_linkset;
12268             if (cur_cicbeginswith < 0) {
12269                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12270                destroy_dahdi_pvt(tmp);
12271                return NULL;
12272             }
12273             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12274             if (!ss7_chan) {
12275                destroy_dahdi_pvt(tmp);
12276                return NULL;
12277             }
12278             tmp->sig_pvt = ss7_chan;
12279             tmp->ss7 = &ss7->ss7;
12280 
12281             ss7_chan->channel = tmp->channel;
12282             ss7_chan->cic = cur_cicbeginswith++;
12283 
12284             /* DB: Add CIC's DPC information */
12285             ss7_chan->dpc = cur_defaultdpc;
12286 
12287             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12288 
12289             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12290             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12291             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12292             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12293 
12294             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12295             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12296          }
12297 #endif   /* defined(HAVE_SS7) */
12298 #ifdef HAVE_OPENR2
12299          if (chan_sig == SIG_MFCR2) {
12300             struct dahdi_mfcr2 *r2_link;
12301             r2_link = dahdi_r2_get_link();
12302             if (!r2_link) {
12303                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12304                destroy_dahdi_pvt(tmp);
12305                return NULL;
12306             }
12307             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12308                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12309                destroy_dahdi_pvt(tmp);
12310                return NULL;
12311             }
12312             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12313                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12314                destroy_dahdi_pvt(tmp);
12315                return NULL;
12316             }
12317             r2_link->pvts[r2_link->numchans++] = tmp;
12318             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12319                                         tmp->subs[SUB_REAL].dfd,
12320                                         NULL, NULL);
12321             if (!tmp->r2chan) {
12322                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12323                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12324                destroy_dahdi_pvt(tmp);
12325                return NULL;
12326             }
12327             tmp->mfcr2 = r2_link;
12328             if (conf->mfcr2.call_files) {
12329                openr2_chan_enable_call_files(tmp->r2chan);
12330             }
12331             openr2_chan_set_client_data(tmp->r2chan, tmp);
12332             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12333             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12334             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12335             tmp->mfcr2_category = conf->mfcr2.category;
12336             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12337             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12338             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12339             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12340             tmp->mfcr2call = 0;
12341             tmp->mfcr2_dnis_index = 0;
12342             tmp->mfcr2_ani_index = 0;
12343             r2_link->monitored_count++;
12344          }
12345 #endif
12346 #ifdef HAVE_PRI
12347          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12348             int offset;
12349             int matchesdchan;
12350             int x,y;
12351             int myswitchtype = 0;
12352 
12353             offset = 0;
12354             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12355                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12356                destroy_dahdi_pvt(tmp);
12357                return NULL;
12358             }
12359             if (span >= NUM_SPANS) {
12360                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12361                destroy_dahdi_pvt(tmp);
12362                return NULL;
12363             } else {
12364                si.spanno = 0;
12365                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12366                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12367                   destroy_dahdi_pvt(tmp);
12368                   return NULL;
12369                }
12370                /* Store the logical span first based upon the real span */
12371                tmp->logicalspan = pris[span].prilogicalspan;
12372                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12373                if (span < 0) {
12374                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12375                   destroy_dahdi_pvt(tmp);
12376                   return NULL;
12377                }
12378                myswitchtype = conf->pri.pri.switchtype;
12379                /* Make sure this isn't a d-channel */
12380                matchesdchan=0;
12381                for (x = 0; x < NUM_SPANS; x++) {
12382                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12383                      if (pris[x].dchannels[y] == tmp->channel) {
12384                         matchesdchan = 1;
12385                         break;
12386                      }
12387                   }
12388                }
12389                if (!matchesdchan) {
12390                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12391                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12392                      destroy_dahdi_pvt(tmp);
12393                      return NULL;
12394                   }
12395                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12396                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12397                      destroy_dahdi_pvt(tmp);
12398                      return NULL;
12399                   }
12400                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12401                      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));
12402                      destroy_dahdi_pvt(tmp);
12403                      return NULL;
12404                   }
12405                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12406                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12407                      destroy_dahdi_pvt(tmp);
12408                      return NULL;
12409                   }
12410                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12411                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12412                      destroy_dahdi_pvt(tmp);
12413                      return NULL;
12414                   }
12415                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12416                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12417                      destroy_dahdi_pvt(tmp);
12418                      return NULL;
12419                   }
12420                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12421                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12422                      destroy_dahdi_pvt(tmp);
12423                      return NULL;
12424                   }
12425                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12426                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12427                         pris[span].pri.trunkgroup);
12428                      destroy_dahdi_pvt(tmp);
12429                      return NULL;
12430                   }
12431 
12432                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12433                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12434                   if (!pri_chan) {
12435                      destroy_dahdi_pvt(tmp);
12436                      return NULL;
12437                   }
12438                   tmp->sig_pvt = pri_chan;
12439                   tmp->pri = &pris[span].pri;
12440 
12441                   tmp->priexclusive = conf->chan.priexclusive;
12442 
12443                   if (!tmp->pri->cc_params) {
12444                      tmp->pri->cc_params = ast_cc_config_params_init();
12445                      if (!tmp->pri->cc_params) {
12446                         destroy_dahdi_pvt(tmp);
12447                         return NULL;
12448                      }
12449                   }
12450                   ast_cc_copy_config_params(tmp->pri->cc_params,
12451                      conf->chan.cc_params);
12452 
12453                   pris[span].pri.sig = chan_sig;
12454                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12455                   pris[span].pri.switchtype = myswitchtype;
12456                   pris[span].pri.nsf = conf->pri.pri.nsf;
12457                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12458                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12459                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12460                   pris[span].pri.minunused = conf->pri.pri.minunused;
12461                   pris[span].pri.minidle = conf->pri.pri.minidle;
12462                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12463                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12464                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12465 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12466                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12467 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12468 #ifdef HAVE_PRI_INBANDDISCONNECT
12469                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12470 #endif
12471 #if defined(HAVE_PRI_CALL_HOLD)
12472                   pris[span].pri.hold_disconnect_transfer =
12473                      conf->pri.pri.hold_disconnect_transfer;
12474 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12475 #if defined(HAVE_PRI_CCSS)
12476                   pris[span].pri.cc_ptmp_recall_mode =
12477                      conf->pri.pri.cc_ptmp_recall_mode;
12478                   pris[span].pri.cc_qsig_signaling_link_req =
12479                      conf->pri.pri.cc_qsig_signaling_link_req;
12480                   pris[span].pri.cc_qsig_signaling_link_rsp =
12481                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12482 #endif   /* defined(HAVE_PRI_CCSS) */
12483 #if defined(HAVE_PRI_CALL_WAITING)
12484                   pris[span].pri.max_call_waiting_calls =
12485                      conf->pri.pri.max_call_waiting_calls;
12486                   pris[span].pri.allow_call_waiting_calls =
12487                      conf->pri.pri.allow_call_waiting_calls;
12488 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12489                   pris[span].pri.transfer = conf->chan.transfer;
12490                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12491 #if defined(HAVE_PRI_L2_PERSISTENCE)
12492                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12493 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12494 #if defined(HAVE_PRI_AOC_EVENTS)
12495                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12496                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12497 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12498                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12499                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12500                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12501 #if defined(HAVE_PRI_MWI)
12502                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12503                      conf->pri.pri.mwi_mailboxes,
12504                      sizeof(pris[span].pri.mwi_mailboxes));
12505 #endif   /* defined(HAVE_PRI_MWI) */
12506                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12507                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12508                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12509                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12510                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12511                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12512                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12513                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12514 
12515                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12516                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12517                   }
12518 
12519 #if defined(HAVE_PRI_CALL_WAITING)
12520                   /* Channel initial config parameters. */
12521                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12522                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12523                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12524                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12525                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12526                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12527                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12528                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12529                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12530                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12531 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12532                } else {
12533                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12534                   destroy_dahdi_pvt(tmp);
12535                   return NULL;
12536                }
12537             }
12538          }
12539 #endif
12540       } else {
12541          /* already exists in interface list */
12542          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));
12543          chan_sig = tmp->sig;
12544          if (tmp->subs[SUB_REAL].dfd > -1) {
12545             memset(&p, 0, sizeof(p));
12546             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12547          }
12548       }
12549       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12550       switch (chan_sig) {
12551       case SIG_FXSKS:
12552       case SIG_FXSLS:
12553       case SIG_EM:
12554       case SIG_EM_E1:
12555       case SIG_EMWINK:
12556       case SIG_FEATD:
12557       case SIG_FEATDMF:
12558       case SIG_FEATDMF_TA:
12559       case SIG_FEATB:
12560       case SIG_E911:
12561       case SIG_SF:
12562       case SIG_SFWINK:
12563       case SIG_FGC_CAMA:
12564       case SIG_FGC_CAMAMF:
12565       case SIG_SF_FEATD:
12566       case SIG_SF_FEATDMF:
12567       case SIG_SF_FEATB:
12568          p.starttime = 250;
12569          break;
12570       }
12571 
12572       if (tmp->radio) {
12573          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12574          p.channo = channel;
12575          p.rxwinktime = 1;
12576          p.rxflashtime = 1;
12577          p.starttime = 1;
12578          p.debouncetime = 5;
12579       } else {
12580          p.channo = channel;
12581          /* Override timing settings based on config file */
12582          if (conf->timing.prewinktime >= 0)
12583             p.prewinktime = conf->timing.prewinktime;
12584          if (conf->timing.preflashtime >= 0)
12585             p.preflashtime = conf->timing.preflashtime;
12586          if (conf->timing.winktime >= 0)
12587             p.winktime = conf->timing.winktime;
12588          if (conf->timing.flashtime >= 0)
12589             p.flashtime = conf->timing.flashtime;
12590          if (conf->timing.starttime >= 0)
12591             p.starttime = conf->timing.starttime;
12592          if (conf->timing.rxwinktime >= 0)
12593             p.rxwinktime = conf->timing.rxwinktime;
12594          if (conf->timing.rxflashtime >= 0)
12595             p.rxflashtime = conf->timing.rxflashtime;
12596          if (conf->timing.debouncetime >= 0)
12597             p.debouncetime = conf->timing.debouncetime;
12598       }
12599 
12600       /* don't set parms on a pseudo-channel */
12601       if (tmp->subs[SUB_REAL].dfd >= 0)
12602       {
12603          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12604          if (res < 0) {
12605             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12606             destroy_dahdi_pvt(tmp);
12607             return NULL;
12608          }
12609       }
12610 #if 1
12611       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12612          memset(&bi, 0, sizeof(bi));
12613          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12614          if (!res) {
12615             bi.txbufpolicy = conf->chan.buf_policy;
12616             bi.rxbufpolicy = conf->chan.buf_policy;
12617             bi.numbufs = conf->chan.buf_no;
12618             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12619             if (res < 0) {
12620                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12621             }
12622          } else {
12623             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12624          }
12625          tmp->buf_policy = conf->chan.buf_policy;
12626          tmp->buf_no = conf->chan.buf_no;
12627          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12628          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12629          tmp->faxbuf_no = conf->chan.faxbuf_no;
12630          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12631           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12632           * The reason the ioctl call above failed should to be determined before worrying about the
12633           * faxbuffer-related ioctl calls */
12634          tmp->bufsize = bi.bufsize;
12635       }
12636 #endif
12637       tmp->immediate = conf->chan.immediate;
12638       tmp->transfertobusy = conf->chan.transfertobusy;
12639       if (chan_sig & __DAHDI_SIG_FXS) {
12640          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12641          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12642          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12643       }
12644       tmp->ringt_base = ringt_base;
12645       tmp->firstradio = 0;
12646       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12647          tmp->permcallwaiting = conf->chan.callwaiting;
12648       else
12649          tmp->permcallwaiting = 0;
12650       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12651       tmp->destroy = 0;
12652       tmp->drings = conf->chan.drings;
12653 
12654       /* 10 is a nice default. */
12655       if (tmp->drings.ringnum[0].range == 0)
12656          tmp->drings.ringnum[0].range = 10;
12657       if (tmp->drings.ringnum[1].range == 0)
12658          tmp->drings.ringnum[1].range = 10;
12659       if (tmp->drings.ringnum[2].range == 0)
12660          tmp->drings.ringnum[2].range = 10;
12661 
12662       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12663       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12664       tmp->threewaycalling = conf->chan.threewaycalling;
12665       tmp->adsi = conf->chan.adsi;
12666       tmp->use_smdi = conf->chan.use_smdi;
12667       tmp->permhidecallerid = conf->chan.hidecallerid;
12668       tmp->hidecalleridname = conf->chan.hidecalleridname;
12669       tmp->callreturn = conf->chan.callreturn;
12670       tmp->echocancel = conf->chan.echocancel;
12671       tmp->echotraining = conf->chan.echotraining;
12672       tmp->pulse = conf->chan.pulse;
12673       if (tmp->echocancel.head.tap_length) {
12674          tmp->echocanbridged = conf->chan.echocanbridged;
12675       } else {
12676          if (conf->chan.echocanbridged)
12677             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12678          tmp->echocanbridged = 0;
12679       }
12680       tmp->busydetect = conf->chan.busydetect;
12681       tmp->busycount = conf->chan.busycount;
12682       tmp->busy_tonelength = conf->chan.busy_tonelength;
12683       tmp->busy_quietlength = conf->chan.busy_quietlength;
12684       tmp->callprogress = conf->chan.callprogress;
12685       tmp->waitfordialtone = conf->chan.waitfordialtone;
12686       tmp->cancallforward = conf->chan.cancallforward;
12687       tmp->dtmfrelax = conf->chan.dtmfrelax;
12688       tmp->callwaiting = tmp->permcallwaiting;
12689       tmp->hidecallerid = tmp->permhidecallerid;
12690       tmp->channel = channel;
12691       tmp->stripmsd = conf->chan.stripmsd;
12692       tmp->use_callerid = conf->chan.use_callerid;
12693       tmp->cid_signalling = conf->chan.cid_signalling;
12694       tmp->cid_start = conf->chan.cid_start;
12695       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12696       tmp->restrictcid = conf->chan.restrictcid;
12697       tmp->use_callingpres = conf->chan.use_callingpres;
12698       if (tmp->usedistinctiveringdetection) {
12699          if (!tmp->use_callerid) {
12700             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12701             tmp->use_callerid = 1;
12702          }
12703       }
12704 
12705       if (tmp->cid_signalling == CID_SIG_SMDI) {
12706          if (!tmp->use_smdi) {
12707             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12708             tmp->use_smdi = 1;
12709          }
12710       }
12711       if (tmp->use_smdi) {
12712          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12713          if (!(tmp->smdi_iface)) {
12714             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12715             tmp->use_smdi = 0;
12716          }
12717       }
12718 
12719       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12720       tmp->amaflags = conf->chan.amaflags;
12721       if (!here) {
12722          tmp->confno = -1;
12723          tmp->propconfno = -1;
12724       }
12725       tmp->canpark = conf->chan.canpark;
12726       tmp->transfer = conf->chan.transfer;
12727       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12728       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12729       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12730       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12731       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12732       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12733       tmp->cid_ton = 0;
12734       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12735          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12736          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12737       } else {
12738          tmp->cid_num[0] = '\0';
12739          tmp->cid_name[0] = '\0';
12740       }
12741 #if defined(HAVE_PRI)
12742       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12743          tmp->cid_tag[0] = '\0';
12744       } else
12745 #endif   /* defined(HAVE_PRI) */
12746       {
12747          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12748       }
12749       tmp->cid_subaddr[0] = '\0';
12750       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12751       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12752          char *mailbox, *context;
12753          mailbox = context = ast_strdupa(tmp->mailbox);
12754          strsep(&context, "@");
12755          if (ast_strlen_zero(context))
12756             context = "default";
12757          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12758             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12759             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12760             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12761             AST_EVENT_IE_END);
12762       }
12763 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12764       tmp->mwisend_setting = conf->chan.mwisend_setting;
12765       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12766       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12767 #endif
12768 
12769       tmp->group = conf->chan.group;
12770       tmp->callgroup = conf->chan.callgroup;
12771       tmp->pickupgroup= conf->chan.pickupgroup;
12772       if (conf->chan.vars) {
12773          struct ast_variable *v, *tmpvar;
12774                    for (v = conf->chan.vars ; v ; v = v->next) {
12775                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12776                                   tmpvar->next = tmp->vars;
12777                                    tmp->vars = tmpvar;
12778                            }
12779                   }
12780       }
12781       tmp->cid_rxgain = conf->chan.cid_rxgain;
12782       tmp->rxgain = conf->chan.rxgain;
12783       tmp->txgain = conf->chan.txgain;
12784       tmp->txdrc = conf->chan.txdrc;
12785       tmp->rxdrc = conf->chan.rxdrc;
12786       tmp->tonezone = conf->chan.tonezone;
12787       if (tmp->subs[SUB_REAL].dfd > -1) {
12788          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12789          if (tmp->dsp)
12790             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12791          update_conf(tmp);
12792          if (!here) {
12793             switch (chan_sig) {
12794             case SIG_PRI_LIB_HANDLE_CASES:
12795             case SIG_SS7:
12796             case SIG_MFCR2:
12797                break;
12798             default:
12799                /* Hang it up to be sure it's good */
12800                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12801                break;
12802             }
12803          }
12804          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12805          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12806             /* the dchannel is down so put the channel in alarm */
12807             switch (tmp->sig) {
12808 #ifdef HAVE_PRI
12809             case SIG_PRI_LIB_HANDLE_CASES:
12810                sig_pri_set_alarm(tmp->sig_pvt, 1);
12811                break;
12812 #endif
12813 #if defined(HAVE_SS7)
12814             case SIG_SS7:
12815                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12816                break;
12817 #endif   /* defined(HAVE_SS7) */
12818             default:
12819                /* The only sig submodule left should be sig_analog. */
12820                analog_p = tmp->sig_pvt;
12821                if (analog_p) {
12822                   analog_p->inalarm = 1;
12823                }
12824                tmp->inalarm = 1;
12825                break;
12826             }
12827             handle_alarms(tmp, res);
12828          }
12829       }
12830 
12831       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12832       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12833       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12834       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12835       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12836 
12837       if (!here) {
12838          tmp->locallyblocked = 0;
12839          tmp->remotelyblocked = 0;
12840          switch (tmp->sig) {
12841 #if defined(HAVE_PRI)
12842          case SIG_PRI_LIB_HANDLE_CASES:
12843             tmp->inservice = 1;/* Inservice until actually implemented. */
12844 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12845             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12846             if (chan_sig == SIG_PRI) {
12847                char db_chan_name[20];
12848                char db_answer[5];
12849 
12850                /*
12851                 * Initialize the active out-of-service status
12852                 * and delete any record if the feature is not enabled.
12853                 */
12854                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12855                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12856                   unsigned *why;
12857 
12858                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12859                   if (tmp->pri->enable_service_message_support) {
12860                      char state;
12861 
12862                      sscanf(db_answer, "%1c:%30u", &state, why);
12863 
12864                      /* Ensure that only the implemented bits could be set.*/
12865                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12866                   }
12867                   if (!*why) {
12868                      ast_db_del(db_chan_name, SRVST_DBKEY);
12869                   }
12870                }
12871             }
12872 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12873             break;
12874 #endif   /* defined(HAVE_PRI) */
12875 #if defined(HAVE_SS7)
12876          case SIG_SS7:
12877             tmp->inservice = 0;
12878             break;
12879 #endif   /* defined(HAVE_SS7) */
12880          default:
12881              /* We default to in service on protocols that don't have a reset */
12882             tmp->inservice = 1;
12883             break;
12884          }
12885       }
12886 
12887       switch (tmp->sig) {
12888 #if defined(HAVE_PRI)
12889       case SIG_PRI_LIB_HANDLE_CASES:
12890          if (pri_chan) {
12891             pri_chan->channel = tmp->channel;
12892             pri_chan->hidecallerid = tmp->hidecallerid;
12893             pri_chan->hidecalleridname = tmp->hidecalleridname;
12894             pri_chan->immediate = tmp->immediate;
12895             pri_chan->inalarm = tmp->inalarm;
12896             pri_chan->priexclusive = tmp->priexclusive;
12897             pri_chan->priindication_oob = tmp->priindication_oob;
12898             pri_chan->use_callerid = tmp->use_callerid;
12899             pri_chan->use_callingpres = tmp->use_callingpres;
12900             ast_copy_string(pri_chan->context, tmp->context,
12901                sizeof(pri_chan->context));
12902             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12903                sizeof(pri_chan->mohinterpret));
12904             pri_chan->stripmsd = tmp->stripmsd;
12905          }
12906          break;
12907 #endif   /* defined(HAVE_PRI) */
12908 #if defined(HAVE_SS7)
12909       case SIG_SS7:
12910          if (ss7_chan) {
12911             ss7_chan->inalarm = tmp->inalarm;
12912 
12913             ss7_chan->stripmsd = tmp->stripmsd;
12914             ss7_chan->hidecallerid = tmp->hidecallerid;
12915             ss7_chan->use_callerid = tmp->use_callerid;
12916             ss7_chan->use_callingpres = tmp->use_callingpres;
12917             ss7_chan->immediate = tmp->immediate;
12918             ss7_chan->locallyblocked = tmp->locallyblocked;
12919             ss7_chan->remotelyblocked = tmp->remotelyblocked;
12920             ast_copy_string(ss7_chan->context, tmp->context,
12921                sizeof(ss7_chan->context));
12922             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12923                sizeof(ss7_chan->mohinterpret));
12924          }
12925          break;
12926 #endif   /* defined(HAVE_SS7) */
12927       default:
12928          /* The only sig submodule left should be sig_analog. */
12929          analog_p = tmp->sig_pvt;
12930          if (analog_p) {
12931             analog_p->channel = tmp->channel;
12932             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12933             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12934             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12935             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12936             analog_p->callreturn = conf->chan.callreturn;
12937             analog_p->cancallforward = conf->chan.cancallforward;
12938             analog_p->canpark = conf->chan.canpark;
12939             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12940             analog_p->immediate = conf->chan.immediate;
12941             analog_p->permhidecallerid = conf->chan.permhidecallerid;
12942             analog_p->pulse = conf->chan.pulse;
12943             analog_p->threewaycalling = conf->chan.threewaycalling;
12944             analog_p->transfer = conf->chan.transfer;
12945             analog_p->transfertobusy = conf->chan.transfertobusy;
12946             analog_p->use_callerid = tmp->use_callerid;
12947             analog_p->use_smdi = tmp->use_smdi;
12948             analog_p->smdi_iface = tmp->smdi_iface;
12949             analog_p->outsigmod = ANALOG_SIG_NONE;
12950             analog_p->echotraining = conf->chan.echotraining;
12951             analog_p->cid_signalling = conf->chan.cid_signalling;
12952             analog_p->stripmsd = conf->chan.stripmsd;
12953             switch (conf->chan.cid_start) {
12954             case CID_START_POLARITY:
12955                analog_p->cid_start = ANALOG_CID_START_POLARITY;
12956                break;
12957             case CID_START_POLARITY_IN:
12958                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12959                break;
12960             case CID_START_DTMF_NOALERT:
12961                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12962                break;
12963             default:
12964                analog_p->cid_start = ANALOG_CID_START_RING;
12965                break;
12966             }
12967             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12968             analog_p->ringt = conf->chan.ringt;
12969             analog_p->ringt_base = ringt_base;
12970             analog_p->chan_tech = &dahdi_tech;
12971             analog_p->onhooktime = time(NULL);
12972             if (chan_sig & __DAHDI_SIG_FXO) {
12973                memset(&p, 0, sizeof(p));
12974                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12975                if (!res) {
12976                   analog_p->fxsoffhookstate = p.rxisoffhook;
12977                }
12978 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12979                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12980 #endif
12981             }
12982             analog_p->msgstate = -1;
12983 
12984             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12985             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12986             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12987 
12988             analog_config_complete(analog_p);
12989          }
12990          break;
12991       }
12992 #if defined(HAVE_PRI)
12993       if (tmp->channel == CHAN_PSEUDO) {
12994          /*
12995           * Save off pseudo channel buffer policy values for dynamic creation of
12996           * no B channel interfaces.
12997           */
12998          dahdi_pseudo_parms.buf_no = tmp->buf_no;
12999          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13000          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13001          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13002       }
13003 #endif   /* defined(HAVE_PRI) */
13004    }
13005    if (tmp && !here) {
13006       /* Add the new channel interface to the sorted channel interface list. */
13007       dahdi_iflist_insert(tmp);
13008    }
13009    return tmp;
13010 }
13011 
13012 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13013 {
13014 #if defined(HAVE_PRI)
13015    if (0 < span) {
13016       /* The channel must be on the specified PRI span. */
13017       if (!p->pri || p->pri->span != span) {
13018          return 0;
13019       }
13020       if (!groupmatch && channelmatch == -1) {
13021          /* Match any group since it only needs to be on the PRI span. */
13022          *groupmatched = 1;
13023          return 1;
13024       }
13025    }
13026 #endif   /* defined(HAVE_PRI) */
13027    /* check group matching */
13028    if (groupmatch) {
13029       if ((p->group & groupmatch) != groupmatch)
13030          /* Doesn't match the specified group, try the next one */
13031          return 0;
13032       *groupmatched = 1;
13033    }
13034    /* Check to see if we have a channel match */
13035    if (channelmatch != -1) {
13036       if (p->channel != channelmatch)
13037          /* Doesn't match the specified channel, try the next one */
13038          return 0;
13039       *channelmatched = 1;
13040    }
13041 
13042    return 1;
13043 }
13044 
13045 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13046 {
13047    struct dahdi_pvt *p = *pvt;
13048 
13049    if (p->inalarm)
13050       return 0;
13051 
13052    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13053       return analog_available(p->sig_pvt);
13054 
13055    switch (p->sig) {
13056 #if defined(HAVE_PRI)
13057    case SIG_PRI_LIB_HANDLE_CASES:
13058       {
13059          struct sig_pri_chan *pvt_chan;
13060          int res;
13061 
13062          pvt_chan = p->sig_pvt;
13063          res = sig_pri_available(&pvt_chan, is_specific_channel);
13064          *pvt = pvt_chan->chan_pvt;
13065          return res;
13066       }
13067 #endif   /* defined(HAVE_PRI) */
13068 #if defined(HAVE_SS7)
13069    case SIG_SS7:
13070       return sig_ss7_available(p->sig_pvt);
13071 #endif   /* defined(HAVE_SS7) */
13072    default:
13073       break;
13074    }
13075 
13076    if (p->locallyblocked || p->remotelyblocked) {
13077       return 0;
13078    }
13079 
13080    /* If no owner definitely available */
13081    if (!p->owner) {
13082 #ifdef HAVE_OPENR2
13083       /* Trust MFC/R2 */
13084       if (p->mfcr2) {
13085          if (p->mfcr2call) {
13086             return 0;
13087          } else {
13088             return 1;
13089          }
13090       }
13091 #endif
13092       return 1;
13093    }
13094 
13095    return 0;
13096 }
13097 
13098 #if defined(HAVE_PRI)
13099 #if defined(HAVE_PRI_CALL_WAITING)
13100 /*!
13101  * \internal
13102  * \brief Init the private channel configuration using the span controller.
13103  * \since 1.8
13104  *
13105  * \param priv Channel to init the configuration.
13106  * \param pri sig_pri PRI control structure.
13107  *
13108  * \note Assumes the pri->lock is already obtained.
13109  *
13110  * \return Nothing
13111  */
13112 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13113 {
13114    struct dahdi_pvt *pvt = priv;
13115 
13116    pvt->stripmsd = pri->ch_cfg.stripmsd;
13117    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13118    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13119    pvt->immediate = pri->ch_cfg.immediate;
13120    pvt->priexclusive = pri->ch_cfg.priexclusive;
13121    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13122    pvt->use_callerid = pri->ch_cfg.use_callerid;
13123    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13124    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13125    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13126 }
13127 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13128 #endif   /* defined(HAVE_PRI) */
13129 
13130 #if defined(HAVE_PRI)
13131 /*!
13132  * \internal
13133  * \brief Create a no B channel interface.
13134  * \since 1.8
13135  *
13136  * \param pri sig_pri span controller to add interface.
13137  *
13138  * \note Assumes the pri->lock is already obtained.
13139  *
13140  * \retval array-index into private pointer array on success.
13141  * \retval -1 on error.
13142  */
13143 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13144 {
13145    int pvt_idx;
13146    int res;
13147    unsigned idx;
13148    struct dahdi_pvt *pvt;
13149    struct sig_pri_chan *chan;
13150    struct dahdi_bufferinfo bi;
13151 
13152    static int nobch_channel = CHAN_PSEUDO;
13153 
13154    /* Find spot in the private pointer array for new interface. */
13155    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13156       if (!pri->pvts[pvt_idx]) {
13157          break;
13158       }
13159    }
13160    if (pri->numchans == pvt_idx) {
13161       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13162          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13163          return -1;
13164       }
13165 
13166       /* Add new spot to the private pointer array. */
13167       pri->pvts[pvt_idx] = NULL;
13168       ++pri->numchans;
13169    }
13170 
13171    pvt = ast_calloc(1, sizeof(*pvt));
13172    if (!pvt) {
13173       return -1;
13174    }
13175    pvt->cc_params = ast_cc_config_params_init();
13176    if (!pvt->cc_params) {
13177       ast_free(pvt);
13178       return -1;
13179    }
13180    ast_mutex_init(&pvt->lock);
13181    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13182       pvt->subs[idx].dfd = -1;
13183    }
13184    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13185    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13186    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13187    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13188 
13189    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13190    if (!chan) {
13191       destroy_dahdi_pvt(pvt);
13192       return -1;
13193    }
13194    chan->no_b_channel = 1;
13195 
13196    /*
13197     * Pseudo channel companding law.
13198     * Needed for outgoing call waiting calls.
13199     * XXX May need to make this determined by switchtype or user option.
13200     */
13201    pvt->law_default = DAHDI_LAW_ALAW;
13202 
13203    pvt->sig = pri->sig;
13204    pvt->outsigmod = -1;
13205    pvt->pri = pri;
13206    pvt->sig_pvt = chan;
13207    pri->pvts[pvt_idx] = chan;
13208 
13209    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13210    if (pvt->subs[SUB_REAL].dfd < 0) {
13211       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13212          strerror(errno));
13213       destroy_dahdi_pvt(pvt);
13214       return -1;
13215    }
13216    memset(&bi, 0, sizeof(bi));
13217    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13218    if (!res) {
13219       pvt->bufsize = bi.bufsize;
13220       bi.txbufpolicy = pvt->buf_policy;
13221       bi.rxbufpolicy = pvt->buf_policy;
13222       bi.numbufs = pvt->buf_no;
13223       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13224       if (res < 0) {
13225          ast_log(LOG_WARNING,
13226             "Unable to set buffer policy on no B channel interface: %s\n",
13227             strerror(errno));
13228       }
13229    } else
13230       ast_log(LOG_WARNING,
13231          "Unable to check buffer policy on no B channel interface: %s\n",
13232          strerror(errno));
13233 
13234    --nobch_channel;
13235    if (CHAN_PSEUDO < nobch_channel) {
13236       nobch_channel = CHAN_PSEUDO - 1;
13237    }
13238    pvt->channel = nobch_channel;
13239    pvt->span = pri->span;
13240    chan->channel = pvt->channel;
13241 
13242    dahdi_nobch_insert(pri, pvt);
13243 
13244    return pvt_idx;
13245 }
13246 #endif   /* defined(HAVE_PRI) */
13247 
13248 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13249    structures; it makes no attempt to safely copy regular channel private
13250    structures that might contain reference-counted object pointers and other
13251    scary bits
13252 */
13253 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13254 {
13255    struct dahdi_pvt *p;
13256    struct dahdi_bufferinfo bi;
13257    int res;
13258 
13259    p = ast_malloc(sizeof(*p));
13260    if (!p) {
13261       return NULL;
13262    }
13263    *p = *src;
13264 
13265    /* Must deep copy the cc_params. */
13266    p->cc_params = ast_cc_config_params_init();
13267    if (!p->cc_params) {
13268       ast_free(p);
13269       return NULL;
13270    }
13271    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13272 
13273    p->which_iflist = DAHDI_IFLIST_NONE;
13274    p->next = NULL;
13275    p->prev = NULL;
13276    ast_mutex_init(&p->lock);
13277    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13278    if (p->subs[SUB_REAL].dfd < 0) {
13279       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13280       destroy_dahdi_pvt(p);
13281       return NULL;
13282    }
13283    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13284    if (!res) {
13285       bi.txbufpolicy = src->buf_policy;
13286       bi.rxbufpolicy = src->buf_policy;
13287       bi.numbufs = src->buf_no;
13288       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13289       if (res < 0) {
13290          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13291       }
13292    } else
13293       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13294    p->destroy = 1;
13295    dahdi_iflist_insert(p);
13296    return p;
13297 }
13298 
13299 struct dahdi_starting_point {
13300    /*! Group matching mask.  Zero if not specified. */
13301    ast_group_t groupmatch;
13302    /*! DAHDI channel to match with.  -1 if not specified. */
13303    int channelmatch;
13304    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13305    int rr_starting_point;
13306    /*! ISDN span where channels can be picked (Zero if not specified) */
13307    int span;
13308    /*! Analog channel distinctive ring cadance index. */
13309    int cadance;
13310    /*! Dialing option. c/r/d if present and valid. */
13311    char opt;
13312    /*! TRUE if to search the channel list backwards. */
13313    char backwards;
13314    /*! TRUE if search is done with round robin sequence. */
13315    char roundrobin;
13316 };
13317 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13318 {
13319    char *dest;
13320    char *s;
13321    int x;
13322    int res = 0;
13323    struct dahdi_pvt *p;
13324    char *subdir = NULL;
13325    AST_DECLARE_APP_ARGS(args,
13326       AST_APP_ARG(group);  /* channel/group token */
13327       //AST_APP_ARG(ext);  /* extension token */
13328       //AST_APP_ARG(opts); /* options token */
13329       AST_APP_ARG(other);  /* Any remining unused arguments */
13330    );
13331 
13332    /*
13333     * data is ---v
13334     * Dial(DAHDI/pseudo[/extension[/options]])
13335     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13336     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13337     * Dial(DAHDI/i<span>[/extension[/options]])
13338     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13339     *
13340     * i - ISDN span channel restriction.
13341     *     Used by CC to ensure that the CC recall goes out the same span.
13342     *     Also to make ISDN channel names dialable when the sequence number
13343     *     is stripped off.  (Used by DTMF attended transfer feature.)
13344     *
13345     * g - channel group allocation search forward
13346     * G - channel group allocation search backward
13347     * r - channel group allocation round robin search forward
13348     * R - channel group allocation round robin search backward
13349     *
13350     * c - Wait for DTMF digit to confirm answer
13351     * r<cadance#> - Set distintive ring cadance number
13352     * d - Force bearer capability for ISDN/SS7 call to digital.
13353     */
13354 
13355    if (data) {
13356       dest = ast_strdupa(data);
13357    } else {
13358       ast_log(LOG_WARNING, "Channel requested with no data\n");
13359       return NULL;
13360    }
13361    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13362    if (!args.argc || ast_strlen_zero(args.group)) {
13363       ast_log(LOG_WARNING, "No channel/group specified\n");
13364       return NULL;
13365    }
13366 
13367    /* Initialize the output parameters */
13368    memset(param, 0, sizeof(*param));
13369    param->channelmatch = -1;
13370 
13371    if (strchr(args.group, '!') != NULL) {
13372       char *prev = args.group;
13373       while ((s = strchr(prev, '!')) != NULL) {
13374          *s++ = '/';
13375          prev = s;
13376       }
13377       *(prev - 1) = '\0';
13378       subdir = args.group;
13379       args.group = prev;
13380    } else if (args.group[0] == 'i') {
13381       /* Extract the ISDN span channel restriction specifier. */
13382       res = sscanf(args.group + 1, "%30d", &x);
13383       if (res < 1) {
13384          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13385          return NULL;
13386       }
13387       param->span = x;
13388 
13389       /* Remove the ISDN span channel restriction specifier. */
13390       s = strchr(args.group, '-');
13391       if (!s) {
13392          /* Search all groups since we are ISDN span restricted. */
13393          return iflist;
13394       }
13395       args.group = s + 1;
13396       res = 0;
13397    }
13398    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13399       /* Retrieve the group number */
13400       s = args.group + 1;
13401       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13402       if (res < 1) {
13403          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13404          return NULL;
13405       }
13406       param->groupmatch = ((ast_group_t) 1 << x);
13407 
13408       if (toupper(args.group[0]) == 'G') {
13409          if (args.group[0] == 'G') {
13410             param->backwards = 1;
13411             p = ifend;
13412          } else
13413             p = iflist;
13414       } else {
13415          if (ARRAY_LEN(round_robin) <= x) {
13416             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13417                x, data);
13418             return NULL;
13419          }
13420          if (args.group[0] == 'R') {
13421             param->backwards = 1;
13422             p = round_robin[x] ? round_robin[x]->prev : ifend;
13423             if (!p)
13424                p = ifend;
13425          } else {
13426             p = round_robin[x] ? round_robin[x]->next : iflist;
13427             if (!p)
13428                p = iflist;
13429          }
13430          param->roundrobin = 1;
13431          param->rr_starting_point = x;
13432       }
13433    } else {
13434       s = args.group;
13435       if (!strcasecmp(s, "pseudo")) {
13436          /* Special case for pseudo */
13437          x = CHAN_PSEUDO;
13438          param->channelmatch = x;
13439       } else {
13440          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13441          if (res < 1) {
13442             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13443             return NULL;
13444          } else {
13445             param->channelmatch = x;
13446          }
13447       }
13448       if (subdir) {
13449          char path[PATH_MAX];
13450          struct stat stbuf;
13451 
13452          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13453                subdir, param->channelmatch);
13454          if (stat(path, &stbuf) < 0) {
13455             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13456                   path, strerror(errno));
13457             return NULL;
13458          }
13459          if (!S_ISCHR(stbuf.st_mode)) {
13460             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13461                   path);
13462             return NULL;
13463          }
13464          param->channelmatch = minor(stbuf.st_rdev);
13465       }
13466 
13467       p = iflist;
13468    }
13469 
13470    if (param->opt == 'r' && res < 3) {
13471       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13472       param->opt = '\0';
13473    }
13474 
13475    return p;
13476 }
13477 
13478 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13479 {
13480    int callwait = 0;
13481    struct dahdi_pvt *p;
13482    struct ast_channel *tmp = NULL;
13483    struct dahdi_pvt *exitpvt;
13484    int channelmatched = 0;
13485    int groupmatched = 0;
13486 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13487    int transcapdigital = 0;
13488 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13489    struct dahdi_starting_point start;
13490 
13491    ast_mutex_lock(&iflock);
13492    p = determine_starting_point(data, &start);
13493    if (!p) {
13494       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13495       ast_mutex_unlock(&iflock);
13496       return NULL;
13497    }
13498 
13499    /* Search for an unowned channel */
13500    exitpvt = p;
13501    while (p && !tmp) {
13502       if (start.roundrobin)
13503          round_robin[start.rr_starting_point] = p;
13504 
13505       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13506          && available(&p, channelmatched)) {
13507          ast_debug(1, "Using channel %d\n", p->channel);
13508 
13509          callwait = (p->owner != NULL);
13510 #ifdef HAVE_OPENR2
13511          if (p->mfcr2) {
13512             ast_mutex_lock(&p->lock);
13513             if (p->mfcr2call) {
13514                ast_mutex_unlock(&p->lock);
13515                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13516                goto next;
13517             }
13518             p->mfcr2call = 1;
13519             ast_mutex_unlock(&p->lock);
13520          }
13521 #endif
13522          if (p->channel == CHAN_PSEUDO) {
13523             p = duplicate_pseudo(p);
13524             if (!p) {
13525                break;
13526             }
13527          }
13528 
13529          p->distinctivering = 0;
13530          /* Make special notes */
13531          switch (start.opt) {
13532          case '\0':
13533             /* No option present. */
13534             break;
13535          case 'c':
13536             /* Confirm answer */
13537             p->confirmanswer = 1;
13538             break;
13539          case 'r':
13540             /* Distinctive ring */
13541             p->distinctivering = start.cadance;
13542             break;
13543          case 'd':
13544 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13545             /* If this is an ISDN call, make it digital */
13546             transcapdigital = AST_TRANS_CAP_DIGITAL;
13547 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13548             break;
13549          default:
13550             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13551             break;
13552          }
13553 
13554          p->outgoing = 1;
13555          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13556             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13557 #ifdef HAVE_PRI
13558          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13559             /*
13560              * We already have the B channel reserved for this call.  We
13561              * just need to make sure that dahdi_hangup() has completed
13562              * cleaning up before continuing.
13563              */
13564             ast_mutex_lock(&p->lock);
13565             ast_mutex_unlock(&p->lock);
13566 
13567             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13568                sizeof(p->dnid));
13569             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13570 #endif
13571 #if defined(HAVE_SS7)
13572          } else if (p->sig == SIG_SS7) {
13573             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13574 #endif   /* defined(HAVE_SS7) */
13575          } else {
13576             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13577          }
13578          if (!tmp) {
13579             p->outgoing = 0;
13580 #if defined(HAVE_PRI)
13581             switch (p->sig) {
13582             case SIG_PRI_LIB_HANDLE_CASES:
13583 #if defined(HAVE_PRI_CALL_WAITING)
13584                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13585                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13586                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13587                }
13588 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13589                /*
13590                 * This should be the last thing to clear when we are done with
13591                 * the channel.
13592                 */
13593                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13594                break;
13595             default:
13596                break;
13597             }
13598 #endif   /* defined(HAVE_PRI) */
13599          } else {
13600             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13601          }
13602          break;
13603       }
13604 #ifdef HAVE_OPENR2
13605 next:
13606 #endif
13607       if (start.backwards) {
13608          p = p->prev;
13609          if (!p)
13610             p = ifend;
13611       } else {
13612          p = p->next;
13613          if (!p)
13614             p = iflist;
13615       }
13616       /* stop when you roll to the one that we started from */
13617       if (p == exitpvt)
13618          break;
13619    }
13620    ast_mutex_unlock(&iflock);
13621    restart_monitor();
13622    if (cause && !tmp) {
13623       if (callwait || channelmatched) {
13624          *cause = AST_CAUSE_BUSY;
13625       } else if (groupmatched) {
13626          *cause = AST_CAUSE_CONGESTION;
13627       } else {
13628          /*
13629           * We did not match any channel requested.
13630           * Dialplan error requesting non-existant channel?
13631           */
13632       }
13633    }
13634 
13635    return tmp;
13636 }
13637 
13638 /*!
13639  * \internal
13640  * \brief Determine the device state for a given DAHDI device if we can.
13641  * \since 1.8
13642  *
13643  * \param data DAHDI device name after "DAHDI/".
13644  *
13645  * \retval device_state enum ast_device_state value.
13646  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13647  */
13648 static int dahdi_devicestate(void *data)
13649 {
13650 #if defined(HAVE_PRI)
13651    char *device;
13652    unsigned span;
13653    int res;
13654 
13655    device = data;
13656 
13657    if (*device != 'I') {
13658       /* The request is not for an ISDN span device. */
13659       return AST_DEVICE_UNKNOWN;
13660    }
13661    res = sscanf(device, "I%30u", &span);
13662    if (res != 1 || !span || NUM_SPANS < span) {
13663       /* Bad format for ISDN span device name. */
13664       return AST_DEVICE_UNKNOWN;
13665    }
13666    device = strchr(device, '/');
13667    if (!device) {
13668       /* Bad format for ISDN span device name. */
13669       return AST_DEVICE_UNKNOWN;
13670    }
13671 
13672    /*
13673     * Since there are currently no other span devstate's defined,
13674     * it must be congestion.
13675     */
13676 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13677    ++device;
13678    if (!strcmp(device, "congestion"))
13679 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13680    {
13681       return pris[span - 1].pri.congestion_devstate;
13682    }
13683 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13684    else if (!strcmp(device, "threshold")) {
13685       return pris[span - 1].pri.threshold_devstate;
13686    }
13687    return AST_DEVICE_UNKNOWN;
13688 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13689 #else
13690    return AST_DEVICE_UNKNOWN;
13691 #endif   /* defined(HAVE_PRI) */
13692 }
13693 
13694 /*!
13695  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13696  * \since 1.8
13697  *
13698  * \param inbound Incoming asterisk channel.
13699  * \param dest Same dial string passed to dahdi_request().
13700  * \param callback Callback into CC core to announce a busy channel available for CC.
13701  *
13702  * \details
13703  * This callback acts like a forked dial with all prongs of the fork busy.
13704  * Essentially, for each channel that could have taken the call, indicate that
13705  * it is busy.
13706  *
13707  * \retval 0 on success.
13708  * \retval -1 on error.
13709  */
13710 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13711 {
13712    struct dahdi_pvt *p;
13713    struct dahdi_pvt *exitpvt;
13714    struct dahdi_starting_point start;
13715    int groupmatched = 0;
13716    int channelmatched = 0;
13717 
13718    ast_mutex_lock(&iflock);
13719    p = determine_starting_point(dest, &start);
13720    if (!p) {
13721       ast_mutex_unlock(&iflock);
13722       return -1;
13723    }
13724    exitpvt = p;
13725    for (;;) {
13726       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13727          /* We found a potential match. call the callback */
13728          struct ast_str *device_name;
13729          char *dash;
13730          const char *monitor_type;
13731          char dialstring[AST_CHANNEL_NAME];
13732          char full_device_name[AST_CHANNEL_NAME];
13733 
13734          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13735          case AST_CC_MONITOR_NEVER:
13736             break;
13737          case AST_CC_MONITOR_NATIVE:
13738          case AST_CC_MONITOR_ALWAYS:
13739          case AST_CC_MONITOR_GENERIC:
13740 #if defined(HAVE_PRI)
13741             if (dahdi_sig_pri_lib_handles(p->sig)) {
13742                /*
13743                 * ISDN is in a trunk busy condition so we need to monitor
13744                 * the span congestion device state.
13745                 */
13746                snprintf(full_device_name, sizeof(full_device_name),
13747                   "DAHDI/I%d/congestion", p->pri->span);
13748             } else
13749 #endif   /* defined(HAVE_PRI) */
13750             {
13751 #if defined(HAVE_PRI)
13752                device_name = create_channel_name(p, 1, "");
13753 #else
13754                device_name = create_channel_name(p);
13755 #endif   /* defined(HAVE_PRI) */
13756                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13757                   device_name ? ast_str_buffer(device_name) : "");
13758                ast_free(device_name);
13759                /*
13760                 * The portion after the '-' in the channel name is either a random
13761                 * number, a sequence number, or a subchannel number. None are
13762                 * necessary so strip them off.
13763                 */
13764                dash = strrchr(full_device_name, '-');
13765                if (dash) {
13766                   *dash = '\0';
13767                }
13768             }
13769             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13770 
13771             /*
13772              * Analog can only do generic monitoring.
13773              * ISDN is in a trunk busy condition and any "device" is going
13774              * to be busy until a B channel becomes available.  The generic
13775              * monitor can do this task.
13776              */
13777             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13778             callback(inbound,
13779 #if defined(HAVE_PRI)
13780                p->pri ? p->pri->cc_params : p->cc_params,
13781 #else
13782                p->cc_params,
13783 #endif   /* defined(HAVE_PRI) */
13784                monitor_type, full_device_name, dialstring, NULL);
13785             break;
13786          }
13787       }
13788       p = start.backwards ? p->prev : p->next;
13789       if (!p) {
13790          p = start.backwards ? ifend : iflist;
13791       }
13792       if (p == exitpvt) {
13793          break;
13794       }
13795    }
13796    ast_mutex_unlock(&iflock);
13797    return 0;
13798 }
13799 
13800 #if defined(HAVE_SS7)
13801 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13802 {
13803    int i;
13804 
13805    if (ss7) {
13806       for (i = 0; i < NUM_SPANS; i++) {
13807          if (linksets[i].ss7.ss7 == ss7) {
13808             ast_verbose("[%d] %s", i + 1, s);
13809             return;
13810          }
13811       }
13812    }
13813    ast_verbose("%s", s);
13814 }
13815 #endif   /* defined(HAVE_SS7) */
13816 
13817 #if defined(HAVE_SS7)
13818 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13819 {
13820    int i;
13821 
13822    if (ss7) {
13823       for (i = 0; i < NUM_SPANS; i++) {
13824          if (linksets[i].ss7.ss7 == ss7) {
13825             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13826             return;
13827          }
13828       }
13829    }
13830    ast_log(LOG_ERROR, "%s", s);
13831 }
13832 #endif   /* defined(HAVE_SS7) */
13833 
13834 #if defined(HAVE_OPENR2)
13835 static void *mfcr2_monitor(void *data)
13836 {
13837    struct dahdi_mfcr2 *mfcr2 = data;
13838    /* we should be using pthread_key_create
13839       and allocate pollers dynamically.
13840       I think do_monitor() could be leaking, since it
13841       could be cancelled at any time and is not
13842       using thread keys, why?, */
13843    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13844    int res = 0;
13845    int i = 0;
13846    int oldstate = 0;
13847    int quit_loop = 0;
13848    int maxsleep = 20;
13849    int was_idle = 0;
13850    int pollsize = 0;
13851    /* now that we're ready to get calls, unblock our side and
13852       get current line state */
13853    for (i = 0; i < mfcr2->numchans; i++) {
13854       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13855       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13856    }
13857    while (1) {
13858       /* we trust here that the mfcr2 channel list will not ever change once
13859          the module is loaded */
13860       pollsize = 0;
13861       for (i = 0; i < mfcr2->numchans; i++) {
13862          pollers[i].revents = 0;
13863          pollers[i].events = 0;
13864          if (mfcr2->pvts[i]->owner) {
13865             continue;
13866          }
13867          if (!mfcr2->pvts[i]->r2chan) {
13868             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13869             quit_loop = 1;
13870             break;
13871          }
13872          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13873          pollers[i].events = POLLIN | POLLPRI;
13874          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13875          pollsize++;
13876       }
13877       if (quit_loop) {
13878          break;
13879       }
13880       if (pollsize == 0) {
13881          if (!was_idle) {
13882             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13883             was_idle = 1;
13884          }
13885          poll(NULL, 0, maxsleep);
13886          continue;
13887       }
13888       was_idle = 0;
13889       /* probably poll() is a valid cancel point, lets just be on the safe side
13890          by calling pthread_testcancel */
13891       pthread_testcancel();
13892       res = poll(pollers, mfcr2->numchans, maxsleep);
13893       pthread_testcancel();
13894       if ((res < 0) && (errno != EINTR)) {
13895          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13896          break;
13897       }
13898       /* do we want to allow to cancel while processing events? */
13899       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13900       for (i = 0; i < mfcr2->numchans; i++) {
13901          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13902             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13903          }
13904       }
13905       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13906    }
13907    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13908    return 0;
13909 }
13910 #endif /* HAVE_OPENR2 */
13911 
13912 #if defined(HAVE_PRI)
13913 #ifndef PRI_RESTART
13914 #error "Upgrade your libpri"
13915 #endif
13916 static void dahdi_pri_message(struct pri *pri, char *s)
13917 {
13918    int x;
13919    int y;
13920    int dchan = -1;
13921    int span = -1;
13922    int dchancount = 0;
13923 
13924    if (pri) {
13925       for (x = 0; x < NUM_SPANS; x++) {
13926          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13927             if (pris[x].pri.dchans[y]) {
13928                dchancount++;
13929             }
13930 
13931             if (pris[x].pri.dchans[y] == pri) {
13932                dchan = y;
13933             }
13934          }
13935          if (dchan >= 0) {
13936             span = x;
13937             break;
13938          }
13939          dchancount = 0;
13940       }
13941       if (-1 < span) {
13942          if (1 < dchancount) {
13943             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13944          } else {
13945             ast_verbose("PRI Span: %d %s", span + 1, s);
13946          }
13947       } else {
13948          ast_verbose("PRI Span: ? %s", s);
13949       }
13950    } else {
13951       ast_verbose("PRI Span: ? %s", s);
13952    }
13953 
13954    ast_mutex_lock(&pridebugfdlock);
13955 
13956    if (pridebugfd >= 0) {
13957       if (write(pridebugfd, s, strlen(s)) < 0) {
13958          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13959       }
13960    }
13961 
13962    ast_mutex_unlock(&pridebugfdlock);
13963 }
13964 #endif   /* defined(HAVE_PRI) */
13965 
13966 #if defined(HAVE_PRI)
13967 static void dahdi_pri_error(struct pri *pri, char *s)
13968 {
13969    int x;
13970    int y;
13971    int dchan = -1;
13972    int span = -1;
13973    int dchancount = 0;
13974 
13975    if (pri) {
13976       for (x = 0; x < NUM_SPANS; x++) {
13977          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13978             if (pris[x].pri.dchans[y]) {
13979                dchancount++;
13980             }
13981 
13982             if (pris[x].pri.dchans[y] == pri) {
13983                dchan = y;
13984             }
13985          }
13986          if (dchan >= 0) {
13987             span = x;
13988             break;
13989          }
13990          dchancount = 0;
13991       }
13992       if (-1 < span) {
13993          if (1 < dchancount) {
13994             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13995          } else {
13996             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
13997          }
13998       } else {
13999          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14000       }
14001    } else {
14002       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14003    }
14004 
14005    ast_mutex_lock(&pridebugfdlock);
14006 
14007    if (pridebugfd >= 0) {
14008       if (write(pridebugfd, s, strlen(s)) < 0) {
14009          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14010       }
14011    }
14012 
14013    ast_mutex_unlock(&pridebugfdlock);
14014 }
14015 #endif   /* defined(HAVE_PRI) */
14016 
14017 #if defined(HAVE_PRI)
14018 static int prepare_pri(struct dahdi_pri *pri)
14019 {
14020    int i, res, x;
14021    struct dahdi_params p;
14022    struct dahdi_bufferinfo bi;
14023    struct dahdi_spaninfo si;
14024 
14025    pri->pri.calls = &dahdi_pri_callbacks;
14026 
14027    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14028       if (!pri->dchannels[i])
14029          break;
14030       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14031       x = pri->dchannels[i];
14032       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14033          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14034          return -1;
14035       }
14036       memset(&p, 0, sizeof(p));
14037       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14038       if (res) {
14039          dahdi_close_pri_fd(pri, i);
14040          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14041          return -1;
14042       }
14043       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14044          dahdi_close_pri_fd(pri, i);
14045          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14046          return -1;
14047       }
14048       memset(&si, 0, sizeof(si));
14049       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14050       if (res) {
14051          dahdi_close_pri_fd(pri, i);
14052          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14053       }
14054       if (!si.alarms) {
14055          pri_event_noalarm(&pri->pri, i, 1);
14056       } else {
14057          pri_event_alarm(&pri->pri, i, 1);
14058       }
14059       memset(&bi, 0, sizeof(bi));
14060       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14061       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14062       bi.numbufs = 32;
14063       bi.bufsize = 1024;
14064       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14065          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14066          dahdi_close_pri_fd(pri, i);
14067          return -1;
14068       }
14069       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14070    }
14071    return 0;
14072 }
14073 #endif   /* defined(HAVE_PRI) */
14074 
14075 #if defined(HAVE_PRI)
14076 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14077 {
14078    int which, span;
14079    char *ret = NULL;
14080 
14081    if (pos != rpos)
14082       return ret;
14083 
14084    for (which = span = 0; span < NUM_SPANS; span++) {
14085       if (pris[span].pri.pri && ++which > state) {
14086          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14087             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14088          }
14089          break;
14090       }
14091    }
14092    return ret;
14093 }
14094 #endif   /* defined(HAVE_PRI) */
14095 
14096 #if defined(HAVE_PRI)
14097 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14098 {
14099    return complete_span_helper(line,word,pos,state,3);
14100 }
14101 #endif   /* defined(HAVE_PRI) */
14102 
14103 #if defined(HAVE_PRI)
14104 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14105 {
14106    int myfd;
14107    switch (cmd) {
14108    case CLI_INIT:
14109       e->command = "pri set debug file";
14110       e->usage = "Usage: pri set debug file [output-file]\n"
14111          "       Sends PRI debug output to the specified output file\n";
14112       return NULL;
14113    case CLI_GENERATE:
14114       return NULL;
14115    }
14116    if (a->argc < 5)
14117       return CLI_SHOWUSAGE;
14118 
14119    if (ast_strlen_zero(a->argv[4]))
14120       return CLI_SHOWUSAGE;
14121 
14122    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14123    if (myfd < 0) {
14124       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14125       return CLI_SUCCESS;
14126    }
14127 
14128    ast_mutex_lock(&pridebugfdlock);
14129 
14130    if (pridebugfd >= 0)
14131       close(pridebugfd);
14132 
14133    pridebugfd = myfd;
14134    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14135    ast_mutex_unlock(&pridebugfdlock);
14136    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14137    return CLI_SUCCESS;
14138 }
14139 #endif   /* defined(HAVE_PRI) */
14140 
14141 #if defined(HAVE_PRI)
14142 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14143 {
14144    int span;
14145    int x;
14146    int level = 0;
14147    switch (cmd) {
14148    case CLI_INIT:
14149       e->command = "pri set debug {on|off|0|1|2} span";
14150       e->usage =
14151          "Usage: pri set debug {<level>|on|off} span <span>\n"
14152          "       Enables debugging on a given PRI span\n";
14153       return NULL;
14154    case CLI_GENERATE:
14155       return complete_span_4(a->line, a->word, a->pos, a->n);
14156    }
14157    if (a->argc < 6) {
14158       return CLI_SHOWUSAGE;
14159    }
14160 
14161    if (!strcasecmp(a->argv[3], "on")) {
14162       level = 1;
14163    } else if (!strcasecmp(a->argv[3], "off")) {
14164       level = 0;
14165    } else {
14166       level = atoi(a->argv[3]);
14167    }
14168    span = atoi(a->argv[5]);
14169    if ((span < 1) || (span > NUM_SPANS)) {
14170       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14171       return CLI_SUCCESS;
14172    }
14173    if (!pris[span-1].pri.pri) {
14174       ast_cli(a->fd, "No PRI running on span %d\n", span);
14175       return CLI_SUCCESS;
14176    }
14177 
14178    /* Set debug level in libpri */
14179    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14180       if (pris[span - 1].pri.dchans[x]) {
14181          switch (level) {
14182          case 0:
14183             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14184             break;
14185          case 1:
14186             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14187             break;
14188          default:
14189             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14190             break;
14191          }
14192       }
14193    }
14194    if (level == 0) {
14195       /* Close the debugging file if it's set */
14196       ast_mutex_lock(&pridebugfdlock);
14197       if (0 <= pridebugfd) {
14198          close(pridebugfd);
14199          pridebugfd = -1;
14200          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14201             pridebugfilename);
14202       }
14203       ast_mutex_unlock(&pridebugfdlock);
14204    }
14205    pris[span - 1].pri.debug = (level) ? 1 : 0;
14206    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14207    return CLI_SUCCESS;
14208 }
14209 #endif   /* defined(HAVE_PRI) */
14210 
14211 #if defined(HAVE_PRI)
14212 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14213 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14214 {
14215    unsigned *why;
14216    int channel;
14217    int trunkgroup;
14218    int x, y, fd = a->fd;
14219    int interfaceid = 0;
14220    char *c;
14221    char db_chan_name[20], db_answer[5];
14222    struct dahdi_pvt *tmp;
14223    struct dahdi_pri *pri;
14224 
14225    if (a->argc < 5 || a->argc > 6)
14226       return CLI_SHOWUSAGE;
14227    if ((c = strchr(a->argv[4], ':'))) {
14228       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14229          return CLI_SHOWUSAGE;
14230       if ((trunkgroup < 1) || (channel < 1))
14231          return CLI_SHOWUSAGE;
14232       pri = NULL;
14233       for (x=0;x<NUM_SPANS;x++) {
14234          if (pris[x].pri.trunkgroup == trunkgroup) {
14235             pri = pris + x;
14236             break;
14237          }
14238       }
14239       if (!pri) {
14240          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14241          return CLI_FAILURE;
14242       }
14243    } else
14244       channel = atoi(a->argv[4]);
14245 
14246    if (a->argc == 6)
14247       interfaceid = atoi(a->argv[5]);
14248 
14249    /* either servicing a D-Channel */
14250    for (x = 0; x < NUM_SPANS; x++) {
14251       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14252          if (pris[x].dchannels[y] == channel) {
14253             pri = pris + x;
14254             if (pri->pri.enable_service_message_support) {
14255                ast_mutex_lock(&pri->pri.lock);
14256                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14257                ast_mutex_unlock(&pri->pri.lock);
14258             } else {
14259                ast_cli(fd,
14260                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14261                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14262             }
14263             return CLI_SUCCESS;
14264          }
14265       }
14266    }
14267 
14268    /* or servicing a B-Channel */
14269    ast_mutex_lock(&iflock);
14270    for (tmp = iflist; tmp; tmp = tmp->next) {
14271       if (tmp->pri && tmp->channel == channel) {
14272          ast_mutex_unlock(&iflock);
14273          ast_mutex_lock(&tmp->pri->lock);
14274          if (!tmp->pri->enable_service_message_support) {
14275             ast_mutex_unlock(&tmp->pri->lock);
14276             ast_cli(fd,
14277                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14278                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14279             return CLI_SUCCESS;
14280          }
14281          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14282          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14283          switch(changestatus) {
14284          case 0: /* enable */
14285             /* Near end wants to be in service now. */
14286             ast_db_del(db_chan_name, SRVST_DBKEY);
14287             *why &= ~SRVST_NEAREND;
14288             if (*why) {
14289                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14290                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14291             } else {
14292                dahdi_pri_update_span_devstate(tmp->pri);
14293             }
14294             break;
14295          /* case 1:  -- loop */
14296          case 2: /* disable */
14297             /* Near end wants to be out-of-service now. */
14298             ast_db_del(db_chan_name, SRVST_DBKEY);
14299             *why |= SRVST_NEAREND;
14300             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14301             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14302             dahdi_pri_update_span_devstate(tmp->pri);
14303             break;
14304          /* case 3:  -- continuity */
14305          /* case 4:  -- shutdown */
14306          default:
14307             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14308             break;
14309          }
14310          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14311          ast_mutex_unlock(&tmp->pri->lock);
14312          return CLI_SUCCESS;
14313       }
14314    }
14315    ast_mutex_unlock(&iflock);
14316 
14317    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14318    return CLI_FAILURE;
14319 }
14320 
14321 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14322 {
14323    switch (cmd) {
14324    case CLI_INIT:
14325       e->command = "pri service enable channel";
14326       e->usage =
14327          "Usage: pri service enable channel <channel> [<interface id>]\n"
14328          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14329          "  to restore a channel to service, with optional interface id\n"
14330          "  as agreed upon with remote switch operator\n";
14331       return NULL;
14332    case CLI_GENERATE:
14333       return NULL;
14334    }
14335    return handle_pri_service_generic(e, cmd, a, 0);
14336 }
14337 
14338 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14339 {
14340    switch (cmd) {
14341    case CLI_INIT:
14342       e->command = "pri service disable channel";
14343       e->usage =
14344          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14345          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14346          "  to remove a channel from service, with optional interface id\n"
14347          "  as agreed upon with remote switch operator\n";
14348       return NULL;
14349    case CLI_GENERATE:
14350       return NULL;
14351    }
14352    return handle_pri_service_generic(e, cmd, a, 2);
14353 }
14354 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14355 #endif   /* defined(HAVE_PRI) */
14356 
14357 #if defined(HAVE_PRI)
14358 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14359 {
14360    int span;
14361 
14362    switch (cmd) {
14363    case CLI_INIT:
14364       e->command = "pri show channels";
14365       e->usage =
14366          "Usage: pri show channels\n"
14367          "       Displays PRI channel information such as the current mapping\n"
14368          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14369          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14370          "       are not associated with any B channel.\n";
14371       return NULL;
14372    case CLI_GENERATE:
14373       return NULL;
14374    }
14375 
14376    if (a->argc != 3)
14377       return CLI_SHOWUSAGE;
14378 
14379    sig_pri_cli_show_channels_header(a->fd);
14380    for (span = 0; span < NUM_SPANS; ++span) {
14381       if (pris[span].pri.pri) {
14382          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14383       }
14384    }
14385    return CLI_SUCCESS;
14386 }
14387 #endif   /* defined(HAVE_PRI) */
14388 
14389 #if defined(HAVE_PRI)
14390 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14391 {
14392    int span;
14393 
14394    switch (cmd) {
14395    case CLI_INIT:
14396       e->command = "pri show spans";
14397       e->usage =
14398          "Usage: pri show spans\n"
14399          "       Displays PRI span information\n";
14400       return NULL;
14401    case CLI_GENERATE:
14402       return NULL;
14403    }
14404 
14405    if (a->argc != 3)
14406       return CLI_SHOWUSAGE;
14407 
14408    for (span = 0; span < NUM_SPANS; span++) {
14409       if (pris[span].pri.pri) {
14410          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14411       }
14412    }
14413    return CLI_SUCCESS;
14414 }
14415 #endif   /* defined(HAVE_PRI) */
14416 
14417 #if defined(HAVE_PRI)
14418 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14419 {
14420    int span;
14421 
14422    switch (cmd) {
14423    case CLI_INIT:
14424       e->command = "pri show span";
14425       e->usage =
14426          "Usage: pri show span <span>\n"
14427          "       Displays PRI Information on a given PRI span\n";
14428       return NULL;
14429    case CLI_GENERATE:
14430       return complete_span_4(a->line, a->word, a->pos, a->n);
14431    }
14432 
14433    if (a->argc < 4)
14434       return CLI_SHOWUSAGE;
14435    span = atoi(a->argv[3]);
14436    if ((span < 1) || (span > NUM_SPANS)) {
14437       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14438       return CLI_SUCCESS;
14439    }
14440    if (!pris[span-1].pri.pri) {
14441       ast_cli(a->fd, "No PRI running on span %d\n", span);
14442       return CLI_SUCCESS;
14443    }
14444 
14445    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14446 
14447    return CLI_SUCCESS;
14448 }
14449 #endif   /* defined(HAVE_PRI) */
14450 
14451 #if defined(HAVE_PRI)
14452 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14453 {
14454    int x;
14455    int span;
14456    int count=0;
14457    int debug;
14458 
14459    switch (cmd) {
14460    case CLI_INIT:
14461       e->command = "pri show debug";
14462       e->usage =
14463          "Usage: pri show debug\n"
14464          "  Show the debug state of pri spans\n";
14465       return NULL;
14466    case CLI_GENERATE:
14467       return NULL;
14468    }
14469 
14470    for (span = 0; span < NUM_SPANS; span++) {
14471       if (pris[span].pri.pri) {
14472          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14473             if (pris[span].pri.dchans[x]) {
14474                debug = pri_get_debug(pris[span].pri.dchans[x]);
14475                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" );
14476                count++;
14477             }
14478          }
14479       }
14480 
14481    }
14482    ast_mutex_lock(&pridebugfdlock);
14483    if (pridebugfd >= 0)
14484       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14485    ast_mutex_unlock(&pridebugfdlock);
14486 
14487    if (!count)
14488       ast_cli(a->fd, "No PRI running\n");
14489    return CLI_SUCCESS;
14490 }
14491 #endif   /* defined(HAVE_PRI) */
14492 
14493 #if defined(HAVE_PRI)
14494 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14495 {
14496    switch (cmd) {
14497    case CLI_INIT:
14498       e->command = "pri show version";
14499       e->usage =
14500          "Usage: pri show version\n"
14501          "Show libpri version information\n";
14502       return NULL;
14503    case CLI_GENERATE:
14504       return NULL;
14505    }
14506 
14507    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14508 
14509    return CLI_SUCCESS;
14510 }
14511 #endif   /* defined(HAVE_PRI) */
14512 
14513 #if defined(HAVE_PRI)
14514 static struct ast_cli_entry dahdi_pri_cli[] = {
14515    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14516 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14517    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14518    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14519 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14520    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14521    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14522    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14523    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14524    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14525    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14526 };
14527 #endif   /* defined(HAVE_PRI) */
14528 
14529 #ifdef HAVE_OPENR2
14530 
14531 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14532 {
14533    switch (cmd) {
14534    case CLI_INIT:
14535       e->command = "mfcr2 show version";
14536       e->usage =
14537          "Usage: mfcr2 show version\n"
14538          "       Shows the version of the OpenR2 library being used.\n";
14539       return NULL;
14540    case CLI_GENERATE:
14541       return NULL;
14542    }
14543    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14544    return CLI_SUCCESS;
14545 }
14546 
14547 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549 #define FORMAT "%4s %40s\n"
14550    int i = 0;
14551    int numvariants = 0;
14552    const openr2_variant_entry_t *variants;
14553    switch (cmd) {
14554    case CLI_INIT:
14555       e->command = "mfcr2 show variants";
14556       e->usage =
14557          "Usage: mfcr2 show variants\n"
14558          "       Shows the list of MFC/R2 variants supported.\n";
14559       return NULL;
14560    case CLI_GENERATE:
14561       return NULL;
14562    }
14563    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14564       ast_cli(a->fd, "Failed to get list of variants.\n");
14565       return CLI_FAILURE;
14566    }
14567    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14568    for (i = 0; i < numvariants; i++) {
14569       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14570    }
14571    return CLI_SUCCESS;
14572 #undef FORMAT
14573 }
14574 
14575 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14576 {
14577 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14578    int filtertype = 0;
14579    int targetnum = 0;
14580    char channo[5];
14581    char anino[5];
14582    char dnisno[5];
14583    struct dahdi_pvt *p;
14584    openr2_context_t *r2context;
14585    openr2_variant_t r2variant;
14586    switch (cmd) {
14587    case CLI_INIT:
14588       e->command = "mfcr2 show channels [group|context]";
14589       e->usage =
14590          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14591          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14592       return NULL;
14593    case CLI_GENERATE:
14594       return NULL;
14595    }
14596    if (!((a->argc == 3) || (a->argc == 5))) {
14597       return CLI_SHOWUSAGE;
14598    }
14599    if (a->argc == 5) {
14600       if (!strcasecmp(a->argv[3], "group")) {
14601          targetnum = atoi(a->argv[4]);
14602          if ((targetnum < 0) || (targetnum > 63))
14603             return CLI_SHOWUSAGE;
14604          targetnum = 1 << targetnum;
14605          filtertype = 1;
14606       } else if (!strcasecmp(a->argv[3], "context")) {
14607          filtertype = 2;
14608       } else {
14609          return CLI_SHOWUSAGE;
14610       }
14611    }
14612    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14613    ast_mutex_lock(&iflock);
14614    for (p = iflist; p; p = p->next) {
14615       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14616          continue;
14617       }
14618       if (filtertype) {
14619          switch(filtertype) {
14620          case 1: /* mfcr2 show channels group <group> */
14621             if (p->group != targetnum) {
14622                continue;
14623             }
14624             break;
14625          case 2: /* mfcr2 show channels context <context> */
14626             if (strcasecmp(p->context, a->argv[4])) {
14627                continue;
14628             }
14629             break;
14630          default:
14631             ;
14632          }
14633       }
14634       r2context = openr2_chan_get_context(p->r2chan);
14635       r2variant = openr2_context_get_variant(r2context);
14636       snprintf(channo, sizeof(channo), "%d", p->channel);
14637       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14638       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14639       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14640             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14641             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14642             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14643    }
14644    ast_mutex_unlock(&iflock);
14645    return CLI_SUCCESS;
14646 #undef FORMAT
14647 }
14648 
14649 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14650 {
14651    struct dahdi_pvt *p = NULL;
14652    int channo = 0;
14653    char *toklevel = NULL;
14654    char *saveptr = NULL;
14655    char *logval = NULL;
14656    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14657    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14658    switch (cmd) {
14659    case CLI_INIT:
14660       e->command = "mfcr2 set debug";
14661       e->usage =
14662          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14663          "       Set a new logging level for the specified channel.\n"
14664          "       If no channel is specified the logging level will be applied to all channels.\n";
14665       return NULL;
14666    case CLI_GENERATE:
14667       return NULL;
14668    }
14669    if (a->argc < 4) {
14670       return CLI_SHOWUSAGE;
14671    }
14672    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14673    logval = ast_strdupa(a->argv[3]);
14674    toklevel = strtok_r(logval, ",", &saveptr);
14675    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14676       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14677       return CLI_FAILURE;
14678    } else if (OR2_LOG_NOTHING == tmplevel) {
14679       loglevel = tmplevel;
14680    } else {
14681       loglevel |= tmplevel;
14682       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14683          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14684             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14685             continue;
14686          }
14687          loglevel |= tmplevel;
14688       }
14689    }
14690    ast_mutex_lock(&iflock);
14691    for (p = iflist; p; p = p->next) {
14692       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14693          continue;
14694       }
14695       if ((channo != -1) && (p->channel != channo )) {
14696          continue;
14697       }
14698       openr2_chan_set_log_level(p->r2chan, loglevel);
14699       if (channo != -1) {
14700          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14701          break;
14702       }
14703    }
14704    if ((channo != -1) && !p) {
14705       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14706    }
14707    if (channo == -1) {
14708       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14709    }
14710    ast_mutex_unlock(&iflock);
14711    return CLI_SUCCESS;
14712 }
14713 
14714 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14715 {
14716    struct dahdi_pvt *p = NULL;
14717    int channo = 0;
14718    switch (cmd) {
14719    case CLI_INIT:
14720       e->command = "mfcr2 call files [on|off]";
14721       e->usage =
14722          "Usage: mfcr2 call files [on|off] <channel>\n"
14723          "       Enable call files creation on the specified channel.\n"
14724          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14725       return NULL;
14726    case CLI_GENERATE:
14727       return NULL;
14728    }
14729    if (a->argc < 4) {
14730       return CLI_SHOWUSAGE;
14731    }
14732    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14733    ast_mutex_lock(&iflock);
14734    for (p = iflist; p; p = p->next) {
14735       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14736          continue;
14737       }
14738       if ((channo != -1) && (p->channel != channo )) {
14739          continue;
14740       }
14741       if (ast_true(a->argv[3])) {
14742          openr2_chan_enable_call_files(p->r2chan);
14743       } else {
14744          openr2_chan_disable_call_files(p->r2chan);
14745       }
14746       if (channo != -1) {
14747          if (ast_true(a->argv[3])) {
14748             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14749          } else {
14750             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14751          }
14752          break;
14753       }
14754    }
14755    if ((channo != -1) && !p) {
14756       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14757    }
14758    if (channo == -1) {
14759       if (ast_true(a->argv[3])) {
14760          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14761       } else {
14762          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14763       }
14764    }
14765    ast_mutex_unlock(&iflock);
14766    return CLI_SUCCESS;
14767 }
14768 
14769 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14770 {
14771    struct dahdi_pvt *p = NULL;
14772    int channo = 0;
14773    switch (cmd) {
14774    case CLI_INIT:
14775       e->command = "mfcr2 set idle";
14776       e->usage =
14777          "Usage: mfcr2 set idle <channel>\n"
14778          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14779          "       Force the given channel into IDLE state.\n"
14780          "       If no channel is specified, all channels will be set to IDLE.\n";
14781       return NULL;
14782    case CLI_GENERATE:
14783       return NULL;
14784    }
14785    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14786    ast_mutex_lock(&iflock);
14787    for (p = iflist; p; p = p->next) {
14788       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14789          continue;
14790       }
14791       if ((channo != -1) && (p->channel != channo )) {
14792          continue;
14793       }
14794       openr2_chan_set_idle(p->r2chan);
14795       ast_mutex_lock(&p->lock);
14796       p->locallyblocked = 0;
14797       p->mfcr2call = 0;
14798       ast_mutex_unlock(&p->lock);
14799       if (channo != -1) {
14800          break;
14801       }
14802    }
14803    if ((channo != -1) && !p) {
14804       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14805    }
14806    ast_mutex_unlock(&iflock);
14807    return CLI_SUCCESS;
14808 }
14809 
14810 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14811 {
14812    struct dahdi_pvt *p = NULL;
14813    int channo = 0;
14814    switch (cmd) {
14815    case CLI_INIT:
14816       e->command = "mfcr2 set blocked";
14817       e->usage =
14818          "Usage: mfcr2 set blocked <channel>\n"
14819          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14820          "       Force the given channel into BLOCKED state.\n"
14821          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14822       return NULL;
14823    case CLI_GENERATE:
14824       return NULL;
14825    }
14826    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14827    ast_mutex_lock(&iflock);
14828    for (p = iflist; p; p = p->next) {
14829       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14830          continue;
14831       }
14832       if ((channo != -1) && (p->channel != channo )) {
14833          continue;
14834       }
14835       openr2_chan_set_blocked(p->r2chan);
14836       ast_mutex_lock(&p->lock);
14837       p->locallyblocked = 1;
14838       ast_mutex_unlock(&p->lock);
14839       if (channo != -1) {
14840          break;
14841       }
14842    }
14843    if ((channo != -1) && !p) {
14844       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14845    }
14846    ast_mutex_unlock(&iflock);
14847    return CLI_SUCCESS;
14848 }
14849 
14850 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14851    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14852    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14853    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14854    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14855    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14856    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14857    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14858 };
14859 
14860 #endif /* HAVE_OPENR2 */
14861 
14862 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14863 {
14864    int channel;
14865    int ret;
14866    switch (cmd) {
14867    case CLI_INIT:
14868       e->command = "dahdi destroy channel";
14869       e->usage =
14870          "Usage: dahdi destroy channel <chan num>\n"
14871          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14872       return NULL;
14873    case CLI_GENERATE:
14874       return NULL;
14875    }
14876    if (a->argc != 4)
14877       return CLI_SHOWUSAGE;
14878 
14879    channel = atoi(a->argv[3]);
14880    ret = dahdi_destroy_channel_bynum(channel);
14881    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14882 }
14883 
14884 static void dahdi_softhangup_all(void)
14885 {
14886    struct dahdi_pvt *p;
14887 retry:
14888    ast_mutex_lock(&iflock);
14889    for (p = iflist; p; p = p->next) {
14890       ast_mutex_lock(&p->lock);
14891       if (p->owner && !p->restartpending) {
14892          if (ast_channel_trylock(p->owner)) {
14893             if (option_debug > 2)
14894                ast_verbose("Avoiding deadlock\n");
14895             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14896             ast_mutex_unlock(&p->lock);
14897             ast_mutex_unlock(&iflock);
14898             goto retry;
14899          }
14900          if (option_debug > 2)
14901             ast_verbose("Softhanging up on %s\n", p->owner->name);
14902          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14903          p->restartpending = 1;
14904          num_restart_pending++;
14905          ast_channel_unlock(p->owner);
14906       }
14907       ast_mutex_unlock(&p->lock);
14908    }
14909    ast_mutex_unlock(&iflock);
14910 }
14911 
14912 static int setup_dahdi(int reload);
14913 static int dahdi_restart(void)
14914 {
14915 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14916    int i, j;
14917 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14918    int cancel_code;
14919    struct dahdi_pvt *p;
14920 
14921    ast_mutex_lock(&restart_lock);
14922    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14923    dahdi_softhangup_all();
14924    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14925 #ifdef HAVE_OPENR2
14926    dahdi_r2_destroy_links();
14927 #endif
14928 
14929 #if defined(HAVE_PRI)
14930    for (i = 0; i < NUM_SPANS; i++) {
14931       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14932          cancel_code = pthread_cancel(pris[i].pri.master);
14933          pthread_kill(pris[i].pri.master, SIGURG);
14934          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);
14935          pthread_join(pris[i].pri.master, NULL);
14936          ast_debug(4, "Joined thread of span %d\n", i);
14937       }
14938    }
14939 #endif
14940 
14941 #if defined(HAVE_SS7)
14942    for (i = 0; i < NUM_SPANS; i++) {
14943       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14944          cancel_code = pthread_cancel(linksets[i].ss7.master);
14945          pthread_kill(linksets[i].ss7.master, SIGURG);
14946          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);
14947          pthread_join(linksets[i].ss7.master, NULL);
14948          ast_debug(4, "Joined thread of span %d\n", i);
14949       }
14950    }
14951 #endif   /* defined(HAVE_SS7) */
14952 
14953    ast_mutex_lock(&monlock);
14954    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14955       cancel_code = pthread_cancel(monitor_thread);
14956       pthread_kill(monitor_thread, SIGURG);
14957       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14958       pthread_join(monitor_thread, NULL);
14959       ast_debug(4, "Joined monitor thread\n");
14960    }
14961    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14962 
14963    ast_mutex_lock(&ss_thread_lock);
14964    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14965       int x = DAHDI_FLASH;
14966       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14967 
14968       ast_mutex_lock(&iflock);
14969       for (p = iflist; p; p = p->next) {
14970          if (p->owner) {
14971             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
14972             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14973          }
14974       }
14975       ast_mutex_unlock(&iflock);
14976       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14977    }
14978 
14979    /* ensure any created channels before monitor threads were stopped are hungup */
14980    dahdi_softhangup_all();
14981    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14982    destroy_all_channels();
14983    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14984 
14985    ast_mutex_unlock(&monlock);
14986 
14987 #ifdef HAVE_PRI
14988    for (i = 0; i < NUM_SPANS; i++) {
14989       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14990          dahdi_close_pri_fd(&(pris[i]), j);
14991    }
14992 
14993    memset(pris, 0, sizeof(pris));
14994    for (i = 0; i < NUM_SPANS; i++) {
14995       sig_pri_init_pri(&pris[i].pri);
14996    }
14997    pri_set_error(dahdi_pri_error);
14998    pri_set_message(dahdi_pri_message);
14999 #endif
15000 #if defined(HAVE_SS7)
15001    for (i = 0; i < NUM_SPANS; i++) {
15002       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15003          dahdi_close_ss7_fd(&(linksets[i]), j);
15004    }
15005 
15006    memset(linksets, 0, sizeof(linksets));
15007    for (i = 0; i < NUM_SPANS; i++) {
15008       sig_ss7_init_linkset(&linksets[i].ss7);
15009    }
15010    ss7_set_error(dahdi_ss7_error);
15011    ss7_set_message(dahdi_ss7_message);
15012 #endif   /* defined(HAVE_SS7) */
15013 
15014    if (setup_dahdi(2) != 0) {
15015       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15016       ast_mutex_unlock(&ss_thread_lock);
15017       return 1;
15018    }
15019    ast_mutex_unlock(&ss_thread_lock);
15020    ast_mutex_unlock(&restart_lock);
15021    return 0;
15022 }
15023 
15024 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15025 {
15026    switch (cmd) {
15027    case CLI_INIT:
15028       e->command = "dahdi restart";
15029       e->usage =
15030          "Usage: dahdi restart\n"
15031          "  Restarts the DAHDI channels: destroys them all and then\n"
15032          "  re-reads them from chan_dahdi.conf.\n"
15033          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15034          "";
15035       return NULL;
15036    case CLI_GENERATE:
15037       return NULL;
15038    }
15039    if (a->argc != 2)
15040       return CLI_SHOWUSAGE;
15041 
15042    if (dahdi_restart() != 0)
15043       return CLI_FAILURE;
15044    return CLI_SUCCESS;
15045 }
15046 
15047 static int action_dahdirestart(struct mansession *s, const struct message *m)
15048 {
15049    if (dahdi_restart() != 0) {
15050       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15051       return 1;
15052    }
15053    astman_send_ack(s, m, "DAHDIRestart: Success");
15054    return 0;
15055 }
15056 
15057 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15058 {
15059 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15060 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15061    unsigned int targetnum = 0;
15062    int filtertype = 0;
15063    struct dahdi_pvt *tmp = NULL;
15064    char tmps[20] = "";
15065    char statestr[20] = "";
15066    char blockstr[20] = "";
15067 
15068    switch (cmd) {
15069    case CLI_INIT:
15070       e->command = "dahdi show channels [group|context]";
15071       e->usage =
15072          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15073          "  Shows a list of available channels with optional filtering\n"
15074          "  <group> must be a number between 0 and 63\n";
15075       return NULL;
15076    case CLI_GENERATE:
15077       return NULL;
15078    }
15079 
15080    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15081 
15082    if (!((a->argc == 3) || (a->argc == 5)))
15083       return CLI_SHOWUSAGE;
15084 
15085    if (a->argc == 5) {
15086       if (!strcasecmp(a->argv[3], "group")) {
15087          targetnum = atoi(a->argv[4]);
15088          if ((targetnum < 0) || (targetnum > 63))
15089             return CLI_SHOWUSAGE;
15090          targetnum = 1 << targetnum;
15091          filtertype = 1;
15092       } else if (!strcasecmp(a->argv[3], "context")) {
15093          filtertype = 2;
15094       }
15095    }
15096 
15097    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15098    ast_mutex_lock(&iflock);
15099    for (tmp = iflist; tmp; tmp = tmp->next) {
15100       if (filtertype) {
15101          switch(filtertype) {
15102          case 1: /* dahdi show channels group <group> */
15103             if (!(tmp->group & targetnum)) {
15104                continue;
15105             }
15106             break;
15107          case 2: /* dahdi show channels context <context> */
15108             if (strcasecmp(tmp->context, a->argv[4])) {
15109                continue;
15110             }
15111             break;
15112          default:
15113             break;
15114          }
15115       }
15116       if (tmp->channel > 0) {
15117          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15118       } else
15119          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15120 
15121       if (tmp->locallyblocked)
15122          blockstr[0] = 'L';
15123       else
15124          blockstr[0] = ' ';
15125 
15126       if (tmp->remotelyblocked)
15127          blockstr[1] = 'R';
15128       else
15129          blockstr[1] = ' ';
15130 
15131       blockstr[2] = '\0';
15132 
15133       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15134 
15135       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15136    }
15137    ast_mutex_unlock(&iflock);
15138    return CLI_SUCCESS;
15139 #undef FORMAT
15140 #undef FORMAT2
15141 }
15142 
15143 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15144 {
15145    int channel;
15146    struct dahdi_pvt *tmp = NULL;
15147    struct dahdi_confinfo ci;
15148    struct dahdi_params ps;
15149    int x;
15150 
15151    switch (cmd) {
15152    case CLI_INIT:
15153       e->command = "dahdi show channel";
15154       e->usage =
15155          "Usage: dahdi show channel <chan num>\n"
15156          "  Detailed information about a given channel\n";
15157       return NULL;
15158    case CLI_GENERATE:
15159       return NULL;
15160    }
15161 
15162    if (a->argc != 4)
15163       return CLI_SHOWUSAGE;
15164 
15165    channel = atoi(a->argv[3]);
15166 
15167    ast_mutex_lock(&iflock);
15168    for (tmp = iflist; tmp; tmp = tmp->next) {
15169       if (tmp->channel == channel) {
15170          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15171          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15172          ast_cli(a->fd, "Span: %d\n", tmp->span);
15173          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15174          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15175          ast_cli(a->fd, "Context: %s\n", tmp->context);
15176          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15177          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15178 #if defined(HAVE_PRI)
15179 #if defined(HAVE_PRI_SUBADDR)
15180          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15181 #endif   /* defined(HAVE_PRI_SUBADDR) */
15182 #endif   /* defined(HAVE_PRI) */
15183          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15184          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15185          if (tmp->vars) {
15186             struct ast_variable *v;
15187             ast_cli(a->fd, "Variables:\n");
15188             for (v = tmp->vars ; v ; v = v->next)
15189                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15190          }
15191          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15192          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15193          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15194          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15195          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15196          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)" : "");
15197          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)" : "");
15198          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)" : "");
15199          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15200          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15201          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15202          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15203          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15204          if (tmp->busydetect) {
15205 #if defined(BUSYDETECT_TONEONLY)
15206             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15207 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15208             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15209 #endif
15210 #ifdef BUSYDETECT_DEBUG
15211             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15212 #endif
15213             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15214             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15215          }
15216          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15217          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15218          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15219          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15220          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15221          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15222          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15223          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15224          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15225          ast_cli(a->fd, "Echo Cancellation:\n");
15226 
15227          if (tmp->echocancel.head.tap_length) {
15228             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15229             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15230                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15231             }
15232             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15233          } else {
15234             ast_cli(a->fd, "\tnone\n");
15235          }
15236          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15237          if (tmp->master)
15238             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15239          for (x = 0; x < MAX_SLAVES; x++) {
15240             if (tmp->slaves[x])
15241                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15242          }
15243 #ifdef HAVE_OPENR2
15244          if (tmp->mfcr2) {
15245             char calldir[OR2_MAX_PATH];
15246             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15247             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15248             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15249             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15250             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15251             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15252             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15253             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15254             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15255             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15256             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15257 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15258             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15259 #endif
15260             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15261             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15262             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15263             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15264             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15265             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15266             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15267             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15268             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15269             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15270             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15271             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15272          }
15273 #endif
15274 #if defined(HAVE_SS7)
15275          if (tmp->ss7) {
15276             struct sig_ss7_chan *chan = tmp->sig_pvt;
15277 
15278             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15279          }
15280 #endif   /* defined(HAVE_SS7) */
15281 #ifdef HAVE_PRI
15282          if (tmp->pri) {
15283             struct sig_pri_chan *chan = tmp->sig_pvt;
15284 
15285             ast_cli(a->fd, "PRI Flags: ");
15286             if (chan->resetting)
15287                ast_cli(a->fd, "Resetting ");
15288             if (chan->call)
15289                ast_cli(a->fd, "Call ");
15290             if (chan->allocated) {
15291                ast_cli(a->fd, "Allocated ");
15292             }
15293             ast_cli(a->fd, "\n");
15294             if (tmp->logicalspan)
15295                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15296             else
15297                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15298          }
15299 #endif
15300          memset(&ci, 0, sizeof(ci));
15301          ps.channo = tmp->channel;
15302          if (tmp->subs[SUB_REAL].dfd > -1) {
15303             memset(&ci, 0, sizeof(ci));
15304             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15305                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15306             }
15307             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15308                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15309             }
15310             memset(&ps, 0, sizeof(ps));
15311             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15312                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15313             } else {
15314                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15315             }
15316          }
15317          ast_mutex_unlock(&iflock);
15318          return CLI_SUCCESS;
15319       }
15320    }
15321    ast_mutex_unlock(&iflock);
15322 
15323    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15324    return CLI_FAILURE;
15325 }
15326 
15327 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15328 {
15329    int i, j;
15330    switch (cmd) {
15331    case CLI_INIT:
15332       e->command = "dahdi show cadences";
15333       e->usage =
15334          "Usage: dahdi show cadences\n"
15335          "       Shows all cadences currently defined\n";
15336       return NULL;
15337    case CLI_GENERATE:
15338       return NULL;
15339    }
15340    for (i = 0; i < num_cadence; i++) {
15341       char output[1024];
15342       char tmp[16], tmp2[64];
15343       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15344       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15345 
15346       for (j = 0; j < 16; j++) {
15347          if (cadences[i].ringcadence[j] == 0)
15348             break;
15349          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15350          if (cidrings[i] * 2 - 1 == j)
15351             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15352          else
15353             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15354          if (j != 0)
15355             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15356          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15357       }
15358       ast_cli(a->fd,"%s\n",output);
15359    }
15360    return CLI_SUCCESS;
15361 }
15362 
15363 /* Based on irqmiss.c */
15364 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15365 {
15366    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15367    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15368    int span;
15369    int res;
15370    char alarmstr[50];
15371 
15372    int ctl;
15373    struct dahdi_spaninfo s;
15374 
15375    switch (cmd) {
15376    case CLI_INIT:
15377       e->command = "dahdi show status";
15378       e->usage =
15379          "Usage: dahdi show status\n"
15380          "       Shows a list of DAHDI cards with status\n";
15381       return NULL;
15382    case CLI_GENERATE:
15383       return NULL;
15384    }
15385    ctl = open("/dev/dahdi/ctl", O_RDWR);
15386    if (ctl < 0) {
15387       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15388       return CLI_FAILURE;
15389    }
15390    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15391 
15392    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15393       s.spanno = span;
15394       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15395       if (res) {
15396          continue;
15397       }
15398       alarmstr[0] = '\0';
15399       if (s.alarms > 0) {
15400          if (s.alarms & DAHDI_ALARM_BLUE)
15401             strcat(alarmstr, "BLU/");
15402          if (s.alarms & DAHDI_ALARM_YELLOW)
15403             strcat(alarmstr, "YEL/");
15404          if (s.alarms & DAHDI_ALARM_RED)
15405             strcat(alarmstr, "RED/");
15406          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15407             strcat(alarmstr, "LB/");
15408          if (s.alarms & DAHDI_ALARM_RECOVER)
15409             strcat(alarmstr, "REC/");
15410          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15411             strcat(alarmstr, "NOP/");
15412          if (!strlen(alarmstr))
15413             strcat(alarmstr, "UUU/");
15414          if (strlen(alarmstr)) {
15415             /* Strip trailing / */
15416             alarmstr[strlen(alarmstr) - 1] = '\0';
15417          }
15418       } else {
15419          if (s.numchans)
15420             strcpy(alarmstr, "OK");
15421          else
15422             strcpy(alarmstr, "UNCONFIGURED");
15423       }
15424 
15425       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15426          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15427          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15428          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15429          "CAS",
15430          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15431          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15432          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15433          "Unk",
15434          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15435             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15436             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15437          lbostr[s.lbo]
15438          );
15439    }
15440    close(ctl);
15441 
15442    return CLI_SUCCESS;
15443 #undef FORMAT
15444 #undef FORMAT2
15445 }
15446 
15447 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15448 {
15449    int pseudo_fd = -1;
15450    struct dahdi_versioninfo vi;
15451 
15452    switch (cmd) {
15453    case CLI_INIT:
15454       e->command = "dahdi show version";
15455       e->usage =
15456          "Usage: dahdi show version\n"
15457          "       Shows the DAHDI version in use\n";
15458       return NULL;
15459    case CLI_GENERATE:
15460       return NULL;
15461    }
15462    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15463       ast_cli(a->fd, "Failed to open control file to get version.\n");
15464       return CLI_SUCCESS;
15465    }
15466 
15467    strcpy(vi.version, "Unknown");
15468    strcpy(vi.echo_canceller, "Unknown");
15469 
15470    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15471       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15472    else
15473       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15474 
15475    close(pseudo_fd);
15476 
15477    return CLI_SUCCESS;
15478 }
15479 
15480 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15481 {
15482    int channel;
15483    int gain;
15484    int tx;
15485    struct dahdi_hwgain hwgain;
15486    struct dahdi_pvt *tmp = NULL;
15487 
15488    switch (cmd) {
15489    case CLI_INIT:
15490       e->command = "dahdi set hwgain";
15491       e->usage =
15492          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15493          "  Sets the hardware gain on a a given channel, overriding the\n"
15494          "   value provided at module loadtime, whether the channel is in\n"
15495          "   use or not.  Changes take effect immediately.\n"
15496          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15497          "   <chan num> is the channel number relative to the device\n"
15498          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15499       return NULL;
15500    case CLI_GENERATE:
15501       return NULL;
15502    }
15503 
15504    if (a->argc != 6)
15505       return CLI_SHOWUSAGE;
15506 
15507    if (!strcasecmp("rx", a->argv[3]))
15508       tx = 0; /* rx */
15509    else if (!strcasecmp("tx", a->argv[3]))
15510       tx = 1; /* tx */
15511    else
15512       return CLI_SHOWUSAGE;
15513 
15514    channel = atoi(a->argv[4]);
15515    gain = atof(a->argv[5])*10.0;
15516 
15517    ast_mutex_lock(&iflock);
15518 
15519    for (tmp = iflist; tmp; tmp = tmp->next) {
15520 
15521       if (tmp->channel != channel)
15522          continue;
15523 
15524       if (tmp->subs[SUB_REAL].dfd == -1)
15525          break;
15526 
15527       hwgain.newgain = gain;
15528       hwgain.tx = tx;
15529       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15530          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15531          ast_mutex_unlock(&iflock);
15532          return CLI_FAILURE;
15533       }
15534       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15535          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15536       break;
15537    }
15538 
15539    ast_mutex_unlock(&iflock);
15540 
15541    if (tmp)
15542       return CLI_SUCCESS;
15543 
15544    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15545    return CLI_FAILURE;
15546 
15547 }
15548 
15549 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15550 {
15551    int channel;
15552    float gain;
15553    int tx;
15554    int res;
15555    struct dahdi_pvt *tmp = NULL;
15556 
15557    switch (cmd) {
15558    case CLI_INIT:
15559       e->command = "dahdi set swgain";
15560       e->usage =
15561          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15562          "  Sets the software gain on a a given channel, overriding the\n"
15563          "   value provided at module loadtime, whether the channel is in\n"
15564          "   use or not.  Changes take effect immediately.\n"
15565          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15566          "   <chan num> is the channel number relative to the device\n"
15567          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15568       return NULL;
15569    case CLI_GENERATE:
15570       return NULL;
15571    }
15572 
15573    if (a->argc != 6)
15574       return CLI_SHOWUSAGE;
15575 
15576    if (!strcasecmp("rx", a->argv[3]))
15577       tx = 0; /* rx */
15578    else if (!strcasecmp("tx", a->argv[3]))
15579       tx = 1; /* tx */
15580    else
15581       return CLI_SHOWUSAGE;
15582 
15583    channel = atoi(a->argv[4]);
15584    gain = atof(a->argv[5]);
15585 
15586    ast_mutex_lock(&iflock);
15587    for (tmp = iflist; tmp; tmp = tmp->next) {
15588 
15589       if (tmp->channel != channel)
15590          continue;
15591 
15592       if (tmp->subs[SUB_REAL].dfd == -1)
15593          break;
15594 
15595       if (tx)
15596          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15597       else
15598          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15599 
15600       if (res) {
15601          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15602          ast_mutex_unlock(&iflock);
15603          return CLI_FAILURE;
15604       }
15605 
15606       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15607          tx ? "tx" : "rx", gain, channel);
15608       break;
15609    }
15610    ast_mutex_unlock(&iflock);
15611 
15612    if (tmp)
15613       return CLI_SUCCESS;
15614 
15615    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15616    return CLI_FAILURE;
15617 
15618 }
15619 
15620 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15621 {
15622    int channel;
15623    int on;
15624    struct dahdi_pvt *dahdi_chan = NULL;
15625 
15626    switch (cmd) {
15627    case CLI_INIT:
15628       e->command = "dahdi set dnd";
15629       e->usage =
15630          "Usage: dahdi set dnd <chan#> <on|off>\n"
15631          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15632          "  Changes take effect immediately.\n"
15633          "  <chan num> is the channel number\n"
15634          "  <on|off> Enable or disable DND mode?\n"
15635          ;
15636       return NULL;
15637    case CLI_GENERATE:
15638       return NULL;
15639    }
15640 
15641    if (a->argc != 5)
15642       return CLI_SHOWUSAGE;
15643 
15644    if ((channel = atoi(a->argv[3])) <= 0) {
15645       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15646       return CLI_SHOWUSAGE;
15647    }
15648 
15649    if (ast_true(a->argv[4]))
15650       on = 1;
15651    else if (ast_false(a->argv[4]))
15652       on = 0;
15653    else {
15654       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15655       return CLI_SHOWUSAGE;
15656    }
15657 
15658    ast_mutex_lock(&iflock);
15659    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15660       if (dahdi_chan->channel != channel)
15661          continue;
15662 
15663       /* Found the channel. Actually set it */
15664       dahdi_dnd(dahdi_chan, on);
15665       break;
15666    }
15667    ast_mutex_unlock(&iflock);
15668 
15669    if (!dahdi_chan) {
15670       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15671       return CLI_FAILURE;
15672    }
15673 
15674    return CLI_SUCCESS;
15675 }
15676 
15677 static struct ast_cli_entry dahdi_cli[] = {
15678    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15679    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15680    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15681    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15682    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15683    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15684    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15685    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15686    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15687    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15688 };
15689 
15690 #define TRANSFER  0
15691 #define HANGUP    1
15692 
15693 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15694 {
15695    if (p) {
15696       switch (mode) {
15697       case TRANSFER:
15698          p->fake_event = DAHDI_EVENT_WINKFLASH;
15699          break;
15700       case HANGUP:
15701          p->fake_event = DAHDI_EVENT_ONHOOK;
15702          break;
15703       default:
15704          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15705       }
15706    }
15707    return 0;
15708 }
15709 static struct dahdi_pvt *find_channel(int channel)
15710 {
15711    struct dahdi_pvt *p;
15712 
15713    ast_mutex_lock(&iflock);
15714    for (p = iflist; p; p = p->next) {
15715       if (p->channel == channel) {
15716          break;
15717       }
15718    }
15719    ast_mutex_unlock(&iflock);
15720    return p;
15721 }
15722 
15723 /*!
15724  * \internal
15725  * \brief Get private struct using given numeric channel string.
15726  *
15727  * \param channel Numeric channel number string get private struct.
15728  *
15729  * \retval pvt on success.
15730  * \retval NULL on error.
15731  */
15732 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15733 {
15734    int chan_num;
15735 
15736    if (sscanf(channel, "%30d", &chan_num) != 1) {
15737       /* Not numeric string. */
15738       return NULL;
15739    }
15740 
15741    return find_channel(chan_num);
15742 }
15743 
15744 static int action_dahdidndon(struct mansession *s, const struct message *m)
15745 {
15746    struct dahdi_pvt *p;
15747    const char *channel = astman_get_header(m, "DAHDIChannel");
15748 
15749    if (ast_strlen_zero(channel)) {
15750       astman_send_error(s, m, "No channel specified");
15751       return 0;
15752    }
15753    p = find_channel_from_str(channel);
15754    if (!p) {
15755       astman_send_error(s, m, "No such channel");
15756       return 0;
15757    }
15758    dahdi_dnd(p, 1);
15759    astman_send_ack(s, m, "DND Enabled");
15760    return 0;
15761 }
15762 
15763 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15764 {
15765    struct dahdi_pvt *p;
15766    const char *channel = astman_get_header(m, "DAHDIChannel");
15767 
15768    if (ast_strlen_zero(channel)) {
15769       astman_send_error(s, m, "No channel specified");
15770       return 0;
15771    }
15772    p = find_channel_from_str(channel);
15773    if (!p) {
15774       astman_send_error(s, m, "No such channel");
15775       return 0;
15776    }
15777    dahdi_dnd(p, 0);
15778    astman_send_ack(s, m, "DND Disabled");
15779    return 0;
15780 }
15781 
15782 static int action_transfer(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,TRANSFER);
15801    astman_send_ack(s, m, "DAHDITransfer");
15802    return 0;
15803 }
15804 
15805 static int action_transferhangup(struct mansession *s, const struct message *m)
15806 {
15807    struct dahdi_pvt *p;
15808    const char *channel = astman_get_header(m, "DAHDIChannel");
15809 
15810    if (ast_strlen_zero(channel)) {
15811       astman_send_error(s, m, "No channel specified");
15812       return 0;
15813    }
15814    p = find_channel_from_str(channel);
15815    if (!p) {
15816       astman_send_error(s, m, "No such channel");
15817       return 0;
15818    }
15819    if (!analog_lib_handles(p->sig, 0, 0)) {
15820       astman_send_error(s, m, "Channel signaling is not analog");
15821       return 0;
15822    }
15823    dahdi_fake_event(p,HANGUP);
15824    astman_send_ack(s, m, "DAHDIHangup");
15825    return 0;
15826 }
15827 
15828 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15829 {
15830    struct dahdi_pvt *p;
15831    const char *channel = astman_get_header(m, "DAHDIChannel");
15832    const char *number = astman_get_header(m, "Number");
15833    int i;
15834 
15835    if (ast_strlen_zero(channel)) {
15836       astman_send_error(s, m, "No channel specified");
15837       return 0;
15838    }
15839    if (ast_strlen_zero(number)) {
15840       astman_send_error(s, m, "No number specified");
15841       return 0;
15842    }
15843    p = find_channel_from_str(channel);
15844    if (!p) {
15845       astman_send_error(s, m, "No such channel");
15846       return 0;
15847    }
15848    if (!p->owner) {
15849       astman_send_error(s, m, "Channel does not have it's owner");
15850       return 0;
15851    }
15852    for (i = 0; i < strlen(number); i++) {
15853       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15854       dahdi_queue_frame(p, &f);
15855    }
15856    astman_send_ack(s, m, "DAHDIDialOffhook");
15857    return 0;
15858 }
15859 
15860 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15861 {
15862    struct dahdi_pvt *tmp = NULL;
15863    const char *id = astman_get_header(m, "ActionID");
15864    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15865    char idText[256] = "";
15866    int channels = 0;
15867    int dahdichanquery;
15868 
15869    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15870       /* Not numeric string. */
15871       dahdichanquery = -1;
15872    }
15873 
15874    astman_send_ack(s, m, "DAHDI channel status will follow");
15875    if (!ast_strlen_zero(id))
15876       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15877 
15878    ast_mutex_lock(&iflock);
15879 
15880    for (tmp = iflist; tmp; tmp = tmp->next) {
15881       if (tmp->channel > 0) {
15882          int alm;
15883 
15884          /* If a specific channel is queried for, only deliver status for that channel */
15885          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15886             continue;
15887 
15888          alm = get_alarms(tmp);
15889          channels++;
15890          if (tmp->owner) {
15891             /* Add data if we have a current call */
15892             astman_append(s,
15893                "Event: DAHDIShowChannels\r\n"
15894                "DAHDIChannel: %d\r\n"
15895                "Channel: %s\r\n"
15896                "Uniqueid: %s\r\n"
15897                "AccountCode: %s\r\n"
15898                "Signalling: %s\r\n"
15899                "SignallingCode: %d\r\n"
15900                "Context: %s\r\n"
15901                "DND: %s\r\n"
15902                "Alarm: %s\r\n"
15903                "%s"
15904                "\r\n",
15905                tmp->channel,
15906                tmp->owner->name,
15907                tmp->owner->uniqueid,
15908                tmp->owner->accountcode,
15909                sig2str(tmp->sig),
15910                tmp->sig,
15911                tmp->context,
15912                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15913                alarm2str(alm), idText);
15914          } else {
15915             astman_append(s,
15916                "Event: DAHDIShowChannels\r\n"
15917                "DAHDIChannel: %d\r\n"
15918                "Signalling: %s\r\n"
15919                "SignallingCode: %d\r\n"
15920                "Context: %s\r\n"
15921                "DND: %s\r\n"
15922                "Alarm: %s\r\n"
15923                "%s"
15924                "\r\n",
15925                tmp->channel, sig2str(tmp->sig), tmp->sig,
15926                tmp->context,
15927                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15928                alarm2str(alm), idText);
15929          }
15930       }
15931    }
15932 
15933    ast_mutex_unlock(&iflock);
15934 
15935    astman_append(s,
15936       "Event: DAHDIShowChannelsComplete\r\n"
15937       "%s"
15938       "Items: %d\r\n"
15939       "\r\n",
15940       idText,
15941       channels);
15942    return 0;
15943 }
15944 
15945 #if defined(HAVE_SS7)
15946 static int linkset_addsigchan(int sigchan)
15947 {
15948    struct dahdi_ss7 *link;
15949    int res;
15950    int curfd;
15951    struct dahdi_params params;
15952    struct dahdi_bufferinfo bi;
15953    struct dahdi_spaninfo si;
15954 
15955    if (sigchan < 0) {
15956       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15957       return -1;
15958    }
15959    if (cur_ss7type < 0) {
15960       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15961       return -1;
15962    }
15963    if (cur_pointcode < 0) {
15964       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15965       return -1;
15966    }
15967    if (cur_adjpointcode < 0) {
15968       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15969       return -1;
15970    }
15971    if (cur_defaultdpc < 0) {
15972       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15973       return -1;
15974    }
15975    if (cur_networkindicator < 0) {
15976       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15977       return -1;
15978    }
15979    link = ss7_resolve_linkset(cur_linkset);
15980    if (!link) {
15981       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15982       return -1;
15983    }
15984    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15985       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15986       return -1;
15987    }
15988 
15989    curfd = link->ss7.numsigchans;
15990 
15991    /* Open signaling channel */
15992    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15993    if (link->ss7.fds[curfd] < 0) {
15994       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15995          strerror(errno));
15996       return -1;
15997    }
15998    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15999       dahdi_close_ss7_fd(link, curfd);
16000       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16001          strerror(errno));
16002       return -1;
16003    }
16004 
16005    /* Get signaling channel parameters */
16006    memset(&params, 0, sizeof(params));
16007    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16008    if (res) {
16009       dahdi_close_ss7_fd(link, curfd);
16010       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16011          strerror(errno));
16012       return -1;
16013    }
16014    if (params.sigtype != DAHDI_SIG_HDLCFCS
16015       && params.sigtype != DAHDI_SIG_HARDHDLC
16016       && params.sigtype != DAHDI_SIG_MTP2) {
16017       dahdi_close_ss7_fd(link, curfd);
16018       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16019       return -1;
16020    }
16021 
16022    /* Set signaling channel buffer policy. */
16023    memset(&bi, 0, sizeof(bi));
16024    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16025    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16026    bi.numbufs = 32;
16027    bi.bufsize = 512;
16028    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16029       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16030          sigchan, strerror(errno));
16031       dahdi_close_ss7_fd(link, curfd);
16032       return -1;
16033    }
16034 
16035    /* Get current signaling channel alarm status. */
16036    memset(&si, 0, sizeof(si));
16037    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16038    if (res) {
16039       dahdi_close_ss7_fd(link, curfd);
16040       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16041          strerror(errno));
16042    }
16043 
16044    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16045       (params.sigtype == DAHDI_SIG_MTP2)
16046          ? SS7_TRANSPORT_DAHDIMTP2
16047          : SS7_TRANSPORT_DAHDIDCHAN,
16048       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16049    if (res) {
16050       dahdi_close_ss7_fd(link, curfd);
16051       return -1;
16052    }
16053 
16054    ++link->ss7.numsigchans;
16055 
16056    return 0;
16057 }
16058 #endif   /* defined(HAVE_SS7) */
16059 
16060 #if defined(HAVE_SS7)
16061 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16062 {
16063    int span;
16064    switch (cmd) {
16065    case CLI_INIT:
16066       e->command = "ss7 set debug {on|off} linkset";
16067       e->usage =
16068          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16069          "       Enables debugging on a given SS7 linkset\n";
16070       return NULL;
16071    case CLI_GENERATE:
16072       return NULL;
16073    }
16074    if (a->argc < 6)
16075       return CLI_SHOWUSAGE;
16076    span = atoi(a->argv[5]);
16077    if ((span < 1) || (span > NUM_SPANS)) {
16078       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16079       return CLI_SUCCESS;
16080    }
16081    if (!linksets[span-1].ss7.ss7) {
16082       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16083    } else {
16084       if (!strcasecmp(a->argv[3], "on")) {
16085          linksets[span - 1].ss7.debug = 1;
16086          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16087          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16088       } else {
16089          linksets[span - 1].ss7.debug = 0;
16090          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16091          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16092       }
16093    }
16094 
16095    return CLI_SUCCESS;
16096 }
16097 #endif   /* defined(HAVE_SS7) */
16098 
16099 #if defined(HAVE_SS7)
16100 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16101 {
16102    int linkset, cic;
16103    int blocked = -1, i;
16104    switch (cmd) {
16105    case CLI_INIT:
16106       e->command = "ss7 block cic";
16107       e->usage =
16108          "Usage: ss7 block cic <linkset> <CIC>\n"
16109          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16110       return NULL;
16111    case CLI_GENERATE:
16112       return NULL;
16113    }
16114    if (a->argc == 5)
16115       linkset = atoi(a->argv[3]);
16116    else
16117       return CLI_SHOWUSAGE;
16118 
16119    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16120       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16121       return CLI_SUCCESS;
16122    }
16123 
16124    if (!linksets[linkset-1].ss7.ss7) {
16125       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16126       return CLI_SUCCESS;
16127    }
16128 
16129    cic = atoi(a->argv[4]);
16130 
16131    if (cic < 1) {
16132       ast_cli(a->fd, "Invalid CIC specified!\n");
16133       return CLI_SUCCESS;
16134    }
16135 
16136    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16137       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16138          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16139          if (!blocked) {
16140             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16141             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16142             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16143          }
16144       }
16145    }
16146 
16147    if (blocked < 0) {
16148       ast_cli(a->fd, "Invalid CIC specified!\n");
16149       return CLI_SUCCESS;
16150    }
16151 
16152    if (!blocked)
16153       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16154    else
16155       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16156 
16157    /* Break poll on the linkset so it sends our messages */
16158    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16159 
16160    return CLI_SUCCESS;
16161 }
16162 #endif   /* defined(HAVE_SS7) */
16163 
16164 #if defined(HAVE_SS7)
16165 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16166 {
16167    int linkset;
16168    int i;
16169    switch (cmd) {
16170    case CLI_INIT:
16171       e->command = "ss7 block linkset";
16172       e->usage =
16173          "Usage: ss7 block linkset <linkset number>\n"
16174          "       Sends a remote blocking request for all CICs on the given linkset\n";
16175       return NULL;
16176    case CLI_GENERATE:
16177       return NULL;
16178    }
16179    if (a->argc == 4)
16180       linkset = atoi(a->argv[3]);
16181    else
16182       return CLI_SHOWUSAGE;
16183 
16184    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16185       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16186       return CLI_SUCCESS;
16187    }
16188 
16189    if (!linksets[linkset-1].ss7.ss7) {
16190       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16191       return CLI_SUCCESS;
16192    }
16193 
16194    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16195       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16196       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16197       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16198       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16199    }
16200 
16201    /* Break poll on the linkset so it sends our messages */
16202    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16203 
16204    return CLI_SUCCESS;
16205 }
16206 #endif   /* defined(HAVE_SS7) */
16207 
16208 #if defined(HAVE_SS7)
16209 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16210 {
16211    int linkset, cic;
16212    int i, blocked = -1;
16213    switch (cmd) {
16214    case CLI_INIT:
16215       e->command = "ss7 unblock cic";
16216       e->usage =
16217          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16218          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16219       return NULL;
16220    case CLI_GENERATE:
16221       return NULL;
16222    }
16223 
16224    if (a->argc == 5)
16225       linkset = atoi(a->argv[3]);
16226    else
16227       return CLI_SHOWUSAGE;
16228 
16229    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16230       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16231       return CLI_SUCCESS;
16232    }
16233 
16234    if (!linksets[linkset-1].ss7.ss7) {
16235       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16236       return CLI_SUCCESS;
16237    }
16238 
16239    cic = atoi(a->argv[4]);
16240 
16241    if (cic < 1) {
16242       ast_cli(a->fd, "Invalid CIC specified!\n");
16243       return CLI_SUCCESS;
16244    }
16245 
16246    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16247       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16248          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16249          if (blocked) {
16250             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16251             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16252             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16253          }
16254       }
16255    }
16256 
16257    if (blocked > 0)
16258       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16259 
16260    /* Break poll on the linkset so it sends our messages */
16261    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16262 
16263    return CLI_SUCCESS;
16264 }
16265 #endif   /* defined(HAVE_SS7) */
16266 
16267 #if defined(HAVE_SS7)
16268 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16269 {
16270    int linkset;
16271    int i;
16272    switch (cmd) {
16273    case CLI_INIT:
16274       e->command = "ss7 unblock linkset";
16275       e->usage =
16276          "Usage: ss7 unblock linkset <linkset number>\n"
16277          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16278       return NULL;
16279    case CLI_GENERATE:
16280       return NULL;
16281    }
16282 
16283    if (a->argc == 4)
16284       linkset = atoi(a->argv[3]);
16285    else
16286       return CLI_SHOWUSAGE;
16287 
16288    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16289       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16290       return CLI_SUCCESS;
16291    }
16292 
16293    if (!linksets[linkset-1].ss7.ss7) {
16294       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16295       return CLI_SUCCESS;
16296    }
16297 
16298    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16299       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16300       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16301       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16302       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16303    }
16304 
16305    /* Break poll on the linkset so it sends our messages */
16306    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16307 
16308    return CLI_SUCCESS;
16309 }
16310 #endif   /* defined(HAVE_SS7) */
16311 
16312 #if defined(HAVE_SS7)
16313 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16314 {
16315    int linkset;
16316    struct sig_ss7_linkset *ss7;
16317    switch (cmd) {
16318    case CLI_INIT:
16319       e->command = "ss7 show linkset";
16320       e->usage =
16321          "Usage: ss7 show linkset <span>\n"
16322          "       Shows the status of an SS7 linkset.\n";
16323       return NULL;
16324    case CLI_GENERATE:
16325       return NULL;
16326    }
16327 
16328    if (a->argc < 4)
16329       return CLI_SHOWUSAGE;
16330    linkset = atoi(a->argv[3]);
16331    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16332       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16333       return CLI_SUCCESS;
16334    }
16335    ss7 = &linksets[linkset - 1].ss7;
16336    if (!ss7->ss7) {
16337       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16338       return CLI_SUCCESS;
16339    }
16340 
16341    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16342 
16343    return CLI_SUCCESS;
16344 }
16345 #endif   /* defined(HAVE_SS7) */
16346 
16347 #if defined(HAVE_SS7)
16348 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16349 {
16350    int linkset;
16351 
16352    switch (cmd) {
16353    case CLI_INIT:
16354       e->command = "ss7 show channels";
16355       e->usage =
16356          "Usage: ss7 show channels\n"
16357          "       Displays SS7 channel information at a glance.\n";
16358       return NULL;
16359    case CLI_GENERATE:
16360       return NULL;
16361    }
16362 
16363    if (a->argc != 3)
16364       return CLI_SHOWUSAGE;
16365 
16366    sig_ss7_cli_show_channels_header(a->fd);
16367    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16368       if (linksets[linkset].ss7.ss7) {
16369          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16370       }
16371    }
16372    return CLI_SUCCESS;
16373 }
16374 #endif   /* defined(HAVE_SS7) */
16375 
16376 #if defined(HAVE_SS7)
16377 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16378 {
16379    switch (cmd) {
16380    case CLI_INIT:
16381       e->command = "ss7 show version";
16382       e->usage =
16383          "Usage: ss7 show version\n"
16384          "  Show the libss7 version\n";
16385       return NULL;
16386    case CLI_GENERATE:
16387       return NULL;
16388    }
16389 
16390    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16391 
16392    return CLI_SUCCESS;
16393 }
16394 #endif   /* defined(HAVE_SS7) */
16395 
16396 #if defined(HAVE_SS7)
16397 static struct ast_cli_entry dahdi_ss7_cli[] = {
16398    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16399    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16400    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16401    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16402    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16403    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16404    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16405    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16406 };
16407 #endif   /* defined(HAVE_SS7) */
16408 
16409 #if defined(HAVE_PRI)
16410 #if defined(HAVE_PRI_CCSS)
16411 /*!
16412  * \internal
16413  * \brief CC agent initialization.
16414  * \since 1.8
16415  *
16416  * \param agent CC core agent control.
16417  * \param chan Original channel the agent will attempt to recall.
16418  *
16419  * \details
16420  * This callback is called when the CC core is initialized.  Agents should allocate
16421  * any private data necessary for the call and assign it to the private_data
16422  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16423  * specific agent type, they should be set in this function as well.
16424  *
16425  * \retval 0 on success.
16426  * \retval -1 on error.
16427  */
16428 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16429 {
16430    struct dahdi_pvt *pvt;
16431    struct sig_pri_chan *pvt_chan;
16432    int res;
16433 
16434    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16435 
16436    pvt = chan->tech_pvt;
16437    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16438       pvt_chan = pvt->sig_pvt;
16439    } else {
16440       pvt_chan = NULL;
16441    }
16442    if (!pvt_chan) {
16443       return -1;
16444    }
16445 
16446    ast_module_ref(ast_module_info->self);
16447 
16448    res = sig_pri_cc_agent_init(agent, pvt_chan);
16449    if (res) {
16450       ast_module_unref(ast_module_info->self);
16451    }
16452    return res;
16453 }
16454 #endif   /* defined(HAVE_PRI_CCSS) */
16455 #endif   /* defined(HAVE_PRI) */
16456 
16457 #if defined(HAVE_PRI)
16458 #if defined(HAVE_PRI_CCSS)
16459 /*!
16460  * \internal
16461  * \brief Destroy private data on the agent.
16462  * \since 1.8
16463  *
16464  * \param agent CC core agent control.
16465  *
16466  * \details
16467  * The core will call this function upon completion
16468  * or failure of CC.
16469  *
16470  * \return Nothing
16471  */
16472 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16473 {
16474    sig_pri_cc_agent_destructor(agent);
16475 
16476    ast_module_unref(ast_module_info->self);
16477 }
16478 #endif   /* defined(HAVE_PRI_CCSS) */
16479 #endif   /* defined(HAVE_PRI) */
16480 
16481 #if defined(HAVE_PRI)
16482 #if defined(HAVE_PRI_CCSS)
16483 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16484    .type = dahdi_pri_cc_type,
16485    .init = dahdi_pri_cc_agent_init,
16486    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16487    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16488    .respond = sig_pri_cc_agent_req_rsp,
16489    .status_request = sig_pri_cc_agent_status_req,
16490    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16491    .party_b_free = sig_pri_cc_agent_party_b_free,
16492    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16493    .callee_available = sig_pri_cc_agent_callee_available,
16494    .destructor = dahdi_pri_cc_agent_destructor,
16495 };
16496 #endif   /* defined(HAVE_PRI_CCSS) */
16497 #endif   /* defined(HAVE_PRI) */
16498 
16499 #if defined(HAVE_PRI)
16500 #if defined(HAVE_PRI_CCSS)
16501 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16502    .type = dahdi_pri_cc_type,
16503    .request_cc = sig_pri_cc_monitor_req_cc,
16504    .suspend = sig_pri_cc_monitor_suspend,
16505    .unsuspend = sig_pri_cc_monitor_unsuspend,
16506    .status_response = sig_pri_cc_monitor_status_rsp,
16507    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16508    .destructor = sig_pri_cc_monitor_destructor,
16509 };
16510 #endif   /* defined(HAVE_PRI_CCSS) */
16511 #endif   /* defined(HAVE_PRI) */
16512 
16513 static int __unload_module(void)
16514 {
16515    struct dahdi_pvt *p;
16516 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16517    int i, j;
16518 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16519 
16520 #ifdef HAVE_PRI
16521    for (i = 0; i < NUM_SPANS; i++) {
16522       if (pris[i].pri.master != AST_PTHREADT_NULL)
16523          pthread_cancel(pris[i].pri.master);
16524    }
16525    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16526    ast_unregister_application(dahdi_send_keypad_facility_app);
16527 #ifdef HAVE_PRI_PROG_W_CAUSE
16528    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16529 #endif
16530 #endif
16531 #if defined(HAVE_SS7)
16532    for (i = 0; i < NUM_SPANS; i++) {
16533       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16534          pthread_cancel(linksets[i].ss7.master);
16535       }
16536    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16537 #endif   /* defined(HAVE_SS7) */
16538 #if defined(HAVE_OPENR2)
16539    dahdi_r2_destroy_links();
16540    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16541    ast_unregister_application(dahdi_accept_r2_call_app);
16542 #endif
16543 
16544    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16545    ast_manager_unregister("DAHDIDialOffhook");
16546    ast_manager_unregister("DAHDIHangup");
16547    ast_manager_unregister("DAHDITransfer");
16548    ast_manager_unregister("DAHDIDNDoff");
16549    ast_manager_unregister("DAHDIDNDon");
16550    ast_manager_unregister("DAHDIShowChannels");
16551    ast_manager_unregister("DAHDIRestart");
16552    ast_data_unregister(NULL);
16553    ast_channel_unregister(&dahdi_tech);
16554 
16555    /* Hangup all interfaces if they have an owner */
16556    ast_mutex_lock(&iflock);
16557    for (p = iflist; p; p = p->next) {
16558       if (p->owner)
16559          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16560    }
16561    ast_mutex_unlock(&iflock);
16562 
16563    ast_mutex_lock(&monlock);
16564    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16565       pthread_cancel(monitor_thread);
16566       pthread_kill(monitor_thread, SIGURG);
16567       pthread_join(monitor_thread, NULL);
16568    }
16569    monitor_thread = AST_PTHREADT_STOP;
16570    ast_mutex_unlock(&monlock);
16571 
16572    destroy_all_channels();
16573 
16574 #if defined(HAVE_PRI)
16575    for (i = 0; i < NUM_SPANS; i++) {
16576       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16577          pthread_join(pris[i].pri.master, NULL);
16578       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16579          dahdi_close_pri_fd(&(pris[i]), j);
16580       }
16581       sig_pri_stop_pri(&pris[i].pri);
16582    }
16583 #if defined(HAVE_PRI_CCSS)
16584    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16585    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16586 #endif   /* defined(HAVE_PRI_CCSS) */
16587    sig_pri_unload();
16588 #endif
16589 
16590 #if defined(HAVE_SS7)
16591    for (i = 0; i < NUM_SPANS; i++) {
16592       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16593          pthread_join(linksets[i].ss7.master, NULL);
16594       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16595          dahdi_close_ss7_fd(&(linksets[i]), j);
16596       }
16597    }
16598 #endif   /* defined(HAVE_SS7) */
16599    ast_cond_destroy(&ss_thread_complete);
16600    return 0;
16601 }
16602 
16603 static int unload_module(void)
16604 {
16605 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16606    int y;
16607 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16608 #ifdef HAVE_PRI
16609    for (y = 0; y < NUM_SPANS; y++)
16610       ast_mutex_destroy(&pris[y].pri.lock);
16611 #endif
16612 #if defined(HAVE_SS7)
16613    for (y = 0; y < NUM_SPANS; y++)
16614       ast_mutex_destroy(&linksets[y].ss7.lock);
16615 #endif   /* defined(HAVE_SS7) */
16616    return __unload_module();
16617 }
16618 
16619 static void string_replace(char *str, int char1, int char2)
16620 {
16621    for (; *str; str++) {
16622       if (*str == char1) {
16623          *str = char2;
16624       }
16625    }
16626 }
16627 
16628 static char *parse_spanchan(char *chanstr, char **subdir)
16629 {
16630    char *p;
16631 
16632    if ((p = strrchr(chanstr, '!')) == NULL) {
16633       *subdir = NULL;
16634       return chanstr;
16635    }
16636    *p++ = '\0';
16637    string_replace(chanstr, '!', '/');
16638    *subdir = chanstr;
16639    return p;
16640 }
16641 
16642 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16643 {
16644    char *c, *chan;
16645    char *subdir;
16646    int x, start, finish;
16647    struct dahdi_pvt *tmp;
16648 
16649    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16650       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16651       return -1;
16652    }
16653 
16654    c = ast_strdupa(value);
16655    c = parse_spanchan(c, &subdir);
16656 
16657    while ((chan = strsep(&c, ","))) {
16658       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16659          /* Range */
16660       } else if (sscanf(chan, "%30d", &start)) {
16661          /* Just one */
16662          finish = start;
16663       } else if (!strcasecmp(chan, "pseudo")) {
16664          finish = start = CHAN_PSEUDO;
16665          if (found_pseudo)
16666             *found_pseudo = 1;
16667       } else {
16668          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16669          return -1;
16670       }
16671       if (finish < start) {
16672          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16673          x = finish;
16674          finish = start;
16675          start = x;
16676       }
16677 
16678       for (x = start; x <= finish; x++) {
16679          char fn[PATH_MAX];
16680          int real_channel = x;
16681 
16682          if (!ast_strlen_zero(subdir)) {
16683             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16684             if (real_channel < 0) {
16685                if (conf->ignore_failed_channels) {
16686                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16687                         subdir, x, real_channel);
16688                   continue;
16689                } else {
16690                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16691                         subdir, x, real_channel);
16692                   return -1;
16693                }
16694             }
16695          }
16696          tmp = mkintf(real_channel, conf, reload);
16697 
16698          if (tmp) {
16699             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16700          } else {
16701             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16702                   (reload == 1) ? "reconfigure" : "register", value);
16703             return -1;
16704          }
16705       }
16706    }
16707 
16708    return 0;
16709 }
16710 
16711 /** The length of the parameters list of 'dahdichan'.
16712  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16713 #define MAX_CHANLIST_LEN 80
16714 
16715 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16716 {
16717    char *parse = ast_strdupa(data);
16718    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16719    unsigned int param_count;
16720    unsigned int x;
16721 
16722    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16723       return;
16724 
16725    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16726 
16727    /* first parameter is tap length, process it here */
16728 
16729    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16730 
16731    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16732       confp->chan.echocancel.head.tap_length = x;
16733    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16734       confp->chan.echocancel.head.tap_length = 128;
16735 
16736    /* now process any remaining parameters */
16737 
16738    for (x = 1; x < param_count; x++) {
16739       struct {
16740          char *name;
16741          char *value;
16742       } param;
16743 
16744       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16745          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16746          continue;
16747       }
16748 
16749       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16750          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16751          continue;
16752       }
16753 
16754       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16755 
16756       if (param.value) {
16757          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16758             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16759             continue;
16760          }
16761       }
16762       confp->chan.echocancel.head.param_count++;
16763    }
16764 }
16765 
16766 /*! process_dahdi() - ignore keyword 'channel' and similar */
16767 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16768 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16769 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16770 
16771 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16772 {
16773    struct dahdi_pvt *tmp;
16774    int y;
16775    int found_pseudo = 0;
16776    struct ast_variable *dahdichan = NULL;
16777 
16778    for (; v; v = v->next) {
16779       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16780          continue;
16781 
16782       /* Create the interface list */
16783       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16784          if (options & PROC_DAHDI_OPT_NOCHAN) {
16785             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16786             continue;
16787          }
16788          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16789             if (confp->ignore_failed_channels) {
16790                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16791                continue;
16792             } else {
16793                return -1;
16794             }
16795          }
16796          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16797       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16798          confp->ignore_failed_channels = ast_true(v->value);
16799       } else if (!strcasecmp(v->name, "buffers")) {
16800          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16801             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16802             confp->chan.buf_no = numbufs;
16803             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16804          }
16805       } else if (!strcasecmp(v->name, "faxbuffers")) {
16806          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16807             confp->chan.usefaxbuffers = 1;
16808          }
16809       } else if (!strcasecmp(v->name, "dahdichan")) {
16810          /* Only process the last dahdichan value. */
16811          dahdichan = v;
16812       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16813          usedistinctiveringdetection = ast_true(v->value);
16814       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16815          distinctiveringaftercid = ast_true(v->value);
16816       } else if (!strcasecmp(v->name, "dring1context")) {
16817          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16818       } else if (!strcasecmp(v->name, "dring2context")) {
16819          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16820       } else if (!strcasecmp(v->name, "dring3context")) {
16821          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16822       } else if (!strcasecmp(v->name, "dring1range")) {
16823          confp->chan.drings.ringnum[0].range = atoi(v->value);
16824       } else if (!strcasecmp(v->name, "dring2range")) {
16825          confp->chan.drings.ringnum[1].range = atoi(v->value);
16826       } else if (!strcasecmp(v->name, "dring3range")) {
16827          confp->chan.drings.ringnum[2].range = atoi(v->value);
16828       } else if (!strcasecmp(v->name, "dring1")) {
16829          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]);
16830       } else if (!strcasecmp(v->name, "dring2")) {
16831          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]);
16832       } else if (!strcasecmp(v->name, "dring3")) {
16833          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]);
16834       } else if (!strcasecmp(v->name, "usecallerid")) {
16835          confp->chan.use_callerid = ast_true(v->value);
16836       } else if (!strcasecmp(v->name, "cidsignalling")) {
16837          if (!strcasecmp(v->value, "bell"))
16838             confp->chan.cid_signalling = CID_SIG_BELL;
16839          else if (!strcasecmp(v->value, "v23"))
16840             confp->chan.cid_signalling = CID_SIG_V23;
16841          else if (!strcasecmp(v->value, "dtmf"))
16842             confp->chan.cid_signalling = CID_SIG_DTMF;
16843          else if (!strcasecmp(v->value, "smdi"))
16844             confp->chan.cid_signalling = CID_SIG_SMDI;
16845          else if (!strcasecmp(v->value, "v23_jp"))
16846             confp->chan.cid_signalling = CID_SIG_V23_JP;
16847          else if (ast_true(v->value))
16848             confp->chan.cid_signalling = CID_SIG_BELL;
16849       } else if (!strcasecmp(v->name, "cidstart")) {
16850          if (!strcasecmp(v->value, "ring"))
16851             confp->chan.cid_start = CID_START_RING;
16852          else if (!strcasecmp(v->value, "polarity_in"))
16853             confp->chan.cid_start = CID_START_POLARITY_IN;
16854          else if (!strcasecmp(v->value, "polarity"))
16855             confp->chan.cid_start = CID_START_POLARITY;
16856          else if (!strcasecmp(v->value, "dtmf"))
16857             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16858          else if (ast_true(v->value))
16859             confp->chan.cid_start = CID_START_RING;
16860       } else if (!strcasecmp(v->name, "threewaycalling")) {
16861          confp->chan.threewaycalling = ast_true(v->value);
16862       } else if (!strcasecmp(v->name, "cancallforward")) {
16863          confp->chan.cancallforward = ast_true(v->value);
16864       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16865          if (ast_true(v->value))
16866             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16867          else
16868             confp->chan.dtmfrelax = 0;
16869       } else if (!strcasecmp(v->name, "mailbox")) {
16870          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16871       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16872          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16873             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16874          }
16875       } else if (!strcasecmp(v->name, "adsi")) {
16876          confp->chan.adsi = ast_true(v->value);
16877       } else if (!strcasecmp(v->name, "usesmdi")) {
16878          confp->chan.use_smdi = ast_true(v->value);
16879       } else if (!strcasecmp(v->name, "smdiport")) {
16880          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16881       } else if (!strcasecmp(v->name, "transfer")) {
16882          confp->chan.transfer = ast_true(v->value);
16883       } else if (!strcasecmp(v->name, "canpark")) {
16884          confp->chan.canpark = ast_true(v->value);
16885       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16886          confp->chan.echocanbridged = ast_true(v->value);
16887       } else if (!strcasecmp(v->name, "busydetect")) {
16888          confp->chan.busydetect = ast_true(v->value);
16889       } else if (!strcasecmp(v->name, "busycount")) {
16890          confp->chan.busycount = atoi(v->value);
16891       } else if (!strcasecmp(v->name, "busypattern")) {
16892          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16893             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16894          }
16895       } else if (!strcasecmp(v->name, "callprogress")) {
16896          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16897          if (ast_true(v->value))
16898             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16899       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16900          confp->chan.waitfordialtone = atoi(v->value);
16901       } else if (!strcasecmp(v->name, "faxdetect")) {
16902          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16903          if (!strcasecmp(v->value, "incoming")) {
16904             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16905          } else if (!strcasecmp(v->value, "outgoing")) {
16906             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16907          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16908             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16909       } else if (!strcasecmp(v->name, "echocancel")) {
16910          process_echocancel(confp, v->value, v->lineno);
16911       } else if (!strcasecmp(v->name, "echotraining")) {
16912          if (sscanf(v->value, "%30d", &y) == 1) {
16913             if ((y < 10) || (y > 4000)) {
16914                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16915             } else {
16916                confp->chan.echotraining = y;
16917             }
16918          } else if (ast_true(v->value)) {
16919             confp->chan.echotraining = 400;
16920          } else
16921             confp->chan.echotraining = 0;
16922       } else if (!strcasecmp(v->name, "hidecallerid")) {
16923          confp->chan.hidecallerid = ast_true(v->value);
16924       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16925          confp->chan.hidecalleridname = ast_true(v->value);
16926       } else if (!strcasecmp(v->name, "pulsedial")) {
16927          confp->chan.pulse = ast_true(v->value);
16928       } else if (!strcasecmp(v->name, "callreturn")) {
16929          confp->chan.callreturn = ast_true(v->value);
16930       } else if (!strcasecmp(v->name, "callwaiting")) {
16931          confp->chan.callwaiting = ast_true(v->value);
16932       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16933          confp->chan.callwaitingcallerid = ast_true(v->value);
16934       } else if (!strcasecmp(v->name, "context")) {
16935          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16936       } else if (!strcasecmp(v->name, "language")) {
16937          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16938       } else if (!strcasecmp(v->name, "progzone")) {
16939          ast_copy_string(progzone, v->value, sizeof(progzone));
16940       } else if (!strcasecmp(v->name, "mohinterpret")
16941          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16942          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16943       } else if (!strcasecmp(v->name, "mohsuggest")) {
16944          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16945       } else if (!strcasecmp(v->name, "parkinglot")) {
16946          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16947       } else if (!strcasecmp(v->name, "stripmsd")) {
16948          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16949          confp->chan.stripmsd = atoi(v->value);
16950       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16951          numbufs = atoi(v->value);
16952       } else if (!strcasecmp(v->name, "group")) {
16953          confp->chan.group = ast_get_group(v->value);
16954       } else if (!strcasecmp(v->name, "callgroup")) {
16955          if (!strcasecmp(v->value, "none"))
16956             confp->chan.callgroup = 0;
16957          else
16958             confp->chan.callgroup = ast_get_group(v->value);
16959       } else if (!strcasecmp(v->name, "pickupgroup")) {
16960          if (!strcasecmp(v->value, "none"))
16961             confp->chan.pickupgroup = 0;
16962          else
16963             confp->chan.pickupgroup = ast_get_group(v->value);
16964       } else if (!strcasecmp(v->name, "setvar")) {
16965          char *varname = ast_strdupa(v->value), *varval = NULL;
16966          struct ast_variable *tmpvar;
16967          if (varname && (varval = strchr(varname, '='))) {
16968             *varval++ = '\0';
16969             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16970                tmpvar->next = confp->chan.vars;
16971                confp->chan.vars = tmpvar;
16972             }
16973          }
16974       } else if (!strcasecmp(v->name, "immediate")) {
16975          confp->chan.immediate = ast_true(v->value);
16976       } else if (!strcasecmp(v->name, "transfertobusy")) {
16977          confp->chan.transfertobusy = ast_true(v->value);
16978       } else if (!strcasecmp(v->name, "mwimonitor")) {
16979          confp->chan.mwimonitor_neon = 0;
16980          confp->chan.mwimonitor_fsk = 0;
16981          confp->chan.mwimonitor_rpas = 0;
16982          if (strcasestr(v->value, "fsk")) {
16983             confp->chan.mwimonitor_fsk = 1;
16984          }
16985          if (strcasestr(v->value, "rpas")) {
16986             confp->chan.mwimonitor_rpas = 1;
16987          }
16988          if (strcasestr(v->value, "neon")) {
16989             confp->chan.mwimonitor_neon = 1;
16990          }
16991          /* If set to true or yes, assume that simple fsk is desired */
16992          if (ast_true(v->value)) {
16993             confp->chan.mwimonitor_fsk = 1;
16994          }
16995       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16996          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16997             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16998          }
16999       } else if (!strcasecmp(v->name, "rxgain")) {
17000          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17001             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17002          }
17003       } else if (!strcasecmp(v->name, "txgain")) {
17004          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17005             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17006          }
17007       } else if (!strcasecmp(v->name, "txdrc")) {
17008          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17009             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17010          }
17011       } else if (!strcasecmp(v->name, "rxdrc")) {
17012          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17013             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17014          }
17015       } else if (!strcasecmp(v->name, "tonezone")) {
17016          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17017             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17018          }
17019       } else if (!strcasecmp(v->name, "callerid")) {
17020          if (!strcasecmp(v->value, "asreceived")) {
17021             confp->chan.cid_num[0] = '\0';
17022             confp->chan.cid_name[0] = '\0';
17023          } else {
17024             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17025          }
17026       } else if (!strcasecmp(v->name, "fullname")) {
17027          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17028       } else if (!strcasecmp(v->name, "cid_number")) {
17029          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17030       } else if (!strcasecmp(v->name, "cid_tag")) {
17031          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17032       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17033          confp->chan.dahditrcallerid = ast_true(v->value);
17034       } else if (!strcasecmp(v->name, "restrictcid")) {
17035          confp->chan.restrictcid = ast_true(v->value);
17036       } else if (!strcasecmp(v->name, "usecallingpres")) {
17037          confp->chan.use_callingpres = ast_true(v->value);
17038       } else if (!strcasecmp(v->name, "accountcode")) {
17039          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17040       } else if (!strcasecmp(v->name, "amaflags")) {
17041          y = ast_cdr_amaflags2int(v->value);
17042          if (y < 0)
17043             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17044          else
17045             confp->chan.amaflags = y;
17046       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17047          confp->chan.polarityonanswerdelay = atoi(v->value);
17048       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17049          confp->chan.answeronpolarityswitch = ast_true(v->value);
17050       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17051          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17052       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17053          confp->chan.sendcalleridafter = atoi(v->value);
17054       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17055          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17056       } else if (ast_cc_is_config_param(v->name)) {
17057          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17058       } else if (!strcasecmp(v->name, "mwisendtype")) {
17059 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17060          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17061             mwisend_rpas = 1;
17062          } else {
17063             mwisend_rpas = 0;
17064          }
17065 #else
17066          /* Default is fsk, to turn it off you must specify nofsk */
17067          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17068          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17069             confp->chan.mwisend_fsk = 0;
17070          } else {             /* Default FSK */
17071             confp->chan.mwisend_fsk = 1;
17072          }
17073          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17074             confp->chan.mwisend_rpas = 1;
17075          } else {
17076             confp->chan.mwisend_rpas = 0;
17077          }
17078          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17079             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17080          }
17081          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17082             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17083          }
17084          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17085             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17086          }
17087 #endif
17088       } else if (reload != 1) {
17089           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17090             int orig_radio = confp->chan.radio;
17091             int orig_outsigmod = confp->chan.outsigmod;
17092             int orig_auto = confp->is_sig_auto;
17093 
17094             confp->chan.radio = 0;
17095             confp->chan.outsigmod = -1;
17096             confp->is_sig_auto = 0;
17097             if (!strcasecmp(v->value, "em")) {
17098                confp->chan.sig = SIG_EM;
17099             } else if (!strcasecmp(v->value, "em_e1")) {
17100                confp->chan.sig = SIG_EM_E1;
17101             } else if (!strcasecmp(v->value, "em_w")) {
17102                confp->chan.sig = SIG_EMWINK;
17103             } else if (!strcasecmp(v->value, "fxs_ls")) {
17104                confp->chan.sig = SIG_FXSLS;
17105             } else if (!strcasecmp(v->value, "fxs_gs")) {
17106                confp->chan.sig = SIG_FXSGS;
17107             } else if (!strcasecmp(v->value, "fxs_ks")) {
17108                confp->chan.sig = SIG_FXSKS;
17109             } else if (!strcasecmp(v->value, "fxo_ls")) {
17110                confp->chan.sig = SIG_FXOLS;
17111             } else if (!strcasecmp(v->value, "fxo_gs")) {
17112                confp->chan.sig = SIG_FXOGS;
17113             } else if (!strcasecmp(v->value, "fxo_ks")) {
17114                confp->chan.sig = SIG_FXOKS;
17115             } else if (!strcasecmp(v->value, "fxs_rx")) {
17116                confp->chan.sig = SIG_FXSKS;
17117                confp->chan.radio = 1;
17118             } else if (!strcasecmp(v->value, "fxo_rx")) {
17119                confp->chan.sig = SIG_FXOLS;
17120                confp->chan.radio = 1;
17121             } else if (!strcasecmp(v->value, "fxs_tx")) {
17122                confp->chan.sig = SIG_FXSLS;
17123                confp->chan.radio = 1;
17124             } else if (!strcasecmp(v->value, "fxo_tx")) {
17125                confp->chan.sig = SIG_FXOGS;
17126                confp->chan.radio = 1;
17127             } else if (!strcasecmp(v->value, "em_rx")) {
17128                confp->chan.sig = SIG_EM;
17129                confp->chan.radio = 1;
17130             } else if (!strcasecmp(v->value, "em_tx")) {
17131                confp->chan.sig = SIG_EM;
17132                confp->chan.radio = 1;
17133             } else if (!strcasecmp(v->value, "em_rxtx")) {
17134                confp->chan.sig = SIG_EM;
17135                confp->chan.radio = 2;
17136             } else if (!strcasecmp(v->value, "em_txrx")) {
17137                confp->chan.sig = SIG_EM;
17138                confp->chan.radio = 2;
17139             } else if (!strcasecmp(v->value, "sf")) {
17140                confp->chan.sig = SIG_SF;
17141             } else if (!strcasecmp(v->value, "sf_w")) {
17142                confp->chan.sig = SIG_SFWINK;
17143             } else if (!strcasecmp(v->value, "sf_featd")) {
17144                confp->chan.sig = SIG_FEATD;
17145             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17146                confp->chan.sig = SIG_FEATDMF;
17147             } else if (!strcasecmp(v->value, "sf_featb")) {
17148                confp->chan.sig = SIG_SF_FEATB;
17149             } else if (!strcasecmp(v->value, "sf")) {
17150                confp->chan.sig = SIG_SF;
17151             } else if (!strcasecmp(v->value, "sf_rx")) {
17152                confp->chan.sig = SIG_SF;
17153                confp->chan.radio = 1;
17154             } else if (!strcasecmp(v->value, "sf_tx")) {
17155                confp->chan.sig = SIG_SF;
17156                confp->chan.radio = 1;
17157             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17158                confp->chan.sig = SIG_SF;
17159                confp->chan.radio = 2;
17160             } else if (!strcasecmp(v->value, "sf_txrx")) {
17161                confp->chan.sig = SIG_SF;
17162                confp->chan.radio = 2;
17163             } else if (!strcasecmp(v->value, "featd")) {
17164                confp->chan.sig = SIG_FEATD;
17165             } else if (!strcasecmp(v->value, "featdmf")) {
17166                confp->chan.sig = SIG_FEATDMF;
17167             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17168                confp->chan.sig = SIG_FEATDMF_TA;
17169             } else if (!strcasecmp(v->value, "e911")) {
17170                confp->chan.sig = SIG_E911;
17171             } else if (!strcasecmp(v->value, "fgccama")) {
17172                confp->chan.sig = SIG_FGC_CAMA;
17173             } else if (!strcasecmp(v->value, "fgccamamf")) {
17174                confp->chan.sig = SIG_FGC_CAMAMF;
17175             } else if (!strcasecmp(v->value, "featb")) {
17176                confp->chan.sig = SIG_FEATB;
17177 #ifdef HAVE_PRI
17178             } else if (!strcasecmp(v->value, "pri_net")) {
17179                confp->chan.sig = SIG_PRI;
17180                confp->pri.pri.nodetype = PRI_NETWORK;
17181             } else if (!strcasecmp(v->value, "pri_cpe")) {
17182                confp->chan.sig = SIG_PRI;
17183                confp->pri.pri.nodetype = PRI_CPE;
17184             } else if (!strcasecmp(v->value, "bri_cpe")) {
17185                confp->chan.sig = SIG_BRI;
17186                confp->pri.pri.nodetype = PRI_CPE;
17187             } else if (!strcasecmp(v->value, "bri_net")) {
17188                confp->chan.sig = SIG_BRI;
17189                confp->pri.pri.nodetype = PRI_NETWORK;
17190             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17191                confp->chan.sig = SIG_BRI_PTMP;
17192                confp->pri.pri.nodetype = PRI_CPE;
17193             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17194 #if defined(HAVE_PRI_CALL_HOLD)
17195                confp->chan.sig = SIG_BRI_PTMP;
17196                confp->pri.pri.nodetype = PRI_NETWORK;
17197 #else
17198                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17199 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17200 #endif
17201 #if defined(HAVE_SS7)
17202             } else if (!strcasecmp(v->value, "ss7")) {
17203                confp->chan.sig = SIG_SS7;
17204 #endif   /* defined(HAVE_SS7) */
17205 #ifdef HAVE_OPENR2
17206             } else if (!strcasecmp(v->value, "mfcr2")) {
17207                confp->chan.sig = SIG_MFCR2;
17208 #endif
17209             } else if (!strcasecmp(v->value, "auto")) {
17210                confp->is_sig_auto = 1;
17211             } else {
17212                confp->chan.outsigmod = orig_outsigmod;
17213                confp->chan.radio = orig_radio;
17214                confp->is_sig_auto = orig_auto;
17215                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17216             }
17217           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17218             if (!strcasecmp(v->value, "em")) {
17219                confp->chan.outsigmod = SIG_EM;
17220             } else if (!strcasecmp(v->value, "em_e1")) {
17221                confp->chan.outsigmod = SIG_EM_E1;
17222             } else if (!strcasecmp(v->value, "em_w")) {
17223                confp->chan.outsigmod = SIG_EMWINK;
17224             } else if (!strcasecmp(v->value, "sf")) {
17225                confp->chan.outsigmod = SIG_SF;
17226             } else if (!strcasecmp(v->value, "sf_w")) {
17227                confp->chan.outsigmod = SIG_SFWINK;
17228             } else if (!strcasecmp(v->value, "sf_featd")) {
17229                confp->chan.outsigmod = SIG_FEATD;
17230             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17231                confp->chan.outsigmod = SIG_FEATDMF;
17232             } else if (!strcasecmp(v->value, "sf_featb")) {
17233                confp->chan.outsigmod = SIG_SF_FEATB;
17234             } else if (!strcasecmp(v->value, "sf")) {
17235                confp->chan.outsigmod = SIG_SF;
17236             } else if (!strcasecmp(v->value, "featd")) {
17237                confp->chan.outsigmod = SIG_FEATD;
17238             } else if (!strcasecmp(v->value, "featdmf")) {
17239                confp->chan.outsigmod = SIG_FEATDMF;
17240             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17241                confp->chan.outsigmod = SIG_FEATDMF_TA;
17242             } else if (!strcasecmp(v->value, "e911")) {
17243                confp->chan.outsigmod = SIG_E911;
17244             } else if (!strcasecmp(v->value, "fgccama")) {
17245                confp->chan.outsigmod = SIG_FGC_CAMA;
17246             } else if (!strcasecmp(v->value, "fgccamamf")) {
17247                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17248             } else if (!strcasecmp(v->value, "featb")) {
17249                confp->chan.outsigmod = SIG_FEATB;
17250             } else {
17251                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17252             }
17253 #ifdef HAVE_PRI
17254          } else if (!strcasecmp(v->name, "pridialplan")) {
17255             if (!strcasecmp(v->value, "national")) {
17256                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17257             } else if (!strcasecmp(v->value, "unknown")) {
17258                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17259             } else if (!strcasecmp(v->value, "private")) {
17260                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17261             } else if (!strcasecmp(v->value, "international")) {
17262                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17263             } else if (!strcasecmp(v->value, "local")) {
17264                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17265             } else if (!strcasecmp(v->value, "dynamic")) {
17266                confp->pri.pri.dialplan = -1;
17267             } else if (!strcasecmp(v->value, "redundant")) {
17268                confp->pri.pri.dialplan = -2;
17269             } else {
17270                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17271             }
17272          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17273             if (!strcasecmp(v->value, "national")) {
17274                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17275             } else if (!strcasecmp(v->value, "unknown")) {
17276                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17277             } else if (!strcasecmp(v->value, "private")) {
17278                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17279             } else if (!strcasecmp(v->value, "international")) {
17280                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17281             } else if (!strcasecmp(v->value, "local")) {
17282                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17283             } else if (!strcasecmp(v->value, "dynamic")) {
17284                confp->pri.pri.localdialplan = -1;
17285             } else if (!strcasecmp(v->value, "redundant")) {
17286                confp->pri.pri.localdialplan = -2;
17287             } else {
17288                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17289             }
17290          } else if (!strcasecmp(v->name, "switchtype")) {
17291             if (!strcasecmp(v->value, "national"))
17292                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17293             else if (!strcasecmp(v->value, "ni1"))
17294                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17295             else if (!strcasecmp(v->value, "dms100"))
17296                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17297             else if (!strcasecmp(v->value, "4ess"))
17298                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17299             else if (!strcasecmp(v->value, "5ess"))
17300                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17301             else if (!strcasecmp(v->value, "euroisdn"))
17302                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17303             else if (!strcasecmp(v->value, "qsig"))
17304                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17305             else {
17306                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17307                return -1;
17308             }
17309          } else if (!strcasecmp(v->name, "msn")) {
17310             ast_copy_string(confp->pri.pri.msn_list, v->value,
17311                sizeof(confp->pri.pri.msn_list));
17312          } else if (!strcasecmp(v->name, "nsf")) {
17313             if (!strcasecmp(v->value, "sdn"))
17314                confp->pri.pri.nsf = PRI_NSF_SDN;
17315             else if (!strcasecmp(v->value, "megacom"))
17316                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17317             else if (!strcasecmp(v->value, "tollfreemegacom"))
17318                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17319             else if (!strcasecmp(v->value, "accunet"))
17320                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17321             else if (!strcasecmp(v->value, "none"))
17322                confp->pri.pri.nsf = PRI_NSF_NONE;
17323             else {
17324                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17325                confp->pri.pri.nsf = PRI_NSF_NONE;
17326             }
17327          } else if (!strcasecmp(v->name, "priindication")) {
17328             if (!strcasecmp(v->value, "outofband"))
17329                confp->chan.priindication_oob = 1;
17330             else if (!strcasecmp(v->value, "inband"))
17331                confp->chan.priindication_oob = 0;
17332             else
17333                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17334                   v->value, v->lineno);
17335          } else if (!strcasecmp(v->name, "priexclusive")) {
17336             confp->chan.priexclusive = ast_true(v->value);
17337          } else if (!strcasecmp(v->name, "internationalprefix")) {
17338             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17339          } else if (!strcasecmp(v->name, "nationalprefix")) {
17340             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17341          } else if (!strcasecmp(v->name, "localprefix")) {
17342             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17343          } else if (!strcasecmp(v->name, "privateprefix")) {
17344             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17345          } else if (!strcasecmp(v->name, "unknownprefix")) {
17346             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17347          } else if (!strcasecmp(v->name, "resetinterval")) {
17348             if (!strcasecmp(v->value, "never"))
17349                confp->pri.pri.resetinterval = -1;
17350             else if (atoi(v->value) >= 60)
17351                confp->pri.pri.resetinterval = atoi(v->value);
17352             else
17353                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17354                   v->value, v->lineno);
17355          } else if (!strcasecmp(v->name, "minunused")) {
17356             confp->pri.pri.minunused = atoi(v->value);
17357          } else if (!strcasecmp(v->name, "minidle")) {
17358             confp->pri.pri.minidle = atoi(v->value);
17359          } else if (!strcasecmp(v->name, "idleext")) {
17360             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17361          } else if (!strcasecmp(v->name, "idledial")) {
17362             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17363          } else if (!strcasecmp(v->name, "overlapdial")) {
17364             if (ast_true(v->value)) {
17365                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17366             } else if (!strcasecmp(v->value, "incoming")) {
17367                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17368             } else if (!strcasecmp(v->value, "outgoing")) {
17369                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17370             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17371                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17372             } else {
17373                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17374             }
17375 #ifdef HAVE_PRI_PROG_W_CAUSE
17376          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17377             if (!strcasecmp(v->value, "logical")) {
17378                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17379             } else if (!strcasecmp(v->value, "physical")) {
17380                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17381             } else {
17382                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17383             }
17384 #endif
17385          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17386             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17387 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17388          } else if (!strcasecmp(v->name, "service_message_support")) {
17389             /* assuming switchtype for this channel group has been configured already */
17390             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17391                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17392                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17393                confp->pri.pri.enable_service_message_support = 1;
17394             } else {
17395                confp->pri.pri.enable_service_message_support = 0;
17396             }
17397 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17398 #ifdef HAVE_PRI_INBANDDISCONNECT
17399          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17400             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17401 #endif
17402          } else if (!strcasecmp(v->name, "pritimer")) {
17403 #ifdef PRI_GETSET_TIMERS
17404             char tmp[20];
17405             char *timerc;
17406             char *c;
17407             int timer;
17408             int timeridx;
17409 
17410             ast_copy_string(tmp, v->value, sizeof(tmp));
17411             c = tmp;
17412             timerc = strsep(&c, ",");
17413             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17414                timeridx = pri_timer2idx(timerc);
17415                timer = atoi(c);
17416                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17417                   ast_log(LOG_WARNING,
17418                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17419                      v->lineno);
17420                } else if (!timer) {
17421                   ast_log(LOG_WARNING,
17422                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17423                      c, timerc, v->lineno);
17424                } else {
17425                   confp->pri.pri.pritimers[timeridx] = timer;
17426                }
17427             } else {
17428                ast_log(LOG_WARNING,
17429                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17430                   v->value, v->lineno);
17431             }
17432 #endif /* PRI_GETSET_TIMERS */
17433          } else if (!strcasecmp(v->name, "facilityenable")) {
17434             confp->pri.pri.facilityenable = ast_true(v->value);
17435 #if defined(HAVE_PRI_AOC_EVENTS)
17436          } else if (!strcasecmp(v->name, "aoc_enable")) {
17437             confp->pri.pri.aoc_passthrough_flag = 0;
17438             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17439                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17440             }
17441             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17442                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17443             }
17444             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17445                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17446             }
17447          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17448             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17449 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17450 #if defined(HAVE_PRI_CALL_HOLD)
17451          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17452             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17453 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17454 #if defined(HAVE_PRI_CCSS)
17455          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17456             if (!strcasecmp(v->value, "global")) {
17457                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17458             } else if (!strcasecmp(v->value, "specific")) {
17459                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17460             } else {
17461                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17462             }
17463          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17464             if (!strcasecmp(v->value, "release")) {
17465                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17466             } else if (!strcasecmp(v->value, "retain")) {
17467                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17468             } else if (!strcasecmp(v->value, "do_not_care")) {
17469                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17470             } else {
17471                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17472             }
17473          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17474             if (!strcasecmp(v->value, "release")) {
17475                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17476             } else if (!strcasecmp(v->value, "retain")) {
17477                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17478             } else {
17479                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17480             }
17481 #endif   /* defined(HAVE_PRI_CCSS) */
17482 #if defined(HAVE_PRI_CALL_WAITING)
17483          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17484             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17485             if (confp->pri.pri.max_call_waiting_calls < 0) {
17486                /* Negative values are not allowed. */
17487                confp->pri.pri.max_call_waiting_calls = 0;
17488             }
17489          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17490             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17491 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17492 #if defined(HAVE_PRI_MWI)
17493          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17494             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17495                sizeof(confp->pri.pri.mwi_mailboxes));
17496 #endif   /* defined(HAVE_PRI_MWI) */
17497          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17498             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17499 #if defined(HAVE_PRI_L2_PERSISTENCE)
17500          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17501             if (!strcasecmp(v->value, "keep_up")) {
17502                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17503             } else if (!strcasecmp(v->value, "leave_down")) {
17504                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17505             } else {
17506                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17507             }
17508 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17509 #endif /* HAVE_PRI */
17510 #if defined(HAVE_SS7)
17511          } else if (!strcasecmp(v->name, "ss7type")) {
17512             if (!strcasecmp(v->value, "itu")) {
17513                cur_ss7type = SS7_ITU;
17514             } else if (!strcasecmp(v->value, "ansi")) {
17515                cur_ss7type = SS7_ANSI;
17516             } else
17517                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17518          } else if (!strcasecmp(v->name, "linkset")) {
17519             cur_linkset = atoi(v->value);
17520          } else if (!strcasecmp(v->name, "pointcode")) {
17521             cur_pointcode = parse_pointcode(v->value);
17522          } else if (!strcasecmp(v->name, "adjpointcode")) {
17523             cur_adjpointcode = parse_pointcode(v->value);
17524          } else if (!strcasecmp(v->name, "defaultdpc")) {
17525             cur_defaultdpc = parse_pointcode(v->value);
17526          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17527             cur_cicbeginswith = atoi(v->value);
17528          } else if (!strcasecmp(v->name, "networkindicator")) {
17529             if (!strcasecmp(v->value, "national"))
17530                cur_networkindicator = SS7_NI_NAT;
17531             else if (!strcasecmp(v->value, "national_spare"))
17532                cur_networkindicator = SS7_NI_NAT_SPARE;
17533             else if (!strcasecmp(v->value, "international"))
17534                cur_networkindicator = SS7_NI_INT;
17535             else if (!strcasecmp(v->value, "international_spare"))
17536                cur_networkindicator = SS7_NI_INT_SPARE;
17537             else
17538                cur_networkindicator = -1;
17539          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17540             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17541          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17542             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17543          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17544             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17545          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17546             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17547          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17548             if (!strcasecmp(v->value, "national")) {
17549                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17550             } else if (!strcasecmp(v->value, "international")) {
17551                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17552             } else if (!strcasecmp(v->value, "subscriber")) {
17553                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17554             } else if (!strcasecmp(v->value, "unknown")) {
17555                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17556             } else if (!strcasecmp(v->value, "dynamic")) {
17557                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17558             } else {
17559                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17560             }
17561          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17562             if (!strcasecmp(v->value, "national")) {
17563                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17564             } else if (!strcasecmp(v->value, "international")) {
17565                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17566             } else if (!strcasecmp(v->value, "subscriber")) {
17567                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17568             } else if (!strcasecmp(v->value, "unknown")) {
17569                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17570             } else if (!strcasecmp(v->value, "dynamic")) {
17571                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17572             } else {
17573                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17574             }
17575          } else if (!strcasecmp(v->name, "sigchan")) {
17576             int sigchan, res;
17577             sigchan = atoi(v->value);
17578             res = linkset_addsigchan(sigchan);
17579             if (res < 0)
17580                return -1;
17581 
17582          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17583             struct dahdi_ss7 *link;
17584             link = ss7_resolve_linkset(cur_linkset);
17585             if (!link) {
17586                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17587                return -1;
17588             }
17589             if (ast_true(v->value))
17590                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17591 #endif   /* defined(HAVE_SS7) */
17592 #ifdef HAVE_OPENR2
17593          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17594             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17595             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);
17596          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17597             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17598          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17599             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17600             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17601                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17602                confp->mfcr2.variant = OR2_VAR_ITU;
17603             }
17604          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17605             confp->mfcr2.mfback_timeout = atoi(v->value);
17606             if (!confp->mfcr2.mfback_timeout) {
17607                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17608                confp->mfcr2.mfback_timeout = -1;
17609             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17610                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17611             }
17612          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17613             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17614             if (confp->mfcr2.metering_pulse_timeout > 500) {
17615                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17616             }
17617          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17618             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17619          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17620             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17621          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17622             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17623          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17624             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17625          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17626             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17627          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17628             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17629          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17630             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17631 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17632          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17633             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17634 #endif
17635          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17636             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17637          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17638             confp->mfcr2.max_ani = atoi(v->value);
17639             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17640                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17641             }
17642          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17643             confp->mfcr2.max_dnis = atoi(v->value);
17644             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17645                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17646             }
17647          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17648             confp->mfcr2.category = openr2_proto_get_category(v->value);
17649             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17650                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17651                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17652                      v->value, v->lineno);
17653             }
17654          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17655             openr2_log_level_t tmplevel;
17656             char *clevel;
17657             char *logval = ast_strdupa(v->value);
17658             while (logval) {
17659                clevel = strsep(&logval,",");
17660                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17661                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17662                   continue;
17663                }
17664                confp->mfcr2.loglevel |= tmplevel;
17665             }
17666 #endif /* HAVE_OPENR2 */
17667          } else if (!strcasecmp(v->name, "cadence")) {
17668             /* setup to scan our argument */
17669             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17670             int i;
17671             struct dahdi_ring_cadence new_cadence;
17672             int cid_location = -1;
17673             int firstcadencepos = 0;
17674             char original_args[80];
17675             int cadence_is_ok = 1;
17676 
17677             ast_copy_string(original_args, v->value, sizeof(original_args));
17678             /* 16 cadences allowed (8 pairs) */
17679             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]);
17680 
17681             /* Cadence must be even (on/off) */
17682             if (element_count % 2 == 1) {
17683                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17684                cadence_is_ok = 0;
17685             }
17686 
17687             /* Ring cadences cannot be negative */
17688             for (i = 0; i < element_count; i++) {
17689                if (c[i] == 0) {
17690                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17691                   cadence_is_ok = 0;
17692                   break;
17693                } else if (c[i] < 0) {
17694                   if (i % 2 == 1) {
17695                      /* Silence duration, negative possibly okay */
17696                      if (cid_location == -1) {
17697                         cid_location = i;
17698                         c[i] *= -1;
17699                      } else {
17700                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17701                         cadence_is_ok = 0;
17702                         break;
17703                      }
17704                   } else {
17705                      if (firstcadencepos == 0) {
17706                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17707                                  /* duration will be passed negative to the DAHDI driver */
17708                      } else {
17709                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17710                         cadence_is_ok = 0;
17711                         break;
17712                      }
17713                   }
17714                }
17715             }
17716 
17717             /* Substitute our scanned cadence */
17718             for (i = 0; i < 16; i++) {
17719                new_cadence.ringcadence[i] = c[i];
17720             }
17721 
17722             if (cadence_is_ok) {
17723                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17724                if (element_count < 2) {
17725                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17726                } else {
17727                   if (cid_location == -1) {
17728                      /* user didn't say; default to first pause */
17729                      cid_location = 1;
17730                   } else {
17731                      /* convert element_index to cidrings value */
17732                      cid_location = (cid_location + 1) / 2;
17733                   }
17734                   /* ---we like their cadence; try to install it--- */
17735                   if (!user_has_defined_cadences++)
17736                      /* this is the first user-defined cadence; clear the default user cadences */
17737                      num_cadence = 0;
17738                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17739                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17740                   else {
17741                      cadences[num_cadence] = new_cadence;
17742                      cidrings[num_cadence++] = cid_location;
17743                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17744                   }
17745                }
17746             }
17747          } else if (!strcasecmp(v->name, "ringtimeout")) {
17748             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17749          } else if (!strcasecmp(v->name, "prewink")) {
17750             confp->timing.prewinktime = atoi(v->value);
17751          } else if (!strcasecmp(v->name, "preflash")) {
17752             confp->timing.preflashtime = atoi(v->value);
17753          } else if (!strcasecmp(v->name, "wink")) {
17754             confp->timing.winktime = atoi(v->value);
17755          } else if (!strcasecmp(v->name, "flash")) {
17756             confp->timing.flashtime = atoi(v->value);
17757          } else if (!strcasecmp(v->name, "start")) {
17758             confp->timing.starttime = atoi(v->value);
17759          } else if (!strcasecmp(v->name, "rxwink")) {
17760             confp->timing.rxwinktime = atoi(v->value);
17761          } else if (!strcasecmp(v->name, "rxflash")) {
17762             confp->timing.rxflashtime = atoi(v->value);
17763          } else if (!strcasecmp(v->name, "debounce")) {
17764             confp->timing.debouncetime = atoi(v->value);
17765          } else if (!strcasecmp(v->name, "toneduration")) {
17766             int toneduration;
17767             int ctlfd;
17768             int res;
17769             struct dahdi_dialparams dps;
17770 
17771             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17772             if (ctlfd == -1) {
17773                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17774                return -1;
17775             }
17776 
17777             toneduration = atoi(v->value);
17778             if (toneduration > -1) {
17779                memset(&dps, 0, sizeof(dps));
17780 
17781                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17782                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17783                if (res < 0) {
17784                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17785                   close(ctlfd);
17786                   return -1;
17787                }
17788             }
17789             close(ctlfd);
17790          } else if (!strcasecmp(v->name, "defaultcic")) {
17791             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17792          } else if (!strcasecmp(v->name, "defaultozz")) {
17793             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17794          } else if (!strcasecmp(v->name, "mwilevel")) {
17795             mwilevel = atoi(v->value);
17796          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17797             dtmfcid_level = atoi(v->value);
17798          } else if (!strcasecmp(v->name, "reportalarms")) {
17799             if (!strcasecmp(v->value, "all"))
17800                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17801             if (!strcasecmp(v->value, "none"))
17802                report_alarms = 0;
17803             else if (!strcasecmp(v->value, "channels"))
17804                report_alarms = REPORT_CHANNEL_ALARMS;
17805             else if (!strcasecmp(v->value, "spans"))
17806                report_alarms = REPORT_SPAN_ALARMS;
17807           }
17808       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17809          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17810    }
17811 
17812    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
17813    if (confp->chan.vars) {
17814       ast_variables_destroy(confp->chan.vars);
17815       confp->chan.vars = NULL;
17816    }
17817 
17818    if (dahdichan) {
17819       /* Process the deferred dahdichan value. */
17820       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17821          &found_pseudo)) {
17822          if (confp->ignore_failed_channels) {
17823             ast_log(LOG_WARNING,
17824                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17825                dahdichan->value);
17826          } else {
17827             return -1;
17828          }
17829       }
17830    }
17831 
17832    /* mark the first channels of each DAHDI span to watch for their span alarms */
17833    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17834       if (!tmp->destroy && tmp->span != y) {
17835          tmp->manages_span_alarms = 1;
17836          y = tmp->span; 
17837       } else {
17838          tmp->manages_span_alarms = 0;
17839       }
17840    }
17841 
17842    /*< \todo why check for the pseudo in the per-channel section.
17843     * Any actual use for manual setup of the pseudo channel? */
17844    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17845       /* use the default configuration for a channel, so
17846          that any settings from real configured channels
17847          don't "leak" into the pseudo channel config
17848       */
17849       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17850 
17851       if (conf.chan.cc_params) {
17852          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17853       } else {
17854          tmp = NULL;
17855       }
17856       if (tmp) {
17857          ast_verb(3, "Automatically generated pseudo channel\n");
17858       } else {
17859          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17860       }
17861       ast_cc_config_params_destroy(conf.chan.cc_params);
17862    }
17863    return 0;
17864 }
17865 
17866 /*!
17867  * \internal
17868  * \brief Deep copy struct dahdi_chan_conf.
17869  * \since 1.8
17870  *
17871  * \param dest Destination.
17872  * \param src Source.
17873  *
17874  * \return Nothing
17875  */
17876 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17877 {
17878    struct ast_cc_config_params *cc_params;
17879 
17880    cc_params = dest->chan.cc_params;
17881    *dest = *src;
17882    dest->chan.cc_params = cc_params;
17883    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17884 }
17885 
17886 /*!
17887  * \internal
17888  * \brief Setup DAHDI channel driver.
17889  *
17890  * \param reload enum: load_module(0), reload(1), restart(2).
17891  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
17892  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
17893  * \param conf Local config parameters.  So cc_params can be properly destroyed.
17894  *
17895  * \retval 0 on success.
17896  * \retval -1 on error.
17897  */
17898 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17899 {
17900    struct ast_config *cfg;
17901    struct ast_config *ucfg;
17902    struct ast_variable *v;
17903    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17904    const char *chans;
17905    const char *cat;
17906    int res;
17907 
17908 #ifdef HAVE_PRI
17909    char *c;
17910    int spanno;
17911    int i;
17912    int logicalspan;
17913    int trunkgroup;
17914    int dchannels[SIG_PRI_NUM_DCHANS];
17915 #endif
17916    int have_cfg_now;
17917    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
17918 
17919    cfg = ast_config_load(config, config_flags);
17920    have_cfg_now = !!cfg;
17921    if (!cfg) {
17922       /* Error if we have no config file */
17923       if (had_cfg_before) {
17924          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17925          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17926       }
17927       cfg = ast_config_new();/* Dummy config */
17928       if (!cfg) {
17929          return 0;
17930       }
17931       ucfg = ast_config_load("users.conf", config_flags);
17932       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17933          ast_config_destroy(cfg);
17934          return 0;
17935       }
17936       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17937          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17938          ast_config_destroy(cfg);
17939          return 0;
17940       }
17941    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17942       ucfg = ast_config_load("users.conf", config_flags);
17943       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17944          return 0;
17945       }
17946       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17947          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17948          return 0;
17949       }
17950       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17951       cfg = ast_config_load(config, config_flags);
17952       have_cfg_now = !!cfg;
17953       if (!cfg) {
17954          if (had_cfg_before) {
17955             /* We should have been able to load the config. */
17956             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
17957             ast_config_destroy(ucfg);
17958             return 0;
17959          }
17960          cfg = ast_config_new();/* Dummy config */
17961          if (!cfg) {
17962             ast_config_destroy(ucfg);
17963             return 0;
17964          }
17965       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17966          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17967          ast_config_destroy(ucfg);
17968          return 0;
17969       }
17970    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17971       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17972       return 0;
17973    } else {
17974       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17975       ucfg = ast_config_load("users.conf", config_flags);
17976       if (ucfg == CONFIG_STATUS_FILEINVALID) {
17977          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17978          ast_config_destroy(cfg);
17979          return 0;
17980       }
17981    }
17982    had_cfg_before = have_cfg_now;
17983 
17984    /* It's a little silly to lock it, but we might as well just to be sure */
17985    ast_mutex_lock(&iflock);
17986 #ifdef HAVE_PRI
17987    if (reload != 1) {
17988       /* Process trunkgroups first */
17989       v = ast_variable_browse(cfg, "trunkgroups");
17990       while (v) {
17991          if (!strcasecmp(v->name, "trunkgroup")) {
17992             trunkgroup = atoi(v->value);
17993             if (trunkgroup > 0) {
17994                if ((c = strchr(v->value, ','))) {
17995                   i = 0;
17996                   memset(dchannels, 0, sizeof(dchannels));
17997                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
17998                      dchannels[i] = atoi(c + 1);
17999                      if (dchannels[i] < 0) {
18000                         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);
18001                      } else
18002                         i++;
18003                      c = strchr(c + 1, ',');
18004                   }
18005                   if (i) {
18006                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18007                         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);
18008                   } else
18009                         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");
18010                   } else
18011                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18012                } else
18013                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18014             } else
18015                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18016          } else if (!strcasecmp(v->name, "spanmap")) {
18017             spanno = atoi(v->value);
18018             if (spanno > 0) {
18019                if ((c = strchr(v->value, ','))) {
18020                   trunkgroup = atoi(c + 1);
18021                   if (trunkgroup > 0) {
18022                      if ((c = strchr(c + 1, ',')))
18023                         logicalspan = atoi(c + 1);
18024                      else
18025                         logicalspan = 0;
18026                      if (logicalspan >= 0) {
18027                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18028                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18029                      } else
18030                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18031                      } else
18032                         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);
18033                   } else
18034                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18035                } else
18036                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18037             } else
18038                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18039          } else {
18040             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18041          }
18042          v = v->next;
18043       }
18044    }
18045 #endif
18046 
18047    /* Copy the default jb config over global_jbconf */
18048    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18049 
18050    mwimonitornotify[0] = '\0';
18051 
18052    v = ast_variable_browse(cfg, "channels");
18053    if ((res = process_dahdi(base_conf,
18054       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18055       v, reload, 0))) {
18056       ast_mutex_unlock(&iflock);
18057       ast_config_destroy(cfg);
18058       if (ucfg) {
18059          ast_config_destroy(ucfg);
18060       }
18061       return res;
18062    }
18063 
18064    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18065    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18066       /* [channels] and [trunkgroups] are used. Let's also reserve
18067        * [globals] and [general] for future use
18068        */
18069       if (!strcasecmp(cat, "general") ||
18070          !strcasecmp(cat, "trunkgroups") ||
18071          !strcasecmp(cat, "globals") ||
18072          !strcasecmp(cat, "channels")) {
18073          continue;
18074       }
18075 
18076       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18077       if (ast_strlen_zero(chans)) {
18078          /* Section is useless without a dahdichan value present. */
18079          continue;
18080       }
18081 
18082       /* Copy base_conf to conf. */
18083       deep_copy_dahdi_chan_conf(conf, base_conf);
18084 
18085       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18086          ast_mutex_unlock(&iflock);
18087          ast_config_destroy(cfg);
18088          if (ucfg) {
18089             ast_config_destroy(ucfg);
18090          }
18091          return res;
18092       }
18093    }
18094 
18095    ast_config_destroy(cfg);
18096 
18097    if (ucfg) {
18098       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18099       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18100       process_dahdi(base_conf,
18101          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18102          ast_variable_browse(ucfg, "general"), 1, 0);
18103 
18104       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18105          if (!strcasecmp(cat, "general")) {
18106             continue;
18107          }
18108 
18109          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18110          if (ast_strlen_zero(chans)) {
18111             /* Section is useless without a dahdichan value present. */
18112             continue;
18113          }
18114 
18115          /* Copy base_conf to conf. */
18116          deep_copy_dahdi_chan_conf(conf, base_conf);
18117 
18118          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18119             ast_config_destroy(ucfg);
18120             ast_mutex_unlock(&iflock);
18121             return res;
18122          }
18123       }
18124       ast_config_destroy(ucfg);
18125    }
18126    ast_mutex_unlock(&iflock);
18127 
18128 #ifdef HAVE_PRI
18129    if (reload != 1) {
18130       int x;
18131       for (x = 0; x < NUM_SPANS; x++) {
18132          if (pris[x].pri.pvts[0]) {
18133             prepare_pri(pris + x);
18134             if (sig_pri_start_pri(&pris[x].pri)) {
18135                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18136                return -1;
18137             } else
18138                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18139          }
18140       }
18141    }
18142 #endif
18143 #if defined(HAVE_SS7)
18144    if (reload != 1) {
18145       int x;
18146       for (x = 0; x < NUM_SPANS; x++) {
18147          if (linksets[x].ss7.ss7) {
18148             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18149             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18150                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18151                return -1;
18152             } else
18153                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18154          }
18155       }
18156    }
18157 #endif   /* defined(HAVE_SS7) */
18158 #ifdef HAVE_OPENR2
18159    if (reload != 1) {
18160       int x;
18161       for (x = 0; x < r2links_count; x++) {
18162          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18163             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18164             return -1;
18165          } else {
18166             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18167          }
18168       }
18169    }
18170 #endif
18171    /* And start the monitor for the first time */
18172    restart_monitor();
18173    return 0;
18174 }
18175 
18176 /*!
18177  * \internal
18178  * \brief Setup DAHDI channel driver.
18179  *
18180  * \param reload enum: load_module(0), reload(1), restart(2).
18181  *
18182  * \retval 0 on success.
18183  * \retval -1 on error.
18184  */
18185 static int setup_dahdi(int reload)
18186 {
18187    int res;
18188    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18189    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18190    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18191 
18192    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18193       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18194    } else {
18195       res = -1;
18196    }
18197    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18198    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18199    ast_cc_config_params_destroy(conf.chan.cc_params);
18200 
18201    return res;
18202 }
18203 
18204 /*!
18205  * \internal
18206  * \brief Callback used to generate the dahdi status tree.
18207  * \param[in] search The search pattern tree.
18208  * \retval NULL on error.
18209  * \retval non-NULL The generated tree.
18210  */
18211 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18212       struct ast_data *data_root)
18213 {
18214    int ctl, res, span;
18215    struct ast_data *data_span, *data_alarms;
18216    struct dahdi_spaninfo s;
18217 
18218    ctl = open("/dev/dahdi/ctl", O_RDWR);
18219    if (ctl < 0) {
18220       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18221       return -1;
18222    }
18223    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18224       s.spanno = span;
18225       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18226       if (res) {
18227          continue;
18228       }
18229 
18230       data_span = ast_data_add_node(data_root, "span");
18231       if (!data_span) {
18232          continue;
18233       }
18234       ast_data_add_str(data_span, "description", s.desc);
18235 
18236       /* insert the alarms status */
18237       data_alarms = ast_data_add_node(data_span, "alarms");
18238       if (!data_alarms) {
18239          continue;
18240       }
18241 
18242       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18243       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18244       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18245       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18246       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18247       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18248 
18249       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18250       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18251       ast_data_add_int(data_span, "crc4", s.crc4count);
18252       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18253                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18254                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18255                      "CAS");
18256       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18257                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18258                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18259                      "Unknown");
18260       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18261                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18262                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18263       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18264 
18265       /* if this span doesn't match remove it. */
18266       if (!ast_data_search_match(search, data_span)) {
18267          ast_data_remove_node(data_root, data_span);
18268       }
18269    }
18270    close(ctl);
18271 
18272    return 0;
18273 }
18274 
18275 /*!
18276  * \internal
18277  * \brief Callback used to generate the dahdi channels tree.
18278  * \param[in] search The search pattern tree.
18279  * \retval NULL on error.
18280  * \retval non-NULL The generated tree.
18281  */
18282 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18283       struct ast_data *data_root)
18284 {
18285    struct dahdi_pvt *tmp;
18286    struct ast_data *data_channel;
18287 
18288    ast_mutex_lock(&iflock);
18289    for (tmp = iflist; tmp; tmp = tmp->next) {
18290       data_channel = ast_data_add_node(data_root, "channel");
18291       if (!data_channel) {
18292          continue;
18293       }
18294 
18295       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18296 
18297       /* if this channel doesn't match remove it. */
18298       if (!ast_data_search_match(search, data_channel)) {
18299          ast_data_remove_node(data_root, data_channel);
18300       }
18301    }
18302    ast_mutex_unlock(&iflock);
18303 
18304    return 0;
18305 }
18306 
18307 /*!
18308  * \internal
18309  * \brief Callback used to generate the dahdi channels tree.
18310  * \param[in] search The search pattern tree.
18311  * \retval NULL on error.
18312  * \retval non-NULL The generated tree.
18313  */
18314 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18315       struct ast_data *data_root)
18316 {
18317    int pseudo_fd = -1;
18318    struct dahdi_versioninfo vi = {
18319       .version = "Unknown",
18320       .echo_canceller = "Unknown"
18321    };
18322 
18323    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18324       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18325       return -1;
18326    }
18327 
18328    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18329       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18330    }
18331 
18332    close(pseudo_fd);
18333 
18334    ast_data_add_str(data_root, "value", vi.version);
18335    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18336 
18337    return 0;
18338 }
18339 
18340 static const struct ast_data_handler dahdi_status_data_provider = {
18341    .version = AST_DATA_HANDLER_VERSION,
18342    .get = dahdi_status_data_provider_get
18343 };
18344 
18345 static const struct ast_data_handler dahdi_channels_data_provider = {
18346    .version = AST_DATA_HANDLER_VERSION,
18347    .get = dahdi_channels_data_provider_get
18348 };
18349 
18350 static const struct ast_data_handler dahdi_version_data_provider = {
18351    .version = AST_DATA_HANDLER_VERSION,
18352    .get = dahdi_version_data_provider_get
18353 };
18354 
18355 static const struct ast_data_entry dahdi_data_providers[] = {
18356    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18357    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18358    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18359 };
18360 
18361 static int load_module(void)
18362 {
18363    int res;
18364 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18365    int y;
18366 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18367 
18368 #ifdef HAVE_PRI
18369    memset(pris, 0, sizeof(pris));
18370    for (y = 0; y < NUM_SPANS; y++) {
18371       sig_pri_init_pri(&pris[y].pri);
18372    }
18373    pri_set_error(dahdi_pri_error);
18374    pri_set_message(dahdi_pri_message);
18375    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18376 #ifdef HAVE_PRI_PROG_W_CAUSE
18377    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18378 #endif
18379 #if defined(HAVE_PRI_CCSS)
18380    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18381       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18382       __unload_module();
18383       return AST_MODULE_LOAD_FAILURE;
18384    }
18385 #endif   /* defined(HAVE_PRI_CCSS) */
18386    if (sig_pri_load(
18387 #if defined(HAVE_PRI_CCSS)
18388       dahdi_pri_cc_type
18389 #else
18390       NULL
18391 #endif   /* defined(HAVE_PRI_CCSS) */
18392       )) {
18393       __unload_module();
18394       return AST_MODULE_LOAD_FAILURE;
18395    }
18396 #endif
18397 #if defined(HAVE_SS7)
18398    memset(linksets, 0, sizeof(linksets));
18399    for (y = 0; y < NUM_SPANS; y++) {
18400       sig_ss7_init_linkset(&linksets[y].ss7);
18401    }
18402    ss7_set_error(dahdi_ss7_error);
18403    ss7_set_message(dahdi_ss7_message);
18404 #endif   /* defined(HAVE_SS7) */
18405    res = setup_dahdi(0);
18406    /* Make sure we can register our DAHDI channel type */
18407    if (res)
18408       return AST_MODULE_LOAD_DECLINE;
18409    if (ast_channel_register(&dahdi_tech)) {
18410       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18411       __unload_module();
18412       return AST_MODULE_LOAD_FAILURE;
18413    }
18414 #ifdef HAVE_PRI
18415    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18416 #endif
18417 #if defined(HAVE_SS7)
18418    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18419 #endif   /* defined(HAVE_SS7) */
18420 #ifdef HAVE_OPENR2
18421    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18422    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18423 #endif
18424 
18425    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18426    /* register all the data providers */
18427    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18428    memset(round_robin, 0, sizeof(round_robin));
18429    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18430    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18431    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18432    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18433    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18434    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18435    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18436 
18437    ast_cond_init(&ss_thread_complete, NULL);
18438 
18439    return res;
18440 }
18441 
18442 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18443 {
18444 #define  END_SILENCE_LEN 400
18445 #define  HEADER_MS 50
18446 #define  TRAILER_MS 5
18447 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18448 #define  ASCII_BYTES_PER_CHAR 80
18449 
18450    unsigned char *buf,*mybuf;
18451    struct dahdi_pvt *p = c->tech_pvt;
18452    struct pollfd fds[1];
18453    int size,res,fd,len,x;
18454    int bytes=0;
18455    /* Initial carrier (imaginary) */
18456    float cr = 1.0;
18457    float ci = 0.0;
18458    float scont = 0.0;
18459    int idx;
18460 
18461    idx = dahdi_get_index(c, p, 0);
18462    if (idx < 0) {
18463       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18464       return -1;
18465    }
18466    if (!text[0]) return(0); /* if nothing to send, don't */
18467    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18468    if (p->mate)
18469       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18470    else
18471       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18472    if (!buf)
18473       return -1;
18474    mybuf = buf;
18475    if (p->mate) {
18476       int codec = AST_LAW(p);
18477       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18478          PUT_CLID_MARKMS;
18479       }
18480       /* Put actual message */
18481       for (x = 0; text[x]; x++) {
18482          PUT_CLID(text[x]);
18483       }
18484       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18485          PUT_CLID_MARKMS;
18486       }
18487       len = bytes;
18488       buf = mybuf;
18489    } else {
18490       len = tdd_generate(p->tdd, buf, text);
18491       if (len < 1) {
18492          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18493          ast_free(mybuf);
18494          return -1;
18495       }
18496    }
18497    memset(buf + len, 0x7f, END_SILENCE_LEN);
18498    len += END_SILENCE_LEN;
18499    fd = p->subs[idx].dfd;
18500    while (len) {
18501       if (ast_check_hangup(c)) {
18502          ast_free(mybuf);
18503          return -1;
18504       }
18505       size = len;
18506       if (size > READ_SIZE)
18507          size = READ_SIZE;
18508       fds[0].fd = fd;
18509       fds[0].events = POLLOUT | POLLPRI;
18510       fds[0].revents = 0;
18511       res = poll(fds, 1, -1);
18512       if (!res) {
18513          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18514          continue;
18515       }
18516       /* if got exception */
18517       if (fds[0].revents & POLLPRI) {
18518          ast_free(mybuf);
18519          return -1;
18520       }
18521       if (!(fds[0].revents & POLLOUT)) {
18522          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18523          continue;
18524       }
18525       res = write(fd, buf, size);
18526       if (res != size) {
18527          if (res == -1) {
18528             ast_free(mybuf);
18529             return -1;
18530          }
18531          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18532          break;
18533       }
18534       len -= size;
18535       buf += size;
18536    }
18537    ast_free(mybuf);
18538    return(0);
18539 }
18540 
18541 
18542 static int reload(void)
18543 {
18544    int res = 0;
18545 
18546    res = setup_dahdi(1);
18547    if (res) {
18548       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18549       return -1;
18550    }
18551    return 0;
18552 }
18553 
18554 /* This is a workaround so that menuselect displays a proper description
18555  * AST_MODULE_INFO(, , "DAHDI Telephony"
18556  */
18557 
18558 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18559    .load = load_module,
18560    .unload = unload_module,
18561    .reload = reload,
18562    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18563       .nonoptreq = "res_smdi",
18564    );