Tue Aug 20 16:34:26 2013

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: 380572 $")
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 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif   /* defined(HAVE_PRI) */
00080 
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif   /* defined(HAVE_SS7) */
00087 
00088 #ifdef HAVE_OPENR2
00089 /* put this here until sig_mfcr2 comes along */
00090 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00091 #include <openr2.h>
00092 #endif
00093 
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128 
00129 /*** DOCUMENTATION
00130    <application name="DAHDISendKeypadFacility" language="en_US">
00131       <synopsis>
00132          Send digits out of band over a PRI.
00133       </synopsis>
00134       <syntax>
00135          <parameter name="digits" required="true" />
00136       </syntax>
00137       <description>
00138          <para>This application will send the given string of digits in a Keypad
00139          Facility IE over the current channel.</para>
00140       </description>
00141    </application>
00142    <application name="DAHDISendCallreroutingFacility" language="en_US">
00143       <synopsis>
00144          Send an ISDN call rerouting/deflection facility message.
00145       </synopsis>
00146       <syntax argsep=",">
00147          <parameter name="destination" required="true">
00148             <para>Destination number.</para>
00149          </parameter>
00150          <parameter name="original">
00151             <para>Original called number.</para>
00152          </parameter>
00153          <parameter name="reason">
00154             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00155          </parameter>
00156       </syntax>
00157       <description>
00158          <para>This application will send an ISDN switch specific call
00159          rerouting/deflection facility message over the current channel.
00160          Supported switches depend upon the version of libpri in use.</para>
00161       </description>
00162    </application>
00163    <application name="DAHDIAcceptR2Call" language="en_US">
00164       <synopsis>
00165          Accept an R2 call if its not already accepted (you still need to answer it)
00166       </synopsis>
00167       <syntax>
00168          <parameter name="charge" required="true">
00169             <para>Yes or No.</para>
00170             <para>Whether you want to accept the call with charge or without charge.</para>
00171          </parameter>
00172       </syntax>
00173       <description>
00174          <para>This application will Accept the R2 call either with charge or no charge.</para>
00175       </description>
00176    </application>
00177    <manager name="DAHDITransfer" language="en_US">
00178       <synopsis>
00179          Transfer DAHDI Channel.
00180       </synopsis>
00181       <syntax>
00182          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00183          <parameter name="DAHDIChannel" required="true">
00184             <para>DAHDI channel number to transfer.</para>
00185          </parameter>
00186       </syntax>
00187       <description>
00188          <para>Simulate a flash hook event by the user connected to the channel.</para>
00189          <note><para>Valid only for analog channels.</para></note>
00190       </description>
00191    </manager>
00192    <manager name="DAHDIHangup" language="en_US">
00193       <synopsis>
00194          Hangup DAHDI Channel.
00195       </synopsis>
00196       <syntax>
00197          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00198          <parameter name="DAHDIChannel" required="true">
00199             <para>DAHDI channel number to hangup.</para>
00200          </parameter>
00201       </syntax>
00202       <description>
00203          <para>Simulate an on-hook event by the user connected to the channel.</para>
00204          <note><para>Valid only for analog channels.</para></note>
00205       </description>
00206    </manager>
00207    <manager name="DAHDIDialOffhook" language="en_US">
00208       <synopsis>
00209          Dial over DAHDI channel while offhook.
00210       </synopsis>
00211       <syntax>
00212          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00213          <parameter name="DAHDIChannel" required="true">
00214             <para>DAHDI channel number to dial digits.</para>
00215          </parameter>
00216          <parameter name="Number" required="true">
00217             <para>Digits to dial.</para>
00218          </parameter>
00219       </syntax>
00220       <description>
00221          <para>Generate DTMF control frames to the bridged peer.</para>
00222       </description>
00223    </manager>
00224    <manager name="DAHDIDNDon" language="en_US">
00225       <synopsis>
00226          Toggle DAHDI channel Do Not Disturb status ON.
00227       </synopsis>
00228       <syntax>
00229          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00230          <parameter name="DAHDIChannel" required="true">
00231             <para>DAHDI channel number to set DND on.</para>
00232          </parameter>
00233       </syntax>
00234       <description>
00235          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00236          <note><para>Feature only supported by analog channels.</para></note>
00237       </description>
00238    </manager>
00239    <manager name="DAHDIDNDoff" language="en_US">
00240       <synopsis>
00241          Toggle DAHDI channel Do Not Disturb status OFF.
00242       </synopsis>
00243       <syntax>
00244          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00245          <parameter name="DAHDIChannel" required="true">
00246             <para>DAHDI channel number to set DND off.</para>
00247          </parameter>
00248       </syntax>
00249       <description>
00250          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00251          <note><para>Feature only supported by analog channels.</para></note>
00252       </description>
00253    </manager>
00254    <manager name="DAHDIShowChannels" language="en_US">
00255       <synopsis>
00256          Show status of DAHDI channels.
00257       </synopsis>
00258       <syntax>
00259          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00260          <parameter name="DAHDIChannel">
00261             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00262          </parameter>
00263       </syntax>
00264       <description>
00265          <para>Similar to the CLI command "dahdi show channels".</para>
00266       </description>
00267    </manager>
00268    <manager name="DAHDIRestart" language="en_US">
00269       <synopsis>
00270          Fully Restart DAHDI channels (terminates calls).
00271       </synopsis>
00272       <syntax>
00273          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00274       </syntax>
00275       <description>
00276          <para>Equivalent to the CLI command "dahdi restart".</para>
00277       </description>
00278    </manager>
00279  ***/
00280 
00281 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00282 
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293 
00294 /*! Global jitterbuffer configuration - by default, jb is disabled
00295  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298    .flags = 0,
00299    .max_size = 200,
00300    .resync_threshold = 1000,
00301    .impl = "fixed",
00302    .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305 
00306 /*!
00307  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00308  * the user hangs up to reset the state machine so ring works properly.
00309  * This is used to be able to support kewlstart by putting the zhone in
00310  * groundstart mode since their forward disconnect supervision is entirely
00311  * broken even though their documentation says it isn't and their support
00312  * is entirely unwilling to provide any assistance with their channel banks
00313  * even though their web site says they support their products for life.
00314  */
00315 /* #define ZHONE_HACK */
00316 
00317 /*! \brief Typically, how many rings before we should send Caller*ID */
00318 #define DEFAULT_CIDRINGS 1
00319 
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321 
00322 
00323 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00324 #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))
00325 
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328    " w/"
00329    #if defined(HAVE_PRI)
00330       "PRI"
00331    #endif   /* defined(HAVE_PRI) */
00332    #if defined(HAVE_SS7)
00333       #if defined(HAVE_PRI)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) */
00336       "SS7"
00337    #endif   /* defined(HAVE_SS7) */
00338    #if defined(HAVE_OPENR2)
00339       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340       " & "
00341       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00342       "MFC/R2"
00343    #endif   /* defined(HAVE_OPENR2) */
00344 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00345 ;
00346 
00347 static const char config[] = "chan_dahdi.conf";
00348 
00349 #define SIG_EM    DAHDI_SIG_EM
00350 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00354 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00357 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI      DAHDI_SIG_CLEAR
00365 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2    DAHDI_SIG_CAS
00369 #define  SIG_SF      DAHDI_SIG_SF
00370 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375 
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS       32
00380 #endif
00381 
00382 #define CHAN_PSEUDO  -2
00383 
00384 #define CALLPROGRESS_PROGRESS    1
00385 #define CALLPROGRESS_FAX_OUTGOING   2
00386 #define CALLPROGRESS_FAX_INCOMING   4
00387 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388 
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392 
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00395    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00396    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00397    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00398 };
00399 
00400 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00401  * is 1, the second pause is 2 and so on.
00402  */
00403 
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405    2,                            /*!< Right after first long ring */
00406    4,                            /*!< Right after long part */
00407    3,                            /*!< After third chirp */
00408    2,                            /*!< Second spell */
00409 };
00410 
00411 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413 
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416 
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00419 
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422 
00423 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int  mwisend_rpas = 0;
00427 #endif
00428 
00429 static char progzone[10] = "";
00430 
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433 
00434 static int numbufs = 4;
00435 
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438 
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS    2 
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442 
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447 
00448 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00449 static int firstdigittimeout = 16000;
00450 
00451 /*! \brief How long to wait for following digits (FXO logic) */
00452 static int gendigittimeout = 8000;
00453 
00454 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00455 static int matchdigittimeout = 3000;
00456 
00457 /*! \brief Protect the interface list (of dahdi_pvt's) */
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459 
00460 
00461 static int ifcount = 0;
00462 
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466 
00467 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00468    when it's doing something critical. */
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470 
00471 /*! \brief This is the thread for the monitor which checks for input on the channels
00472    which are not currently in use. */
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479 
00480 static int restart_monitor(void);
00481 
00482 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);
00483 
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485 
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488    /* This module does not handle MWI in an event-based manner.  However, it
00489     * subscribes to MWI for each mailbox that is configured so that the core
00490     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00491     * event cache instead of checking the mailbox directly. */
00492 }
00493 
00494 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00495 static inline int dahdi_get_event(int fd)
00496 {
00497    int j;
00498    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499       return -1;
00500    return j;
00501 }
00502 
00503 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506    int i, j = 0;
00507    i = DAHDI_IOMUX_SIGEVENT;
00508    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509       return -1;
00510    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511       return -1;
00512    return j;
00513 }
00514 
00515 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00516 #define READ_SIZE 160
00517 
00518 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00519 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00520 
00521 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00522 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00523 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00524 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00525 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00526 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00527 
00528 struct dahdi_pvt;
00529 
00530 /*!
00531  * \brief Configured ring timeout base.
00532  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00533  */
00534 static int ringt_base = DEFAULT_RINGT;
00535 
00536 #if defined(HAVE_SS7)
00537 
00538 struct dahdi_ss7 {
00539    struct sig_ss7_linkset ss7;
00540 };
00541 
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543 
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif   /* defined(HAVE_SS7) */
00552 
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2 {
00555    pthread_t r2master;            /*!< Thread of master */
00556    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00557    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00558    int numchans;                          /*!< Number of channels in this R2 block */
00559    int monitored_count;                   /*!< Number of channels being monitored */
00560 };
00561 
00562 struct dahdi_mfcr2_conf {
00563    openr2_variant_t variant;
00564    int mfback_timeout;
00565    int metering_pulse_timeout;
00566    int max_ani;
00567    int max_dnis;
00568    signed int get_ani_first:2;
00569 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00570    signed int skip_category_request:2;
00571 #endif
00572    unsigned int call_files:1;
00573    unsigned int allow_collect_calls:1;
00574    unsigned int charge_calls:1;
00575    unsigned int accept_on_offer:1;
00576    unsigned int forced_release:1;
00577    unsigned int double_answer:1;
00578    signed int immediate_accept:2;
00579    char logdir[OR2_MAX_PATH];
00580    char r2proto_file[OR2_MAX_PATH];
00581    openr2_log_level_t loglevel;
00582    openr2_calling_party_category_t category;
00583 };
00584 
00585 /* malloc'd array of malloc'd r2links */
00586 static struct dahdi_mfcr2 **r2links;
00587 /* how many r2links have been malloc'd */
00588 static int r2links_count = 0;
00589 
00590 #endif /* HAVE_OPENR2 */
00591 
00592 #ifdef HAVE_PRI
00593 
00594 struct dahdi_pri {
00595    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00596    int mastertrunkgroup;               /*!< What trunk group is our master */
00597    int prilogicalspan;                 /*!< Logical span number within trunk group */
00598    struct sig_pri_span pri;
00599 };
00600 
00601 static struct dahdi_pri pris[NUM_SPANS];
00602 
00603 #if defined(HAVE_PRI_CCSS)
00604 /*! DAHDI PRI CCSS agent and monitor type name. */
00605 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00606 #endif   /* defined(HAVE_PRI_CCSS) */
00607 
00608 #else
00609 /*! Shut up the compiler */
00610 struct dahdi_pri;
00611 #endif
00612 
00613 #define SUB_REAL  0        /*!< Active call */
00614 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00615 #define SUB_THREEWAY 2        /*!< Three-way call */
00616 
00617 /* Polarity states */
00618 #define POLARITY_IDLE   0
00619 #define POLARITY_REV    1
00620 
00621 
00622 struct distRingData {
00623    int ring[3];
00624    int range;
00625 };
00626 struct ringContextData {
00627    char contextData[AST_MAX_CONTEXT];
00628 };
00629 struct dahdi_distRings {
00630    struct distRingData ringnum[3];
00631    struct ringContextData ringContext[3];
00632 };
00633 
00634 static const char * const subnames[] = {
00635    "Real",
00636    "Callwait",
00637    "Threeway"
00638 };
00639 
00640 struct dahdi_subchannel {
00641    int dfd;
00642    struct ast_channel *owner;
00643    int chan;
00644    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00645    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00646    unsigned int needringing:1;
00647    unsigned int needbusy:1;
00648    unsigned int needcongestion:1;
00649    unsigned int needanswer:1;
00650    unsigned int needflash:1;
00651    unsigned int needhold:1;
00652    unsigned int needunhold:1;
00653    unsigned int linear:1;
00654    unsigned int inthreeway:1;
00655    struct dahdi_confinfo curconf;
00656 };
00657 
00658 #define CONF_USER_REAL     (1 << 0)
00659 #define CONF_USER_THIRDCALL   (1 << 1)
00660 
00661 #define MAX_SLAVES   4
00662 
00663 /* States for sending MWI message
00664  * First three states are required for send Ring Pulse Alert Signal
00665  */
00666 typedef enum {
00667    MWI_SEND_NULL = 0,
00668    MWI_SEND_SA,
00669    MWI_SEND_SA_WAIT,
00670    MWI_SEND_PAUSE,
00671    MWI_SEND_SPILL,
00672    MWI_SEND_CLEANUP,
00673    MWI_SEND_DONE,
00674 } mwisend_states;
00675 
00676 struct mwisend_info {
00677    struct   timeval  pause;
00678    mwisend_states    mwisend_current;
00679 };
00680 
00681 /*! Specify the lists dahdi_pvt can be put in. */
00682 enum DAHDI_IFLIST {
00683    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00684    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00685 #if defined(HAVE_PRI)
00686    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00687 #endif   /* defined(HAVE_PRI) */
00688 };
00689 
00690 struct dahdi_pvt {
00691    ast_mutex_t lock;             /*!< Channel private lock. */
00692    struct callerid_state *cs;
00693    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00694                      /*!< Up to three channels can be associated with this call */
00695 
00696    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00697    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00698    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00699 
00700    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00701    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00702    int inconference;          /*!< If our real should be in the conference */
00703 
00704    int bufsize;                /*!< Size of the buffers */
00705    int buf_no;             /*!< Number of buffers */
00706    int buf_policy;            /*!< Buffer policy */
00707    int faxbuf_no;              /*!< Number of Fax buffers */
00708    int faxbuf_policy;          /*!< Fax buffer policy */
00709    int sig;             /*!< Signalling style */
00710    /*!
00711     * \brief Nonzero if the signaling type is sent over a radio.
00712     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00713     */
00714    int radio;
00715    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00716    int oprmode;               /*!< "Operator Services" mode */
00717    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00718    /*! \brief Amount of gain to increase during caller id */
00719    float cid_rxgain;
00720    /*! \brief Rx gain set by chan_dahdi.conf */
00721    float rxgain;
00722    /*! \brief Tx gain set by chan_dahdi.conf */
00723    float txgain;
00724 
00725    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00726    float rxdrc;
00727    
00728    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00729    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00730    struct dahdi_pvt *next;          /*!< Next channel in list */
00731    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00732 
00733    /* flags */
00734 
00735    /*!
00736     * \brief TRUE if ADSI (Analog Display Services Interface) available
00737     * \note Set from the "adsi" value read in from chan_dahdi.conf
00738     */
00739    unsigned int adsi:1;
00740    /*!
00741     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00742     * call is answered by the remote party.
00743     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00744     */
00745    unsigned int answeronpolarityswitch:1;
00746    /*!
00747     * \brief TRUE if busy detection is enabled.
00748     * (Listens for the beep-beep busy pattern.)
00749     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00750     */
00751    unsigned int busydetect:1;
00752    /*!
00753     * \brief TRUE if call return is enabled.
00754     * (*69, if your dialplan doesn't catch this first)
00755     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00756     */
00757    unsigned int callreturn:1;
00758    /*!
00759     * \brief TRUE if busy extensions will hear the call-waiting tone
00760     * and can use hook-flash to switch between callers.
00761     * \note Can be disabled by dialing *70.
00762     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00763     */
00764    unsigned int callwaiting:1;
00765    /*!
00766     * \brief TRUE if send caller ID for Call Waiting
00767     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00768     */
00769    unsigned int callwaitingcallerid:1;
00770    /*!
00771     * \brief TRUE if support for call forwarding enabled.
00772     * Dial *72 to enable call forwarding.
00773     * Dial *73 to disable call forwarding.
00774     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00775     */
00776    unsigned int cancallforward:1;
00777    /*!
00778     * \brief TRUE if support for call parking is enabled.
00779     * \note Set from the "canpark" value read in from chan_dahdi.conf
00780     */
00781    unsigned int canpark:1;
00782    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00783    unsigned int confirmanswer:1;
00784    /*!
00785     * \brief TRUE if the channel is to be destroyed on hangup.
00786     * (Used by pseudo channels.)
00787     */
00788    unsigned int destroy:1;
00789    unsigned int didtdd:1;           /*!< flag to say its done it once */
00790    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00791    unsigned int dialednone:1;
00792    /*!
00793     * \brief TRUE if in the process of dialing digits or sending something.
00794     * \note This is used as a receive squelch for ISDN until connected.
00795     */
00796    unsigned int dialing:1;
00797    /*! \brief TRUE if the transfer capability of the call is digital. */
00798    unsigned int digital:1;
00799    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00800    unsigned int dnd:1;
00801    /*! \brief XXX BOOLEAN Purpose??? */
00802    unsigned int echobreak:1;
00803    /*!
00804     * \brief TRUE if echo cancellation enabled when bridged.
00805     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00806     * \note Disabled if the echo canceller is not setup.
00807     */
00808    unsigned int echocanbridged:1;
00809    /*! \brief TRUE if echo cancellation is turned on. */
00810    unsigned int echocanon:1;
00811    /*! \brief TRUE if a fax tone has already been handled. */
00812    unsigned int faxhandled:1;
00813    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00814    unsigned int usefaxbuffers:1;
00815    /*! TRUE while buffer configuration override is in use */
00816    unsigned int bufferoverrideinuse:1;
00817    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00818    unsigned int firstradio:1;
00819    /*!
00820     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00821     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00822     */
00823    unsigned int hanguponpolarityswitch:1;
00824    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00825    unsigned int hardwaredtmf:1;
00826    /*!
00827     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00828     * \note Caller ID can be disabled by dialing *67.
00829     * \note Caller ID can be enabled by dialing *82.
00830     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00831     */
00832    unsigned int hidecallerid:1;
00833    /*!
00834     * \brief TRUE if hide just the name not the number for legacy PBX use.
00835     * \note Only applies to PRI channels.
00836     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00837     */
00838    unsigned int hidecalleridname:1;
00839    /*! \brief TRUE if DTMF detection is disabled. */
00840    unsigned int ignoredtmf:1;
00841    /*!
00842     * \brief TRUE if the channel should be answered immediately
00843     * without attempting to gather any digits.
00844     * \note Set from the "immediate" value read in from chan_dahdi.conf
00845     */
00846    unsigned int immediate:1;
00847    /*! \brief TRUE if in an alarm condition. */
00848    unsigned int inalarm:1;
00849    /*! \brief TRUE if TDD in MATE mode */
00850    unsigned int mate:1;
00851    /*! \brief TRUE if we originated the call leg. */
00852    unsigned int outgoing:1;
00853    /* unsigned int overlapdial:1;         unused and potentially confusing */
00854    /*!
00855     * \brief TRUE if busy extensions will hear the call-waiting tone
00856     * and can use hook-flash to switch between callers.
00857     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00858     */
00859    unsigned int permcallwaiting:1;
00860    /*!
00861     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00862     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00863     */
00864    unsigned int permhidecallerid:1;
00865    /*!
00866     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00867     * \note Set from the "priindication" value read in from chan_dahdi.conf
00868     */
00869    unsigned int priindication_oob:1;
00870    /*!
00871     * \brief TRUE if PRI B channels are always exclusively selected.
00872     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00873     */
00874    unsigned int priexclusive:1;
00875    /*!
00876     * \brief TRUE if we will pulse dial.
00877     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00878     */
00879    unsigned int pulse:1;
00880    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00881    unsigned int pulsedial:1;
00882    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00883    /*!
00884     * \brief TRUE if caller ID is restricted.
00885     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00886     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00887     */
00888    unsigned int restrictcid:1;
00889    /*!
00890     * \brief TRUE if three way calling is enabled
00891     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00892     */
00893    unsigned int threewaycalling:1;
00894    /*!
00895     * \brief TRUE if call transfer is enabled
00896     * \note For FXS ports (either direct analog or over T1/E1):
00897     *   Support flash-hook call transfer
00898     * \note For digital ports using ISDN PRI protocols:
00899     *   Support switch-side transfer (called 2BCT, RLT or other names)
00900     * \note Set from the "transfer" value read in from chan_dahdi.conf
00901     */
00902    unsigned int transfer:1;
00903    /*!
00904     * \brief TRUE if caller ID is used on this channel.
00905     * \note PRI and SS7 spans will save caller ID from the networking peer.
00906     * \note FXS ports will generate the caller ID spill.
00907     * \note FXO ports will listen for the caller ID spill.
00908     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00909     */
00910    unsigned int use_callerid:1;
00911    /*!
00912     * \brief TRUE if we will use the calling presentation setting
00913     * from the Asterisk channel for outgoing calls.
00914     * \note Only applies to PRI and SS7 channels.
00915     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00916     */
00917    unsigned int use_callingpres:1;
00918    /*!
00919     * \brief TRUE if distinctive rings are to be detected.
00920     * \note For FXO lines
00921     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00922     */
00923    unsigned int usedistinctiveringdetection:1;
00924    /*!
00925     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00926     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00927     */
00928    unsigned int dahditrcallerid:1;
00929    /*!
00930     * \brief TRUE if allowed to flash-transfer to busy channels.
00931     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00932     */
00933    unsigned int transfertobusy:1;
00934    /*!
00935     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00936     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00937     */
00938    unsigned int mwimonitor_neon:1;
00939    /*!
00940     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00941     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00942     */
00943    unsigned int mwimonitor_fsk:1;
00944    /*!
00945     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00946     * \note RPAS - Ring Pulse Alert Signal
00947     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00948     */
00949    unsigned int mwimonitor_rpas:1;
00950    /*! \brief TRUE if an MWI monitor thread is currently active */
00951    unsigned int mwimonitoractive:1;
00952    /*! \brief TRUE if a MWI message sending thread is active */
00953    unsigned int mwisendactive:1;
00954    /*!
00955     * \brief TRUE if channel is out of reset and ready
00956     * \note Set but not used.
00957     */
00958    unsigned int inservice:1;
00959    /*!
00960     * \brief TRUE if the channel is locally blocked.
00961     * \note Applies to SS7 and MFCR2 channels.
00962     */
00963    unsigned int locallyblocked:1;
00964    /*!
00965     * \brief TRUE if the channel is remotely blocked.
00966     * \note Applies to SS7 and MFCR2 channels.
00967     */
00968    unsigned int remotelyblocked:1;
00969    /*!
00970     * \brief TRUE if the channel alarms will be managed also as Span ones
00971     * \note Applies to all channels
00972     */
00973    unsigned int manages_span_alarms:1;
00974 
00975 #if defined(HAVE_PRI)
00976    struct sig_pri_span *pri;
00977    int logicalspan;
00978 #endif
00979    /*!
00980     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00981     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00982     */
00983    unsigned int use_smdi:1;
00984    struct mwisend_info mwisend_data;
00985    /*! \brief The SMDI interface to get SMDI messages from. */
00986    struct ast_smdi_interface *smdi_iface;
00987 
00988    /*! \brief Distinctive Ring data */
00989    struct dahdi_distRings drings;
00990 
00991    /*!
00992     * \brief The configured context for incoming calls.
00993     * \note The "context" string read in from chan_dahdi.conf
00994     */
00995    char context[AST_MAX_CONTEXT];
00996    /*!
00997     * \brief Saved context string.
00998     */
00999    char defcontext[AST_MAX_CONTEXT];
01000    /*! \brief Extension to use in the dialplan. */
01001    char exten[AST_MAX_EXTENSION];
01002    /*!
01003     * \brief Language configured for calls.
01004     * \note The "language" string read in from chan_dahdi.conf
01005     */
01006    char language[MAX_LANGUAGE];
01007    /*!
01008     * \brief The configured music-on-hold class to use for calls.
01009     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01010     */
01011    char mohinterpret[MAX_MUSICCLASS];
01012    /*!
01013     * \brief Suggested music-on-hold class for peer channel to use for calls.
01014     * \note The "mohsuggest" string read in from chan_dahdi.conf
01015     */
01016    char mohsuggest[MAX_MUSICCLASS];
01017    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01018 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01019    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01020    char cid_ani[AST_MAX_EXTENSION];
01021 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01022    /*! \brief Automatic Number Identification code from PRI */
01023    int cid_ani2;
01024    /*! \brief Caller ID number from an incoming call. */
01025    char cid_num[AST_MAX_EXTENSION];
01026    /*!
01027     * \brief Caller ID tag from incoming call
01028     * \note the "cid_tag" string read in from chan_dahdi.conf
01029     */
01030    char cid_tag[AST_MAX_EXTENSION];
01031    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01032    int cid_ton;
01033    /*! \brief Caller ID name from an incoming call. */
01034    char cid_name[AST_MAX_EXTENSION];
01035    /*! \brief Caller ID subaddress from an incoming call. */
01036    char cid_subaddr[AST_MAX_EXTENSION];
01037    char *origcid_num;            /*!< malloced original callerid */
01038    char *origcid_name;           /*!< malloced original callerid */
01039    /*! \brief Call waiting number. */
01040    char callwait_num[AST_MAX_EXTENSION];
01041    /*! \brief Call waiting name. */
01042    char callwait_name[AST_MAX_EXTENSION];
01043    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01044    char rdnis[AST_MAX_EXTENSION];
01045    /*! \brief Dialed Number Identifier */
01046    char dnid[AST_MAX_EXTENSION];
01047    /*!
01048     * \brief Bitmapped groups this belongs to.
01049     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01050     */
01051    ast_group_t group;
01052    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01053    int law_default;
01054    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01055    int law;
01056    int confno;             /*!< Our conference */
01057    int confusers;             /*!< Who is using our conference */
01058    int propconfno;               /*!< Propagated conference number */
01059    /*!
01060     * \brief Bitmapped call groups this belongs to.
01061     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01062     */
01063    ast_group_t callgroup;
01064    /*!
01065     * \brief Bitmapped pickup groups this belongs to.
01066     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01067     */
01068    ast_group_t pickupgroup;
01069    /*!
01070     * \brief Channel variable list with associated values to set when a channel is created.
01071     * \note The "setvar" strings read in from chan_dahdi.conf
01072     */
01073    struct ast_variable *vars;
01074    int channel;               /*!< Channel Number */
01075    int span;               /*!< Span number */
01076    time_t guardtime;          /*!< Must wait this much time before using for new call */
01077    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01078    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01079    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01080    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01081    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01082    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01083    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01084    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01085    /*! \brief Analog caller ID waveform sample buffer */
01086    unsigned char *cidspill;
01087    /*! \brief Position in the cidspill buffer to send out next. */
01088    int cidpos;
01089    /*! \brief Length of the cidspill buffer containing samples. */
01090    int cidlen;
01091    /*! \brief Ring timeout timer?? */
01092    int ringt;
01093    /*!
01094     * \brief Ring timeout base.
01095     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01096     */
01097    int ringt_base;
01098    /*!
01099     * \brief Number of most significant digits/characters to strip from the dialed number.
01100     * \note Feature is deprecated.  Use dialplan logic.
01101     * \note The characters are stripped before the PRI TON/NPI prefix
01102     * characters are processed.
01103     */
01104    int stripmsd;
01105    /*!
01106     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01107     * \note
01108     * After CAS is sent, the call waiting caller id will be sent if the phone
01109     * gives a positive reply.
01110     */
01111    int callwaitcas;
01112    /*! \brief Number of call waiting rings. */
01113    int callwaitrings;
01114    /*! \brief Echo cancel parameters. */
01115    struct {
01116       struct dahdi_echocanparams head;
01117       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01118    } echocancel;
01119    /*!
01120     * \brief Echo training time. 0 = disabled
01121     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01122     */
01123    int echotraining;
01124    /*! \brief Filled with 'w'.  XXX Purpose?? */
01125    char echorest[20];
01126    /*!
01127     * \brief Number of times to see "busy" tone before hanging up.
01128     * \note Set from the "busycount" value read in from chan_dahdi.conf
01129     */
01130    int busycount;
01131    /*!
01132     * \brief If your country has a busy tone with the same length tone and silence (as many countries do), consider using this option in order to compare tone and silence lengths
01133     * \note Set from the "busycompare" value read in from chan_dahdi.conf
01134     */
01135    int busycompare;
01136    /*!
01137     * \brief Lenght of "tone" in ms.
01138     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01139     */
01140    int busytonelength;
01141    /*!
01142     * \brief Lenght of "silence" in ms.
01143     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01144     */
01145    int busyquietlength;
01146    /*!
01147     * \brief  Maximun percentage difference allowed between measured and actual pattern
01148     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
01149     */
01150    int busyfuzziness;
01151    /*!
01152     * \brief Maximun signal average level considered as silence in this channel
01153     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
01154     */
01155    int silencethreshold;
01156    /*!
01157     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01158     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01159     */
01160    int callprogress;
01161    /*!
01162     * \brief Number of milliseconds to wait for dialtone.
01163     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01164     */
01165    int waitfordialtone;
01166    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01167    struct timeval flashtime;        /*!< Last flash-hook time */
01168    /*! \brief Opaque DSP configuration structure. */
01169    struct ast_dsp *dsp;
01170    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01171    struct dahdi_dialoperation dop;
01172    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01173    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01174    char finaldial[64];
01175    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01176    int amaflags;              /*!< AMA Flags */
01177    struct tdd_state *tdd;           /*!< TDD flag */
01178    /*! \brief Accumulated call forwarding number. */
01179    char call_forward[AST_MAX_EXTENSION];
01180    /*!
01181     * \brief Voice mailbox location.
01182     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01183     */
01184    char mailbox[AST_MAX_EXTENSION];
01185    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01186    struct ast_event_sub *mwi_event_sub;
01187    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01188    char dialdest[256];
01189 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01190    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01191    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01192    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01193 #endif
01194    int distinctivering;          /*!< Which distinctivering to use */
01195    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01196    /*! \brief Holding place for event injected from outside normal operation. */
01197    int fake_event;
01198    /*!
01199     * \brief Minimal time period (ms) between the answer polarity
01200     * switch and hangup polarity switch.
01201     */
01202    int polarityonanswerdelay;
01203    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01204    struct timeval polaritydelaytv;
01205    /*!
01206     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01207     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01208     */
01209    int sendcalleridafter;
01210    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01211    int polarity;
01212    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01213    int dsp_features;
01214 #if defined(HAVE_SS7)
01215    /*! \brief SS7 control parameters */
01216    struct sig_ss7_linkset *ss7;
01217 #endif   /* defined(HAVE_SS7) */
01218 #ifdef HAVE_OPENR2
01219    struct dahdi_mfcr2 *mfcr2;
01220    openr2_chan_t *r2chan;
01221    openr2_calling_party_category_t mfcr2_recvd_category;
01222    openr2_calling_party_category_t mfcr2_category;
01223    int mfcr2_dnis_index;
01224    int mfcr2_ani_index;
01225    int mfcr2call:1;
01226    int mfcr2_answer_pending:1;
01227    int mfcr2_charge_calls:1;
01228    int mfcr2_allow_collect_calls:1;
01229    int mfcr2_forced_release:1;
01230    int mfcr2_dnis_matched:1;
01231    int mfcr2_call_accepted:1;
01232    int mfcr2_progress:1;
01233    int mfcr2_accept_on_offer:1;
01234 #endif
01235    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01236    char begindigit;
01237    /*! \brief TRUE if confrence is muted. */
01238    int muting;
01239    void *sig_pvt;
01240    struct ast_cc_config_params *cc_params;
01241    /* DAHDI channel names may differ greatly from the
01242     * string that was provided to an app such as Dial. We
01243     * need to save the original string passed to dahdi_request
01244     * for call completion purposes. This way, we can replicate
01245     * the original dialed string later.
01246     */
01247    char dialstring[AST_CHANNEL_NAME];
01248 };
01249 
01250 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01251    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01252    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01253    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01254    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01255    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01256    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01257    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01258    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01259    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01260    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01261    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01262    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01263    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01265    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01266    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01267    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01268    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01269    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01270    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01271    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01272    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01273    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01274    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01275    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01276    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01277    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01278    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01279    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01280    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01281    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01282    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01283    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01284    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01285    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01286    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01287    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01288    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01289    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01290    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01291    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01292    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01293    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01294    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01295    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01296    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01297    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01298    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01299    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01300    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01301    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01302    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01303    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01304    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01305    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01306    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01307    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01308    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01309    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01310    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01311    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01312    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01313    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01314    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01315    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01316    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01317    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01318 
01319 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01320 
01321 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01322 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01323 
01324 #if defined(HAVE_PRI)
01325 static struct dahdi_parms_pseudo {
01326    int buf_no;             /*!< Number of buffers */
01327    int buf_policy;            /*!< Buffer policy */
01328    int faxbuf_no;              /*!< Number of Fax buffers */
01329    int faxbuf_policy;          /*!< Fax buffer policy */
01330 } dahdi_pseudo_parms;
01331 #endif   /* defined(HAVE_PRI) */
01332 
01333 /*! \brief Channel configuration from chan_dahdi.conf .
01334  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01335  * Generally there is a field here for every possible configuration item.
01336  *
01337  * The state of fields is saved along the parsing and whenever a 'channel'
01338  * statement is reached, the current dahdi_chan_conf is used to configure the
01339  * channel (struct dahdi_pvt)
01340  *
01341  * \see dahdi_chan_init for the default values.
01342  */
01343 struct dahdi_chan_conf {
01344    struct dahdi_pvt chan;
01345 #ifdef HAVE_PRI
01346    struct dahdi_pri pri;
01347 #endif
01348 
01349 #if defined(HAVE_SS7)
01350    struct dahdi_ss7 ss7;
01351 #endif   /* defined(HAVE_SS7) */
01352 
01353 #ifdef HAVE_OPENR2
01354    struct dahdi_mfcr2_conf mfcr2;
01355 #endif
01356    struct dahdi_params timing;
01357    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01358    /*! Continue configuration even if a channel is not there. */
01359    int ignore_failed_channels;
01360 
01361    /*!
01362     * \brief The serial port to listen for SMDI data on
01363     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01364     */
01365    char smdi_port[SMDI_MAX_FILENAME_LEN];
01366 };
01367 
01368 /*! returns a new dahdi_chan_conf with default values (by-value) */
01369 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01370 {
01371    /* recall that if a field is not included here it is initialized
01372     * to 0 or equivalent
01373     */
01374    struct dahdi_chan_conf conf = {
01375 #ifdef HAVE_PRI
01376       .pri.pri = {
01377          .nsf = PRI_NSF_NONE,
01378          .switchtype = PRI_SWITCH_NI2,
01379          .dialplan = PRI_UNKNOWN + 1,
01380          .localdialplan = PRI_NATIONAL_ISDN + 1,
01381          .nodetype = PRI_CPE,
01382          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01383 
01384 #if defined(HAVE_PRI_CCSS)
01385          .cc_ptmp_recall_mode = 1,/* specificRecall */
01386          .cc_qsig_signaling_link_req = 1,/* retain */
01387          .cc_qsig_signaling_link_rsp = 1,/* retain */
01388 #endif   /* defined(HAVE_PRI_CCSS) */
01389 
01390          .minunused = 2,
01391          .idleext = "",
01392          .idledial = "",
01393          .internationalprefix = "",
01394          .nationalprefix = "",
01395          .localprefix = "",
01396          .privateprefix = "",
01397          .unknownprefix = "",
01398          .resetinterval = -1,
01399       },
01400 #endif
01401 #if defined(HAVE_SS7)
01402       .ss7.ss7 = {
01403          .called_nai = SS7_NAI_NATIONAL,
01404          .calling_nai = SS7_NAI_NATIONAL,
01405          .internationalprefix = "",
01406          .nationalprefix = "",
01407          .subscriberprefix = "",
01408          .unknownprefix = ""
01409       },
01410 #endif   /* defined(HAVE_SS7) */
01411 #ifdef HAVE_OPENR2
01412       .mfcr2 = {
01413          .variant = OR2_VAR_ITU,
01414          .mfback_timeout = -1,
01415          .metering_pulse_timeout = -1,
01416          .max_ani = 10,
01417          .max_dnis = 4,
01418          .get_ani_first = -1,
01419 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01420          .skip_category_request = -1,
01421 #endif
01422          .call_files = 0,
01423          .allow_collect_calls = 0,
01424          .charge_calls = 1,
01425          .accept_on_offer = 1,
01426          .forced_release = 0,
01427          .double_answer = 0,
01428          .immediate_accept = -1,
01429          .logdir = "",
01430          .r2proto_file = "",
01431          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01432          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01433       },
01434 #endif
01435       .chan = {
01436          .context = "default",
01437          .cid_num = "",
01438          .cid_name = "",
01439          .cid_tag = "",
01440          .mohinterpret = "default",
01441          .mohsuggest = "",
01442          .parkinglot = "",
01443          .transfertobusy = 1,
01444 
01445          .cid_signalling = CID_SIG_BELL,
01446          .cid_start = CID_START_RING,
01447          .dahditrcallerid = 0,
01448          .use_callerid = 1,
01449          .sig = -1,
01450          .outsigmod = -1,
01451 
01452          .cid_rxgain = +5.0,
01453 
01454          .tonezone = -1,
01455 
01456          .echocancel.head.tap_length = 1,
01457 
01458          .busycount = 3,
01459          .busycompare = 0,
01460          .busytonelength = 0,
01461          .busyquietlength = 0,
01462          .busyfuzziness = 0,
01463          .silencethreshold = 0,
01464 
01465          .accountcode = "",
01466 
01467          .mailbox = "",
01468 
01469 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01470          .mwisend_fsk = 1,
01471 #endif
01472          .polarityonanswerdelay = 600,
01473 
01474          .sendcalleridafter = DEFAULT_CIDRINGS,
01475 
01476          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01477          .buf_no = numbufs,
01478          .usefaxbuffers = 0,
01479          .cc_params = ast_cc_config_params_init(),
01480       },
01481       .timing = {
01482          .prewinktime = -1,
01483          .preflashtime = -1,
01484          .winktime = -1,
01485          .flashtime = -1,
01486          .starttime = -1,
01487          .rxwinktime = -1,
01488          .rxflashtime = -1,
01489          .debouncetime = -1
01490       },
01491       .is_sig_auto = 1,
01492       .smdi_port = "/dev/ttyS0",
01493    };
01494 
01495    return conf;
01496 }
01497 
01498 
01499 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01500 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01501 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01502 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01503 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01504 static int dahdi_hangup(struct ast_channel *ast);
01505 static int dahdi_answer(struct ast_channel *ast);
01506 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01507 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01508 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01509 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01510 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01511 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01512 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01513 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01514 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01515 static int dahdi_devicestate(void *data);
01516 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01517 
01518 static const struct ast_channel_tech dahdi_tech = {
01519    .type = "DAHDI",
01520    .description = tdesc,
01521    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01522    .requester = dahdi_request,
01523    .send_digit_begin = dahdi_digit_begin,
01524    .send_digit_end = dahdi_digit_end,
01525    .send_text = dahdi_sendtext,
01526    .call = dahdi_call,
01527    .hangup = dahdi_hangup,
01528    .answer = dahdi_answer,
01529    .read = dahdi_read,
01530    .write = dahdi_write,
01531    .bridge = dahdi_bridge,
01532    .exception = dahdi_exception,
01533    .indicate = dahdi_indicate,
01534    .fixup = dahdi_fixup,
01535    .setoption = dahdi_setoption,
01536    .queryoption = dahdi_queryoption,
01537    .func_channel_read = dahdi_func_read,
01538    .func_channel_write = dahdi_func_write,
01539    .devicestate = dahdi_devicestate,
01540    .cc_callback = dahdi_cc_callback,
01541 };
01542 
01543 #define GET_CHANNEL(p) ((p)->channel)
01544 
01545 #define SIG_PRI_LIB_HANDLE_CASES \
01546    SIG_PRI:                \
01547    case SIG_BRI:              \
01548    case SIG_BRI_PTMP
01549 
01550 /*!
01551  * \internal
01552  * \brief Determine if sig_pri handles the signaling.
01553  * \since 1.8
01554  *
01555  * \param signaling Signaling to determine if is for sig_pri.
01556  *
01557  * \return TRUE if the signaling is for sig_pri.
01558  */
01559 static inline int dahdi_sig_pri_lib_handles(int signaling)
01560 {
01561    int handles;
01562 
01563    switch (signaling) {
01564    case SIG_PRI_LIB_HANDLE_CASES:
01565       handles = 1;
01566       break;
01567    default:
01568       handles = 0;
01569       break;
01570    }
01571 
01572    return handles;
01573 }
01574 
01575 static int analog_lib_handles(int signalling, int radio, int oprmode)
01576 {
01577    switch (signalling) {
01578    case SIG_FXOLS:
01579    case SIG_FXOGS:
01580    case SIG_FXOKS:
01581    case SIG_FXSLS:
01582    case SIG_FXSGS:
01583    case SIG_FXSKS:
01584    case SIG_EMWINK:
01585    case SIG_EM:
01586    case SIG_EM_E1:
01587    case SIG_FEATD:
01588    case SIG_FEATDMF:
01589    case SIG_E911:
01590    case SIG_FGC_CAMA:
01591    case SIG_FGC_CAMAMF:
01592    case SIG_FEATB:
01593    case SIG_SFWINK:
01594    case SIG_SF:
01595    case SIG_SF_FEATD:
01596    case SIG_SF_FEATDMF:
01597    case SIG_FEATDMF_TA:
01598    case SIG_SF_FEATB:
01599       break;
01600    default:
01601       /* The rest of the function should cover the remainder of signalling types */
01602       return 0;
01603    }
01604 
01605    if (radio) {
01606       return 0;
01607    }
01608 
01609    if (oprmode) {
01610       return 0;
01611    }
01612 
01613    return 1;
01614 }
01615 
01616 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01617 {
01618    switch (sig) {
01619    case SIG_FXOLS:
01620       return ANALOG_SIG_FXOLS;
01621    case SIG_FXOGS:
01622       return ANALOG_SIG_FXOGS;
01623    case SIG_FXOKS:
01624       return ANALOG_SIG_FXOKS;
01625    case SIG_FXSLS:
01626       return ANALOG_SIG_FXSLS;
01627    case SIG_FXSGS:
01628       return ANALOG_SIG_FXSGS;
01629    case SIG_FXSKS:
01630       return ANALOG_SIG_FXSKS;
01631    case SIG_EMWINK:
01632       return ANALOG_SIG_EMWINK;
01633    case SIG_EM:
01634       return ANALOG_SIG_EM;
01635    case SIG_EM_E1:
01636       return ANALOG_SIG_EM_E1;
01637    case SIG_FEATD:
01638       return ANALOG_SIG_FEATD;
01639    case SIG_FEATDMF:
01640       return ANALOG_SIG_FEATDMF;
01641    case SIG_E911:
01642       return SIG_E911;
01643    case SIG_FGC_CAMA:
01644       return ANALOG_SIG_FGC_CAMA;
01645    case SIG_FGC_CAMAMF:
01646       return ANALOG_SIG_FGC_CAMAMF;
01647    case SIG_FEATB:
01648       return ANALOG_SIG_FEATB;
01649    case SIG_SFWINK:
01650       return ANALOG_SIG_SFWINK;
01651    case SIG_SF:
01652       return ANALOG_SIG_SF;
01653    case SIG_SF_FEATD:
01654       return ANALOG_SIG_SF_FEATD;
01655    case SIG_SF_FEATDMF:
01656       return ANALOG_SIG_SF_FEATDMF;
01657    case SIG_FEATDMF_TA:
01658       return ANALOG_SIG_FEATDMF_TA;
01659    case SIG_SF_FEATB:
01660       return ANALOG_SIG_FEATB;
01661    default:
01662       return -1;
01663    }
01664 }
01665 
01666 
01667 static int analog_tone_to_dahditone(enum analog_tone tone)
01668 {
01669    switch (tone) {
01670    case ANALOG_TONE_RINGTONE:
01671       return DAHDI_TONE_RINGTONE;
01672    case ANALOG_TONE_STUTTER:
01673       return DAHDI_TONE_STUTTER;
01674    case ANALOG_TONE_CONGESTION:
01675       return DAHDI_TONE_CONGESTION;
01676    case ANALOG_TONE_DIALTONE:
01677       return DAHDI_TONE_DIALTONE;
01678    case ANALOG_TONE_DIALRECALL:
01679       return DAHDI_TONE_DIALRECALL;
01680    case ANALOG_TONE_INFO:
01681       return DAHDI_TONE_INFO;
01682    default:
01683       return -1;
01684    }
01685 }
01686 
01687 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01688 {
01689    int index;
01690 
01691    switch (analogsub) {
01692    case ANALOG_SUB_REAL:
01693       index = SUB_REAL;
01694       break;
01695    case ANALOG_SUB_CALLWAIT:
01696       index = SUB_CALLWAIT;
01697       break;
01698    case ANALOG_SUB_THREEWAY:
01699       index = SUB_THREEWAY;
01700       break;
01701    default:
01702       ast_log(LOG_ERROR, "Unidentified sub!\n");
01703       index = SUB_REAL;
01704    }
01705 
01706    return index;
01707 }
01708 
01709 static enum analog_event dahdievent_to_analogevent(int event);
01710 static int bump_gains(struct dahdi_pvt *p);
01711 static int dahdi_setlinear(int dfd, int linear);
01712 
01713 static int my_start_cid_detect(void *pvt, int cid_signalling)
01714 {
01715    struct dahdi_pvt *p = pvt;
01716    int index = SUB_REAL;
01717    p->cs = callerid_new(cid_signalling);
01718    if (!p->cs) {
01719       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01720       return -1;
01721    }
01722    bump_gains(p);
01723    dahdi_setlinear(p->subs[index].dfd, 0);
01724 
01725    return 0;
01726 }
01727 
01728 static int my_stop_cid_detect(void *pvt)
01729 {
01730    struct dahdi_pvt *p = pvt;
01731    int index = SUB_REAL;
01732    if (p->cs)
01733       callerid_free(p->cs);
01734    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01735    return 0;
01736 }
01737 
01738 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01739 {
01740    struct dahdi_pvt *p = pvt;
01741    struct analog_pvt *analog_p = p->sig_pvt;
01742    struct pollfd poller;
01743    char *name, *num;
01744    int index = SUB_REAL;
01745    int res;
01746    unsigned char buf[256];
01747    int flags;
01748 
01749    poller.fd = p->subs[SUB_REAL].dfd;
01750    poller.events = POLLPRI | POLLIN;
01751    poller.revents = 0;
01752 
01753    res = poll(&poller, 1, timeout);
01754 
01755    if (poller.revents & POLLPRI) {
01756       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01757       return 1;
01758    }
01759 
01760    if (poller.revents & POLLIN) {
01761       /*** NOTES ***/
01762       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01763        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01764        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01765        * a failure and die, and returning 2 means no event was received. */
01766       res = read(p->subs[index].dfd, buf, sizeof(buf));
01767       if (res < 0) {
01768          if (errno != ELAST) {
01769             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01770             callerid_free(p->cs);
01771             return -1;
01772          }
01773       }
01774 
01775       if (analog_p->ringt > 0) {
01776          if (!(--analog_p->ringt)) {
01777             /* only return if we timeout from a ring event */
01778             return -1;
01779          }
01780       }
01781 
01782       if (p->cid_signalling == CID_SIG_V23_JP) {
01783          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01784       } else {
01785          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01786       }
01787       if (res < 0) {
01788          /*
01789           * The previous diagnostic message output likely
01790           * explains why it failed.
01791           */
01792          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01793          return -1;
01794       }
01795 
01796       if (res == 1) {
01797          callerid_get(p->cs, &name, &num, &flags);
01798          if (name)
01799             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01800          if (num)
01801             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01802 
01803          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01804          return 0;
01805       }
01806    }
01807 
01808    *ev = ANALOG_EVENT_NONE;
01809    return 2;
01810 }
01811 
01812 static const char *event2str(int event);
01813 static int restore_gains(struct dahdi_pvt *p);
01814 
01815 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01816 {
01817    unsigned char buf[256];
01818    int distMatches;
01819    int curRingData[RING_PATTERNS];
01820    int receivedRingT;
01821    int counter1;
01822    int counter;
01823    int i;
01824    int res;
01825    int checkaftercid = 0;
01826 
01827    struct dahdi_pvt *p = pvt;
01828    struct analog_pvt *analog_p = p->sig_pvt;
01829 
01830    if (ringdata == NULL) {
01831       ringdata = curRingData;
01832    } else {
01833       checkaftercid = 1;
01834    }
01835 
01836    /* We must have a ring by now, so, if configured, lets try to listen for
01837     * distinctive ringing */
01838    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01839       /* Clear the current ring data array so we don't have old data in it. */
01840       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01841          ringdata[receivedRingT] = 0;
01842       receivedRingT = 0;
01843       if (checkaftercid && distinctiveringaftercid)
01844          ast_verb(3, "Detecting post-CID distinctive ring\n");
01845       /* Check to see if context is what it should be, if not set to be. */
01846       else if (strcmp(p->context,p->defcontext) != 0) {
01847          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01848          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01849       }
01850 
01851       for (;;) {
01852          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01853          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01854             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01855             ast_hangup(chan);
01856             return 1;
01857          }
01858          if (i & DAHDI_IOMUX_SIGEVENT) {
01859             res = dahdi_get_event(p->subs[idx].dfd);
01860             if (res == DAHDI_EVENT_NOALARM) {
01861                p->inalarm = 0;
01862                analog_p->inalarm = 0;
01863             }
01864             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01865             res = 0;
01866             /* Let us detect distinctive ring */
01867 
01868             ringdata[receivedRingT] = analog_p->ringt;
01869 
01870             if (analog_p->ringt < analog_p->ringt_base/2)
01871                break;
01872             /* Increment the ringT counter so we can match it against
01873                values in chan_dahdi.conf for distinctive ring */
01874             if (++receivedRingT == RING_PATTERNS)
01875                break;
01876          } else if (i & DAHDI_IOMUX_READ) {
01877             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01878             if (res < 0) {
01879                if (errno != ELAST) {
01880                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01881                   ast_hangup(chan);
01882                   return 1;
01883                }
01884                break;
01885             }
01886             if (analog_p->ringt > 0) {
01887                if (!(--analog_p->ringt)) {
01888                   res = -1;
01889                   break;
01890                }
01891             }
01892          }
01893       }
01894    }
01895    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01896       /* this only shows up if you have n of the dring patterns filled in */
01897       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01898       for (counter = 0; counter < 3; counter++) {
01899       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01900          distMatches = 0;
01901          /* this only shows up if you have n of the dring patterns filled in */
01902          ast_verb(3, "Checking %d,%d,%d\n",
01903                p->drings.ringnum[counter].ring[0],
01904                p->drings.ringnum[counter].ring[1],
01905                p->drings.ringnum[counter].ring[2]);
01906          for (counter1 = 0; counter1 < 3; counter1++) {
01907             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01908             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01909                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01910                ringdata[counter1]);
01911                distMatches++;
01912             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01913                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01914                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01915                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01916                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01917                distMatches++;
01918             }
01919          }
01920 
01921          if (distMatches == 3) {
01922             /* The ring matches, set the context to whatever is for distinctive ring.. */
01923             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01924             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01925             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01926             break;
01927          }
01928       }
01929    }
01930    /* Restore linear mode (if appropriate) for Caller*ID processing */
01931    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01932    restore_gains(p);
01933 
01934    return 0;
01935 }
01936 
01937 static int my_stop_callwait(void *pvt)
01938 {
01939    struct dahdi_pvt *p = pvt;
01940    p->callwaitingrepeat = 0;
01941    p->cidcwexpire = 0;
01942    p->cid_suppress_expire = 0;
01943 
01944    return 0;
01945 }
01946 
01947 static int send_callerid(struct dahdi_pvt *p);
01948 static int save_conference(struct dahdi_pvt *p);
01949 static int restore_conference(struct dahdi_pvt *p);
01950 
01951 static int my_callwait(void *pvt)
01952 {
01953    struct dahdi_pvt *p = pvt;
01954    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01955    if (p->cidspill) {
01956       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01957       ast_free(p->cidspill);
01958    }
01959 
01960    /*
01961     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01962     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01963     */
01964    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01965       return -1;
01966    save_conference(p);
01967    /* Silence */
01968    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01969    if (!p->callwaitrings && p->callwaitingcallerid) {
01970       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01971       p->callwaitcas = 1;
01972       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01973    } else {
01974       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01975       p->callwaitcas = 0;
01976       p->cidlen = 2400 + READ_SIZE * 4;
01977    }
01978    p->cidpos = 0;
01979    send_callerid(p);
01980 
01981    return 0;
01982 }
01983 
01984 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01985 {
01986    struct dahdi_pvt *p = pvt;
01987 
01988    ast_debug(2, "Starting cid spill\n");
01989 
01990    if (p->cidspill) {
01991       ast_log(LOG_WARNING, "cidspill already exists??\n");
01992       ast_free(p->cidspill);
01993    }
01994 
01995    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01996       if (cwcid == 0) {
01997          p->cidlen = ast_callerid_generate(p->cidspill,
01998             caller->id.name.str,
01999             caller->id.number.str,
02000             AST_LAW(p));
02001       } else {
02002          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
02003             caller->id.name.str, caller->id.number.str);
02004          p->callwaitcas = 0;
02005          p->cidcwexpire = 0;
02006          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02007             caller->id.name.str,
02008             caller->id.number.str,
02009             AST_LAW(p));
02010          p->cidlen += READ_SIZE * 4;
02011       }
02012       p->cidpos = 0;
02013       p->cid_suppress_expire = 0;
02014       send_callerid(p);
02015    }
02016    return 0;
02017 }
02018 
02019 static int my_dsp_reset_and_flush_digits(void *pvt)
02020 {
02021    struct dahdi_pvt *p = pvt;
02022    if (p->dsp)
02023       ast_dsp_digitreset(p->dsp);
02024 
02025    return 0;
02026 }
02027 
02028 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02029 {
02030    struct dahdi_pvt *p = pvt;
02031 
02032    if (p->channel == CHAN_PSEUDO)
02033       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02034 
02035    if (mode == ANALOG_DIGITMODE_DTMF) {
02036       /* If we do hardware dtmf, no need for a DSP */
02037       if (p->hardwaredtmf) {
02038          if (p->dsp) {
02039             ast_dsp_free(p->dsp);
02040             p->dsp = NULL;
02041          }
02042          return 0;
02043       }
02044 
02045       if (!p->dsp) {
02046          p->dsp = ast_dsp_new();
02047          if (!p->dsp) {
02048             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02049             return -1;
02050          }
02051       }
02052 
02053       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02054    } else if (mode == ANALOG_DIGITMODE_MF) {
02055       if (!p->dsp) {
02056          p->dsp = ast_dsp_new();
02057          if (!p->dsp) {
02058             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02059             return -1;
02060          }
02061       }
02062       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02063    }
02064    return 0;
02065 }
02066 
02067 static int dahdi_wink(struct dahdi_pvt *p, int index);
02068 
02069 static int my_wink(void *pvt, enum analog_sub sub)
02070 {
02071    struct dahdi_pvt *p = pvt;
02072    int index = analogsub_to_dahdisub(sub);
02073    if (index != SUB_REAL) {
02074       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02075    }
02076    return dahdi_wink(p, index);
02077 }
02078 
02079 static void wakeup_sub(struct dahdi_pvt *p, int a);
02080 
02081 static int reset_conf(struct dahdi_pvt *p);
02082 
02083 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02084 
02085 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02086 {
02087    struct ast_frame *f = *dest;
02088    struct dahdi_pvt *p = pvt;
02089    int idx = analogsub_to_dahdisub(analog_index);
02090 
02091    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02092       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02093       f->subclass.integer, f->subclass.integer, ast->name);
02094 
02095    if (f->subclass.integer == 'f') {
02096       if (f->frametype == AST_FRAME_DTMF_END) {
02097          /* Fax tone -- Handle and return NULL */
02098          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02099             /* If faxbuffers are configured, use them for the fax transmission */
02100             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02101                struct dahdi_bufferinfo bi = {
02102                   .txbufpolicy = p->faxbuf_policy,
02103                   .bufsize = p->bufsize,
02104                   .numbufs = p->faxbuf_no
02105                };
02106                int res;
02107 
02108                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02109                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02110                } else {
02111                   p->bufferoverrideinuse = 1;
02112                }
02113             }
02114             p->faxhandled = 1;
02115             if (p->dsp) {
02116                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02117                ast_dsp_set_features(p->dsp, p->dsp_features);
02118                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02119             }
02120             if (strcmp(ast->exten, "fax")) {
02121                const char *target_context = S_OR(ast->macrocontext, ast->context);
02122 
02123                /* We need to unlock 'ast' here because ast_exists_extension has the
02124                 * potential to start autoservice on the channel. Such action is prone
02125                 * to deadlock.
02126                 */
02127                ast_mutex_unlock(&p->lock);
02128                ast_channel_unlock(ast);
02129                if (ast_exists_extension(ast, target_context, "fax", 1,
02130                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02131                   ast_channel_lock(ast);
02132                   ast_mutex_lock(&p->lock);
02133                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02134                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02135                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02136                   if (ast_async_goto(ast, target_context, "fax", 1))
02137                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02138                } else {
02139                   ast_channel_lock(ast);
02140                   ast_mutex_lock(&p->lock);
02141                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02142                }
02143             } else {
02144                ast_debug(1, "Already in a fax extension, not redirecting\n");
02145             }
02146          } else {
02147             ast_debug(1, "Fax already handled\n");
02148          }
02149          dahdi_confmute(p, 0);
02150       }
02151       p->subs[idx].f.frametype = AST_FRAME_NULL;
02152       p->subs[idx].f.subclass.integer = 0;
02153       *dest = &p->subs[idx].f;
02154    }
02155 }
02156 
02157 static void my_lock_private(void *pvt)
02158 {
02159    struct dahdi_pvt *p = pvt;
02160    ast_mutex_lock(&p->lock);
02161 }
02162 
02163 static void my_unlock_private(void *pvt)
02164 {
02165    struct dahdi_pvt *p = pvt;
02166    ast_mutex_unlock(&p->lock);
02167 }
02168 
02169 static void my_deadlock_avoidance_private(void *pvt)
02170 {
02171    struct dahdi_pvt *p = pvt;
02172 
02173    DEADLOCK_AVOIDANCE(&p->lock);
02174 }
02175 
02176 /*!
02177  * \internal
02178  * \brief Post an AMI DAHDI channel association event.
02179  * \since 1.8
02180  *
02181  * \param p DAHDI private pointer
02182  * \param chan Channel associated with the private pointer
02183  *
02184  * \return Nothing
02185  */
02186 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02187 {
02188    char ch_name[20];
02189 
02190    if (p->channel < CHAN_PSEUDO) {
02191       /* No B channel */
02192       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02193    } else if (p->channel == CHAN_PSEUDO) {
02194       /* Pseudo channel */
02195       strcpy(ch_name, "pseudo");
02196    } else {
02197       /* Real channel */
02198       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02199    }
02200    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02201       "Channel: %s\r\n"
02202       "Uniqueid: %s\r\n"
02203       "DAHDISpan: %d\r\n"
02204       "DAHDIChannel: %s\r\n",
02205       chan->name,
02206       chan->uniqueid,
02207       p->span,
02208       ch_name);
02209 }
02210 
02211 #ifdef HAVE_PRI
02212 /*!
02213  * \internal
02214  * \brief Post an AMI DAHDI channel association event.
02215  * \since 1.8
02216  *
02217  * \param pvt DAHDI private pointer
02218  * \param chan Channel associated with the private pointer
02219  *
02220  * \return Nothing
02221  */
02222 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02223 {
02224    struct dahdi_pvt *p = pvt;
02225 
02226    dahdi_ami_channel_event(p, chan);
02227 }
02228 #endif
02229 
02230 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02231 *  returns the last value of the linear setting 
02232 */ 
02233 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02234 {
02235    struct dahdi_pvt *p = pvt;
02236    int oldval;
02237    int idx = analogsub_to_dahdisub(sub);
02238    
02239    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02240    oldval = p->subs[idx].linear;
02241    p->subs[idx].linear = linear_mode ? 1 : 0;
02242    return oldval;
02243 }
02244 
02245 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02246 {
02247    struct dahdi_pvt *p = pvt;
02248    int idx = analogsub_to_dahdisub(sub);
02249 
02250    p->subs[idx].inthreeway = inthreeway;
02251 }
02252 
02253 static int get_alarms(struct dahdi_pvt *p);
02254 static void handle_alarms(struct dahdi_pvt *p, int alms);
02255 static void my_get_and_handle_alarms(void *pvt)
02256 {
02257    int res;
02258    struct dahdi_pvt *p = pvt;
02259 
02260    res = get_alarms(p);
02261    handle_alarms(p, res);
02262 }
02263 
02264 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02265 {
02266    struct ast_channel *bridged = ast_bridged_channel(chan);
02267 
02268    if (bridged && bridged->tech == &dahdi_tech) {
02269       struct dahdi_pvt *p = bridged->tech_pvt;
02270 
02271       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02272          return p->sig_pvt;
02273       }
02274    }
02275    return NULL;
02276 }
02277 
02278 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02279 {
02280    struct dahdi_pvt *p = pvt;
02281    int dahdi_sub = analogsub_to_dahdisub(sub);
02282    return p->subs[dahdi_sub].dfd;
02283 }
02284 
02285 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02286 {
02287    struct dahdi_pvt *p = pvt;
02288 
02289    /* Choose proper cadence */
02290    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02291       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02292          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02293       *cid_rings = cidrings[p->distinctivering - 1];
02294    } else {
02295       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02296          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02297       *cid_rings = p->sendcalleridafter;
02298    }
02299 }
02300 
02301 static void my_set_alarm(void *pvt, int in_alarm)
02302 {
02303    struct dahdi_pvt *p = pvt;
02304 
02305    p->inalarm = in_alarm;
02306 }
02307 
02308 static void my_set_dialing(void *pvt, int is_dialing)
02309 {
02310    struct dahdi_pvt *p = pvt;
02311 
02312    p->dialing = is_dialing;
02313 }
02314 
02315 static void my_set_outgoing(void *pvt, int is_outgoing)
02316 {
02317    struct dahdi_pvt *p = pvt;
02318 
02319    p->outgoing = is_outgoing;
02320 }
02321 
02322 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02323 static void my_set_digital(void *pvt, int is_digital)
02324 {
02325    struct dahdi_pvt *p = pvt;
02326 
02327    p->digital = is_digital;
02328 }
02329 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02330 
02331 #if defined(HAVE_SS7)
02332 static void my_set_inservice(void *pvt, int is_inservice)
02333 {
02334    struct dahdi_pvt *p = pvt;
02335 
02336    p->inservice = is_inservice;
02337 }
02338 #endif   /* defined(HAVE_SS7) */
02339 
02340 #if defined(HAVE_SS7)
02341 static void my_set_locallyblocked(void *pvt, int is_blocked)
02342 {
02343    struct dahdi_pvt *p = pvt;
02344 
02345    p->locallyblocked = is_blocked;
02346 }
02347 #endif   /* defined(HAVE_SS7) */
02348 
02349 #if defined(HAVE_SS7)
02350 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02351 {
02352    struct dahdi_pvt *p = pvt;
02353 
02354    p->remotelyblocked = is_blocked;
02355 }
02356 #endif   /* defined(HAVE_SS7) */
02357 
02358 static void my_set_ringtimeout(void *pvt, int ringt)
02359 {
02360    struct dahdi_pvt *p = pvt;
02361    p->ringt = ringt;
02362 }
02363 
02364 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02365 {
02366    struct dahdi_pvt *p = pvt;
02367 
02368    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02369       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02370       gettimeofday(&p->waitingfordt, NULL);
02371       ast_setstate(ast, AST_STATE_OFFHOOK);
02372    }
02373 }
02374 
02375 static int my_check_waitingfordt(void *pvt)
02376 {
02377    struct dahdi_pvt *p = pvt;
02378 
02379    if (p->waitingfordt.tv_usec) {
02380       return 1;
02381    }
02382 
02383    return 0;
02384 }
02385 
02386 static void my_set_confirmanswer(void *pvt, int flag)
02387 {
02388    struct dahdi_pvt *p = pvt;
02389    p->confirmanswer = flag;
02390 }
02391 
02392 static int my_check_confirmanswer(void *pvt)
02393 {
02394    struct dahdi_pvt *p = pvt;
02395    if (p->confirmanswer) {
02396       return 1;
02397    }
02398 
02399    return 0;
02400 }
02401 
02402 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02403 {
02404    struct dahdi_pvt *p = pvt;
02405 
02406    p->callwaiting = callwaiting_enable;
02407 }
02408 
02409 static void my_cancel_cidspill(void *pvt)
02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    ast_free(p->cidspill);
02414    p->cidspill = NULL;
02415    restore_conference(p);
02416 }
02417 
02418 static int my_confmute(void *pvt, int mute)
02419 {
02420    struct dahdi_pvt *p = pvt;
02421    return dahdi_confmute(p, mute);
02422 }
02423 
02424 static void my_set_pulsedial(void *pvt, int flag)
02425 {
02426    struct dahdi_pvt *p = pvt;
02427    p->pulsedial = flag;
02428 }
02429 
02430 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02431 {
02432    struct dahdi_pvt *p = pvt;
02433 
02434    p->owner = new_owner;
02435 }
02436 
02437 static const char *my_get_orig_dialstring(void *pvt)
02438 {
02439    struct dahdi_pvt *p = pvt;
02440 
02441    return p->dialstring;
02442 }
02443 
02444 static void my_increase_ss_count(void)
02445 {
02446    ast_mutex_lock(&ss_thread_lock);
02447    ss_thread_count++;
02448    ast_mutex_unlock(&ss_thread_lock);
02449 }
02450 
02451 static void my_decrease_ss_count(void)
02452 {
02453    ast_mutex_lock(&ss_thread_lock);
02454    ss_thread_count--;
02455    ast_cond_signal(&ss_thread_complete);
02456    ast_mutex_unlock(&ss_thread_lock);
02457 }
02458 
02459 static void my_all_subchannels_hungup(void *pvt)
02460 {
02461    struct dahdi_pvt *p = pvt;
02462    int res, law;
02463 
02464    p->faxhandled = 0;
02465    p->didtdd = 0;
02466 
02467    if (p->dsp) {
02468       ast_dsp_free(p->dsp);
02469       p->dsp = NULL;
02470    }
02471 
02472    p->law = p->law_default;
02473    law = p->law_default;
02474    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02475    if (res < 0)
02476       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02477 
02478    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02479 
02480 #if 1
02481    {
02482    int i;
02483    p->owner = NULL;
02484    /* Cleanup owners here */
02485    for (i = 0; i < 3; i++) {
02486       p->subs[i].owner = NULL;
02487    }
02488    }
02489 #endif
02490 
02491    reset_conf(p);
02492    if (num_restart_pending == 0) {
02493       restart_monitor();
02494    }
02495 }
02496 
02497 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02498 
02499 static int my_conf_del(void *pvt, enum analog_sub sub)
02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int x = analogsub_to_dahdisub(sub);
02503 
02504    return conf_del(p, &p->subs[x], x);
02505 }
02506 
02507 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02508 
02509 static int my_conf_add(void *pvt, enum analog_sub sub)
02510 {
02511    struct dahdi_pvt *p = pvt;
02512    int x = analogsub_to_dahdisub(sub);
02513 
02514    return conf_add(p, &p->subs[x], x, 0);
02515 }
02516 
02517 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02518 
02519 static int my_complete_conference_update(void *pvt, int needconference)
02520 {
02521    struct dahdi_pvt *p = pvt;
02522    int needconf = needconference;
02523    int x;
02524    int useslavenative;
02525    struct dahdi_pvt *slave = NULL;
02526 
02527    useslavenative = isslavenative(p, &slave);
02528 
02529    /* If we have a slave, add him to our conference now. or DAX
02530       if this is slave native */
02531    for (x = 0; x < MAX_SLAVES; x++) {
02532       if (p->slaves[x]) {
02533          if (useslavenative)
02534             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02535          else {
02536             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02537             needconf++;
02538          }
02539       }
02540    }
02541    /* If we're supposed to be in there, do so now */
02542    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02543       if (useslavenative)
02544          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02545       else {
02546          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02547          needconf++;
02548       }
02549    }
02550    /* If we have a master, add ourselves to his conference */
02551    if (p->master) {
02552       if (isslavenative(p->master, NULL)) {
02553          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02554       } else {
02555          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02556       }
02557    }
02558    if (!needconf) {
02559       /* Nobody is left (or should be left) in our conference.
02560          Kill it. */
02561       p->confno = -1;
02562    }
02563 
02564    return 0;
02565 }
02566 
02567 static int check_for_conference(struct dahdi_pvt *p);
02568 
02569 static int my_check_for_conference(void *pvt)
02570 {
02571    struct dahdi_pvt *p = pvt;
02572    return check_for_conference(p);
02573 }
02574 
02575 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)
02576 {
02577    struct dahdi_pvt *p = pvt;
02578    int da, db;
02579    int tchan;
02580    int tinthreeway;
02581 
02582    da = analogsub_to_dahdisub(a);
02583    db = analogsub_to_dahdisub(b);
02584 
02585    tchan = p->subs[da].chan;
02586    p->subs[da].chan = p->subs[db].chan;
02587    p->subs[db].chan = tchan;
02588 
02589    tinthreeway = p->subs[da].inthreeway;
02590    p->subs[da].inthreeway = p->subs[db].inthreeway;
02591    p->subs[db].inthreeway = tinthreeway;
02592 
02593    p->subs[da].owner = ast_a;
02594    p->subs[db].owner = ast_b;
02595 
02596    if (ast_a)
02597       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02598    if (ast_b)
02599       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02600 
02601    wakeup_sub(p, a);
02602    wakeup_sub(p, b);
02603 
02604    return;
02605 }
02606 
02607 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02608 
02609 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02610 {
02611    struct dahdi_pvt *p = pvt;
02612    int dsub = analogsub_to_dahdisub(sub);
02613 
02614    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02615 }
02616 
02617 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02618 static int dahdi_setlaw(int dfd, int law)
02619 {
02620    int res;
02621    res = ioctl(dfd, DAHDI_SETLAW, &law);
02622    if (res)
02623       return res;
02624    return 0;
02625 }
02626 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02627 
02628 #if defined(HAVE_PRI)
02629 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)
02630 {
02631    struct dahdi_pvt *p = pvt;
02632    int audio;
02633    int newlaw = -1;
02634 
02635    switch (p->sig) {
02636    case SIG_PRI_LIB_HANDLE_CASES:
02637       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02638          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02639          break;
02640       }
02641       /* Fall through */
02642    default:
02643       /* Set to audio mode at this point */
02644       audio = 1;
02645       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02646          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02647             p->channel, audio, strerror(errno));
02648       }
02649       break;
02650    }
02651 
02652    if (law != SIG_PRI_DEFLAW) {
02653       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02654    }
02655 
02656    ast_copy_string(p->exten, exten, sizeof(p->exten));
02657 
02658    switch (law) {
02659       case SIG_PRI_DEFLAW:
02660          newlaw = 0;
02661          break;
02662       case SIG_PRI_ALAW:
02663          newlaw = DAHDI_LAW_ALAW;
02664          break;
02665       case SIG_PRI_ULAW:
02666          newlaw = DAHDI_LAW_MULAW;
02667          break;
02668    }
02669    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02670 }
02671 #endif   /* defined(HAVE_PRI) */
02672 
02673 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02674 
02675 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02676 /*!
02677  * \internal
02678  * \brief Open the PRI/SS7 channel media path.
02679  * \since 1.8
02680  *
02681  * \param p Channel private control structure.
02682  *
02683  * \return Nothing
02684  */
02685 static void my_pri_ss7_open_media(void *p)
02686 {
02687    struct dahdi_pvt *pvt = p;
02688    int res;
02689    int dfd;
02690    int set_val;
02691 
02692    dfd = pvt->subs[SUB_REAL].dfd;
02693 
02694    /* Open the media path. */
02695    set_val = 1;
02696    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02697    if (res < 0) {
02698       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02699          pvt->channel, strerror(errno));
02700    }
02701 
02702    /* Set correct companding law for this call. */
02703    res = dahdi_setlaw(dfd, pvt->law);
02704    if (res < 0) {
02705       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02706    }
02707 
02708    /* Set correct gain for this call. */
02709    if (pvt->digital) {
02710       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02711    } else {
02712       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02713          pvt->law);
02714    }
02715    if (res < 0) {
02716       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02717    }
02718 
02719    if (pvt->dsp_features && pvt->dsp) {
02720       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02721       pvt->dsp_features = 0;
02722    }
02723 }
02724 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02725 
02726 #if defined(HAVE_PRI)
02727 /*!
02728  * \internal
02729  * \brief Ask DAHDI to dial the given dial string.
02730  * \since 1.8.11
02731  *
02732  * \param p Channel private control structure.
02733  * \param dial_string String to pass to DAHDI to dial.
02734  *
02735  * \note The channel private lock needs to be held when calling.
02736  *
02737  * \return Nothing
02738  */
02739 static void my_pri_dial_digits(void *p, const char *dial_string)
02740 {
02741    struct dahdi_dialoperation zo = {
02742       .op = DAHDI_DIAL_OP_APPEND,
02743    };
02744    struct dahdi_pvt *pvt = p;
02745    int res;
02746 
02747    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02748    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02749    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02750    if (res) {
02751       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02752          pvt->channel, dial_string, strerror(errno));
02753    } else {
02754       pvt->dialing = 1;
02755    }
02756 }
02757 #endif   /* defined(HAVE_PRI) */
02758 
02759 static int unalloc_sub(struct dahdi_pvt *p, int x);
02760 
02761 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02762 {
02763    struct dahdi_pvt *p = pvt;
02764 
02765    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02766 }
02767 
02768 static int alloc_sub(struct dahdi_pvt *p, int x);
02769 
02770 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02771 {
02772    struct dahdi_pvt *p = pvt;
02773 
02774    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02775 }
02776 
02777 static int has_voicemail(struct dahdi_pvt *p);
02778 
02779 static int my_has_voicemail(void *pvt)
02780 {
02781    struct dahdi_pvt *p = pvt;
02782 
02783    return has_voicemail(p);
02784 }
02785 
02786 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02787 {
02788    struct dahdi_pvt *p = pvt;
02789    int index;
02790 
02791    index = analogsub_to_dahdisub(sub);
02792 
02793    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02794 }
02795 
02796 static enum analog_event dahdievent_to_analogevent(int event)
02797 {
02798    enum analog_event res;
02799 
02800    switch (event) {
02801    case DAHDI_EVENT_ONHOOK:
02802       res = ANALOG_EVENT_ONHOOK;
02803       break;
02804    case DAHDI_EVENT_RINGOFFHOOK:
02805       res = ANALOG_EVENT_RINGOFFHOOK;
02806       break;
02807    case DAHDI_EVENT_WINKFLASH:
02808       res = ANALOG_EVENT_WINKFLASH;
02809       break;
02810    case DAHDI_EVENT_ALARM:
02811       res = ANALOG_EVENT_ALARM;
02812       break;
02813    case DAHDI_EVENT_NOALARM:
02814       res = ANALOG_EVENT_NOALARM;
02815       break;
02816    case DAHDI_EVENT_DIALCOMPLETE:
02817       res = ANALOG_EVENT_DIALCOMPLETE;
02818       break;
02819    case DAHDI_EVENT_RINGERON:
02820       res = ANALOG_EVENT_RINGERON;
02821       break;
02822    case DAHDI_EVENT_RINGEROFF:
02823       res = ANALOG_EVENT_RINGEROFF;
02824       break;
02825    case DAHDI_EVENT_HOOKCOMPLETE:
02826       res = ANALOG_EVENT_HOOKCOMPLETE;
02827       break;
02828    case DAHDI_EVENT_PULSE_START:
02829       res = ANALOG_EVENT_PULSE_START;
02830       break;
02831    case DAHDI_EVENT_POLARITY:
02832       res = ANALOG_EVENT_POLARITY;
02833       break;
02834    case DAHDI_EVENT_RINGBEGIN:
02835       res = ANALOG_EVENT_RINGBEGIN;
02836       break;
02837    case DAHDI_EVENT_EC_DISABLED:
02838       res = ANALOG_EVENT_EC_DISABLED;
02839       break;
02840    case DAHDI_EVENT_REMOVED:
02841       res = ANALOG_EVENT_REMOVED;
02842       break;
02843    case DAHDI_EVENT_NEONMWI_ACTIVE:
02844       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02845       break;
02846    case DAHDI_EVENT_NEONMWI_INACTIVE:
02847       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02848       break;
02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02850    case DAHDI_EVENT_TX_CED_DETECTED:
02851       res = ANALOG_EVENT_TX_CED_DETECTED;
02852       break;
02853    case DAHDI_EVENT_RX_CED_DETECTED:
02854       res = ANALOG_EVENT_RX_CED_DETECTED;
02855       break;
02856    case DAHDI_EVENT_EC_NLP_DISABLED:
02857       res = ANALOG_EVENT_EC_NLP_DISABLED;
02858       break;
02859    case DAHDI_EVENT_EC_NLP_ENABLED:
02860       res = ANALOG_EVENT_EC_NLP_ENABLED;
02861       break;
02862 #endif
02863    case DAHDI_EVENT_PULSEDIGIT:
02864       res = ANALOG_EVENT_PULSEDIGIT;
02865       break;
02866    case DAHDI_EVENT_DTMFDOWN:
02867       res = ANALOG_EVENT_DTMFDOWN;
02868       break;
02869    case DAHDI_EVENT_DTMFUP:
02870       res = ANALOG_EVENT_DTMFUP;
02871       break;
02872    default:
02873       switch(event & 0xFFFF0000) {
02874       case DAHDI_EVENT_PULSEDIGIT:
02875       case DAHDI_EVENT_DTMFDOWN:
02876       case DAHDI_EVENT_DTMFUP:
02877          /* The event includes a digit number in the low word.
02878           * Converting it to a 'enum analog_event' would remove
02879           * that information. Thus it is returned as-is.
02880           */
02881          return event;
02882       }
02883 
02884       res = ANALOG_EVENT_ERROR;
02885       break;
02886    }
02887 
02888    return res;
02889 }
02890 
02891 static inline int dahdi_wait_event(int fd);
02892 
02893 static int my_wait_event(void *pvt)
02894 {
02895    struct dahdi_pvt *p = pvt;
02896 
02897    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02898 }
02899 
02900 static int my_get_event(void *pvt)
02901 {
02902    struct dahdi_pvt *p = pvt;
02903    int res;
02904 
02905    if (p->fake_event) {
02906       res = p->fake_event;
02907       p->fake_event = 0;
02908    } else
02909       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02910 
02911    return dahdievent_to_analogevent(res);
02912 }
02913 
02914 static int my_is_off_hook(void *pvt)
02915 {
02916    struct dahdi_pvt *p = pvt;
02917    int res;
02918    struct dahdi_params par;
02919 
02920    memset(&par, 0, sizeof(par));
02921 
02922    if (p->subs[SUB_REAL].dfd > -1)
02923       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02924    else {
02925       /* Assume not off hook on CVRS */
02926       res = 0;
02927       par.rxisoffhook = 0;
02928    }
02929    if (res) {
02930       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02931    }
02932 
02933    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02934       /* When "onhook" that means no battery on the line, and thus
02935       it is out of service..., if it's on a TDM card... If it's a channel
02936       bank, there is no telling... */
02937       return (par.rxbits > -1) || par.rxisoffhook;
02938    }
02939 
02940    return par.rxisoffhook;
02941 }
02942 
02943 static void dahdi_enable_ec(struct dahdi_pvt *p);
02944 static void dahdi_disable_ec(struct dahdi_pvt *p);
02945 
02946 static int my_set_echocanceller(void *pvt, int enable)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    if (enable)
02951       dahdi_enable_ec(p);
02952    else
02953       dahdi_disable_ec(p);
02954 
02955    return 0;
02956 }
02957 
02958 static int dahdi_ring_phone(struct dahdi_pvt *p);
02959 
02960 static int my_ring(void *pvt)
02961 {
02962    struct dahdi_pvt *p = pvt;
02963 
02964    return dahdi_ring_phone(p);
02965 }
02966 
02967 static int my_flash(void *pvt)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970    int func = DAHDI_FLASH;
02971    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02972 }
02973 
02974 static inline int dahdi_set_hook(int fd, int hs);
02975 
02976 static int my_off_hook(void *pvt)
02977 {
02978    struct dahdi_pvt *p = pvt;
02979    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02980 }
02981 
02982 static void my_set_needringing(void *pvt, int value)
02983 {
02984    struct dahdi_pvt *p = pvt;
02985    p->subs[SUB_REAL].needringing = value;
02986 }
02987 
02988 static void my_set_polarity(void *pvt, int value)
02989 {
02990    struct dahdi_pvt *p = pvt;
02991 
02992    if (p->channel == CHAN_PSEUDO) {
02993       return;
02994    }
02995    p->polarity = value;
02996    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02997 }
02998 
02999 static void my_start_polarityswitch(void *pvt)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03004       my_set_polarity(pvt, 0);
03005    }
03006 }
03007 
03008 static void my_answer_polarityswitch(void *pvt)
03009 {
03010    struct dahdi_pvt *p = pvt;
03011 
03012    if (!p->answeronpolarityswitch) {
03013       return;
03014    }
03015 
03016    my_set_polarity(pvt, 1);
03017 }
03018 
03019 static void my_hangup_polarityswitch(void *pvt)
03020 {
03021    struct dahdi_pvt *p = pvt;
03022 
03023    if (!p->hanguponpolarityswitch) {
03024       return;
03025    }
03026 
03027    if (p->answeronpolarityswitch) {
03028       my_set_polarity(pvt, 0);
03029    } else {
03030       my_set_polarity(pvt, 1);
03031    }
03032 }
03033 
03034 static int my_start(void *pvt)
03035 {
03036    struct dahdi_pvt *p = pvt;
03037    int x = DAHDI_START;
03038 
03039    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03040 }
03041 
03042 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03043 {
03044    int index = analogsub_to_dahdisub(sub);
03045    int res;
03046    struct dahdi_pvt *p = pvt;
03047    struct dahdi_dialoperation ddop;
03048 
03049    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03050       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03051       return -1;
03052    }
03053 
03054    if (sub != ANALOG_SUB_REAL) {
03055       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03056          dop->dialstr, p->channel, sub);
03057       return -1;
03058    }
03059 
03060    ddop.op = DAHDI_DIAL_OP_REPLACE;
03061    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03062 
03063    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03064 
03065    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03066    if (res == -1) {
03067       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03068    }
03069 
03070    return res;
03071 }
03072 
03073 static void dahdi_train_ec(struct dahdi_pvt *p);
03074 
03075 static int my_train_echocanceller(void *pvt)
03076 {
03077    struct dahdi_pvt *p = pvt;
03078 
03079    dahdi_train_ec(p);
03080 
03081    return 0;
03082 }
03083 
03084 static int my_is_dialing(void *pvt, enum analog_sub sub)
03085 {
03086    struct dahdi_pvt *p = pvt;
03087    int index;
03088    int x;
03089 
03090    index = analogsub_to_dahdisub(sub);
03091 
03092    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03093       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03094       return -1;
03095    }
03096 
03097    return x;
03098 }
03099 
03100 static int my_on_hook(void *pvt)
03101 {
03102    struct dahdi_pvt *p = pvt;
03103    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03104 }
03105 
03106 #if defined(HAVE_PRI)
03107 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03108 {
03109    struct dahdi_pvt *old_chan = chan_old;
03110    struct dahdi_pvt *new_chan = chan_new;
03111 
03112    new_chan->owner = old_chan->owner;
03113    old_chan->owner = NULL;
03114    if (new_chan->owner) {
03115       new_chan->owner->tech_pvt = new_chan;
03116       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03117       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03118       old_chan->subs[SUB_REAL].owner = NULL;
03119    }
03120    /* Copy any DSP that may be present */
03121    new_chan->dsp = old_chan->dsp;
03122    new_chan->dsp_features = old_chan->dsp_features;
03123    old_chan->dsp = NULL;
03124    old_chan->dsp_features = 0;
03125 
03126    /* Transfer flags from the old channel. */
03127    new_chan->dialing = old_chan->dialing;
03128    new_chan->digital = old_chan->digital;
03129    new_chan->outgoing = old_chan->outgoing;
03130    old_chan->dialing = 0;
03131    old_chan->digital = 0;
03132    old_chan->outgoing = 0;
03133 
03134    /* More stuff to transfer to the new channel. */
03135    new_chan->law = old_chan->law;
03136    strcpy(new_chan->dialstring, old_chan->dialstring);
03137 }
03138 #endif   /* defined(HAVE_PRI) */
03139 
03140 #if defined(HAVE_PRI)
03141 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03142 {
03143    switch (tone) {
03144    case SIG_PRI_TONE_RINGTONE:
03145       return DAHDI_TONE_RINGTONE;
03146    case SIG_PRI_TONE_STUTTER:
03147       return DAHDI_TONE_STUTTER;
03148    case SIG_PRI_TONE_CONGESTION:
03149       return DAHDI_TONE_CONGESTION;
03150    case SIG_PRI_TONE_DIALTONE:
03151       return DAHDI_TONE_DIALTONE;
03152    case SIG_PRI_TONE_DIALRECALL:
03153       return DAHDI_TONE_DIALRECALL;
03154    case SIG_PRI_TONE_INFO:
03155       return DAHDI_TONE_INFO;
03156    case SIG_PRI_TONE_BUSY:
03157       return DAHDI_TONE_BUSY;
03158    default:
03159       return -1;
03160    }
03161 }
03162 #endif   /* defined(HAVE_PRI) */
03163 
03164 #if defined(HAVE_PRI)
03165 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03166 {
03167    int x;
03168 
03169    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03170    switch (x) {
03171    case DAHDI_EVENT_NONE:
03172       break;
03173    case DAHDI_EVENT_ALARM:
03174    case DAHDI_EVENT_NOALARM:
03175       if (sig_pri_is_alarm_ignored(pri)) {
03176          break;
03177       }
03178       /* Fall through */
03179    default:
03180       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03181          event2str(x), x, pri->span);
03182       break;
03183    }
03184    /* Keep track of alarm state */
03185    switch (x) {
03186    case DAHDI_EVENT_ALARM:
03187       pri_event_alarm(pri, index, 0);
03188       break;
03189    case DAHDI_EVENT_NOALARM:
03190       pri_event_noalarm(pri, index, 0);
03191       break;
03192    default:
03193       break;
03194    }
03195 }
03196 #endif   /* defined(HAVE_PRI) */
03197 
03198 #if defined(HAVE_PRI)
03199 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03200 {
03201    struct dahdi_pvt *p = pvt;
03202 
03203    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03204 }
03205 #endif   /* defined(HAVE_PRI) */
03206 
03207 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03208 /*!
03209  * \internal
03210  * \brief Set the caller id information.
03211  * \since 1.8
03212  *
03213  * \param pvt DAHDI private structure
03214  * \param caller Caller-id information to set.
03215  *
03216  * \return Nothing
03217  */
03218 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03219 {
03220    struct dahdi_pvt *p = pvt;
03221 
03222    ast_copy_string(p->cid_num,
03223       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03224       sizeof(p->cid_num));
03225    ast_copy_string(p->cid_name,
03226       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03227       sizeof(p->cid_name));
03228    ast_copy_string(p->cid_subaddr,
03229       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03230       sizeof(p->cid_subaddr));
03231    p->cid_ton = caller->id.number.plan;
03232    p->callingpres = ast_party_id_presentation(&caller->id);
03233    if (caller->id.tag) {
03234       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03235    }
03236    ast_copy_string(p->cid_ani,
03237       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03238       sizeof(p->cid_ani));
03239    p->cid_ani2 = caller->ani2;
03240 }
03241 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03242 
03243 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03244 /*!
03245  * \internal
03246  * \brief Set the Dialed Number Identifier.
03247  * \since 1.8
03248  *
03249  * \param pvt DAHDI private structure
03250  * \param dnid Dialed Number Identifier string.
03251  *
03252  * \return Nothing
03253  */
03254 static void my_set_dnid(void *pvt, const char *dnid)
03255 {
03256    struct dahdi_pvt *p = pvt;
03257 
03258    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03259 }
03260 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03261 
03262 #if defined(HAVE_PRI)
03263 /*!
03264  * \internal
03265  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03266  * \since 1.8
03267  *
03268  * \param pvt DAHDI private structure
03269  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03270  *
03271  * \return Nothing
03272  */
03273 static void my_set_rdnis(void *pvt, const char *rdnis)
03274 {
03275    struct dahdi_pvt *p = pvt;
03276 
03277    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03278 }
03279 #endif   /* defined(HAVE_PRI) */
03280 
03281 #if defined(HAVE_PRI)
03282 /*!
03283  * \internal
03284  * \brief Make a dialstring for native ISDN CC to recall properly.
03285  * \since 1.8
03286  *
03287  * \param priv Channel private control structure.
03288  * \param buf Where to put the modified dialstring.
03289  * \param buf_size Size of modified dialstring buffer.
03290  *
03291  * \details
03292  * original dialstring:
03293  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03294  *
03295  * The modified dialstring will have prefixed the channel-group section
03296  * with the ISDN channel restriction.
03297  *
03298  * buf:
03299  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03300  *
03301  * The routine will check to see if the ISDN channel restriction is already
03302  * in the original dialstring.
03303  *
03304  * \return Nothing
03305  */
03306 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03307 {
03308    char *dial;
03309    struct dahdi_pvt *pvt;
03310    AST_DECLARE_APP_ARGS(args,
03311       AST_APP_ARG(tech);   /* channel technology token */
03312       AST_APP_ARG(group);  /* channel/group token */
03313       //AST_APP_ARG(ext);  /* extension token */
03314       //AST_APP_ARG(opts); /* options token */
03315       //AST_APP_ARG(other);   /* Any remining unused arguments */
03316    );
03317 
03318    pvt = priv;
03319    dial = ast_strdupa(pvt->dialstring);
03320    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03321    if (!args.tech) {
03322       ast_copy_string(buf, pvt->dialstring, buf_size);
03323       return;
03324    }
03325    if (!args.group) {
03326       /* Append the ISDN span channel restriction to the dialstring. */
03327       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03328       return;
03329    }
03330    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03331       /* The ISDN span channel restriction is not needed or already
03332        * in the dialstring. */
03333       ast_copy_string(buf, pvt->dialstring, buf_size);
03334       return;
03335    }
03336    /* Insert the ISDN span channel restriction into the dialstring. */
03337    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03338 }
03339 #endif   /* defined(HAVE_PRI) */
03340 
03341 #if defined(HAVE_PRI)
03342 /*!
03343  * \internal
03344  * \brief Reevaluate the PRI span device state.
03345  * \since 1.8
03346  *
03347  * \param pri Asterisk D channel control structure.
03348  *
03349  * \return Nothing
03350  *
03351  * \note Assumes the pri->lock is already obtained.
03352  */
03353 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03354 {
03355    unsigned idx;
03356    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03357    unsigned in_use;     /* Number of B channels in use on the span. */
03358    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03359    enum ast_device_state new_state;
03360 
03361    /* Count the number of B channels and the number of B channels in use. */
03362    num_b_chans = 0;
03363    in_use = 0;
03364    in_alarm = 1;
03365    for (idx = pri->numchans; idx--;) {
03366       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03367          /* This is a B channel interface. */
03368          ++num_b_chans;
03369          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03370             ++in_use;
03371          }
03372          if (!pri->pvts[idx]->inalarm) {
03373             /* There is a channel that is not in alarm. */
03374             in_alarm = 0;
03375          }
03376       }
03377    }
03378 
03379    /* Update the span congestion device state and report any change. */
03380    if (in_alarm) {
03381       new_state = AST_DEVICE_UNAVAILABLE;
03382    } else {
03383       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03384    }
03385    if (pri->congestion_devstate != new_state) {
03386       pri->congestion_devstate = new_state;
03387       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03388    }
03389 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03390    /* Update the span threshold device state and report any change. */
03391    if (in_alarm) {
03392       new_state = AST_DEVICE_UNAVAILABLE;
03393    } else if (!in_use) {
03394       new_state = AST_DEVICE_NOT_INUSE;
03395    } else if (!pri->user_busy_threshold) {
03396       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03397    } else {
03398       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03399          : AST_DEVICE_BUSY;
03400    }
03401    if (pri->threshold_devstate != new_state) {
03402       pri->threshold_devstate = new_state;
03403       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03404    }
03405 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03406 }
03407 #endif   /* defined(HAVE_PRI) */
03408 
03409 #if defined(HAVE_PRI)
03410 /*!
03411  * \internal
03412  * \brief Reference this module.
03413  * \since 1.8
03414  *
03415  * \return Nothing
03416  */
03417 static void my_module_ref(void)
03418 {
03419    ast_module_ref(ast_module_info->self);
03420 }
03421 #endif   /* defined(HAVE_PRI) */
03422 
03423 #if defined(HAVE_PRI)
03424 /*!
03425  * \internal
03426  * \brief Unreference this module.
03427  * \since 1.8
03428  *
03429  * \return Nothing
03430  */
03431 static void my_module_unref(void)
03432 {
03433    ast_module_unref(ast_module_info->self);
03434 }
03435 #endif   /* defined(HAVE_PRI) */
03436 
03437 #if defined(HAVE_PRI)
03438 #if defined(HAVE_PRI_CALL_WAITING)
03439 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03440 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03441 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03442 
03443 static struct sig_pri_callback dahdi_pri_callbacks =
03444 {
03445    .handle_dchan_exception = my_handle_dchan_exception,
03446    .play_tone = my_pri_play_tone,
03447    .set_echocanceller = my_set_echocanceller,
03448    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03449    .lock_private = my_lock_private,
03450    .unlock_private = my_unlock_private,
03451    .new_ast_channel = my_new_pri_ast_channel,
03452    .fixup_chans = my_pri_fixup_chans,
03453    .set_alarm = my_set_alarm,
03454    .set_dialing = my_set_dialing,
03455    .set_outgoing = my_set_outgoing,
03456    .set_digital = my_set_digital,
03457    .set_callerid = my_set_callerid,
03458    .set_dnid = my_set_dnid,
03459    .set_rdnis = my_set_rdnis,
03460    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03461 #if defined(HAVE_PRI_CALL_WAITING)
03462    .init_config = my_pri_init_config,
03463 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03464    .get_orig_dialstring = my_get_orig_dialstring,
03465    .make_cc_dialstring = my_pri_make_cc_dialstring,
03466    .update_span_devstate = dahdi_pri_update_span_devstate,
03467    .module_ref = my_module_ref,
03468    .module_unref = my_module_unref,
03469    .dial_digits = my_pri_dial_digits,
03470    .open_media = my_pri_ss7_open_media,
03471    .ami_channel_event = my_ami_channel_event,
03472 };
03473 #endif   /* defined(HAVE_PRI) */
03474 
03475 #if defined(HAVE_SS7)
03476 /*!
03477  * \internal
03478  * \brief Handle the SS7 link exception.
03479  * \since 1.8
03480  *
03481  * \param linkset Controlling linkset for the channel.
03482  * \param which Link index of the signaling channel.
03483  *
03484  * \return Nothing
03485  */
03486 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03487 {
03488    int event;
03489 
03490    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03491       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03492          linkset->span, which);
03493       return;
03494    }
03495    switch (event) {
03496    case DAHDI_EVENT_NONE:
03497       break;
03498    case DAHDI_EVENT_ALARM:
03499       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03500          event2str(event), event, linkset->span, which);
03501       sig_ss7_link_alarm(linkset, which);
03502       break;
03503    case DAHDI_EVENT_NOALARM:
03504       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03505          event2str(event), event, linkset->span, which);
03506       sig_ss7_link_noalarm(linkset, which);
03507       break;
03508    default:
03509       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03510          event2str(event), event, linkset->span, which);
03511       break;
03512    }
03513 }
03514 #endif   /* defined(HAVE_SS7) */
03515 
03516 #if defined(HAVE_SS7)
03517 static void my_ss7_set_loopback(void *pvt, int enable)
03518 {
03519    struct dahdi_pvt *p = pvt;
03520 
03521    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03522       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03523          strerror(errno));
03524    }
03525 }
03526 #endif   /* defined(HAVE_SS7) */
03527 
03528 #if defined(HAVE_SS7)
03529 /*!
03530  * \internal
03531  * \brief Create a new asterisk channel structure for SS7.
03532  * \since 1.8
03533  *
03534  * \param pvt Private channel structure.
03535  * \param state Initial state of new channel.
03536  * \param law Combanding law to use.
03537  * \param exten Dialplan extension for incoming call.
03538  * \param requestor Channel requesting this new channel.
03539  *
03540  * \retval ast_channel on success.
03541  * \retval NULL on error.
03542  */
03543 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)
03544 {
03545    struct dahdi_pvt *p = pvt;
03546    int audio;
03547    int newlaw;
03548 
03549    /* Set to audio mode at this point */
03550    audio = 1;
03551    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03552       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03553          p->channel, audio, strerror(errno));
03554 
03555    if (law != SIG_SS7_DEFLAW) {
03556       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03557          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03558    }
03559 
03560    ast_copy_string(p->exten, exten, sizeof(p->exten));
03561 
03562    newlaw = -1;
03563    switch (law) {
03564    case SIG_SS7_DEFLAW:
03565       newlaw = 0;
03566       break;
03567    case SIG_SS7_ALAW:
03568       newlaw = DAHDI_LAW_ALAW;
03569       break;
03570    case SIG_SS7_ULAW:
03571       newlaw = DAHDI_LAW_MULAW;
03572       break;
03573    }
03574    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03575 }
03576 #endif   /* defined(HAVE_SS7) */
03577 
03578 #if defined(HAVE_SS7)
03579 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03580 {
03581    switch (tone) {
03582    case SIG_SS7_TONE_RINGTONE:
03583       return DAHDI_TONE_RINGTONE;
03584    case SIG_SS7_TONE_STUTTER:
03585       return DAHDI_TONE_STUTTER;
03586    case SIG_SS7_TONE_CONGESTION:
03587       return DAHDI_TONE_CONGESTION;
03588    case SIG_SS7_TONE_DIALTONE:
03589       return DAHDI_TONE_DIALTONE;
03590    case SIG_SS7_TONE_DIALRECALL:
03591       return DAHDI_TONE_DIALRECALL;
03592    case SIG_SS7_TONE_INFO:
03593       return DAHDI_TONE_INFO;
03594    case SIG_SS7_TONE_BUSY:
03595       return DAHDI_TONE_BUSY;
03596    default:
03597       return -1;
03598    }
03599 }
03600 #endif   /* defined(HAVE_SS7) */
03601 
03602 #if defined(HAVE_SS7)
03603 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03604 {
03605    struct dahdi_pvt *p = pvt;
03606 
03607    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03608 }
03609 #endif   /* defined(HAVE_SS7) */
03610 
03611 #if defined(HAVE_SS7)
03612 static struct sig_ss7_callback dahdi_ss7_callbacks =
03613 {
03614    .lock_private = my_lock_private,
03615    .unlock_private = my_unlock_private,
03616 
03617    .set_echocanceller = my_set_echocanceller,
03618    .set_loopback = my_ss7_set_loopback,
03619 
03620    .new_ast_channel = my_new_ss7_ast_channel,
03621    .play_tone = my_ss7_play_tone,
03622 
03623    .handle_link_exception = my_handle_link_exception,
03624    .set_alarm = my_set_alarm,
03625    .set_dialing = my_set_dialing,
03626    .set_outgoing = my_set_outgoing,
03627    .set_digital = my_set_digital,
03628    .set_inservice = my_set_inservice,
03629    .set_locallyblocked = my_set_locallyblocked,
03630    .set_remotelyblocked = my_set_remotelyblocked,
03631    .set_callerid = my_set_callerid,
03632    .set_dnid = my_set_dnid,
03633    .open_media = my_pri_ss7_open_media,
03634 };
03635 #endif   /* defined(HAVE_SS7) */
03636 
03637 /*!
03638  * \brief Send MWI state change
03639  *
03640  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03641  *      MWI state has changed on.
03642  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03643  *      whether there are messages waiting or not.
03644  *
03645  *  \return nothing
03646  *
03647  * This function does two things:
03648  *
03649  * 1) It generates an internal Asterisk event notifying any other module that
03650  *    cares about MWI that the state of a mailbox has changed.
03651  *
03652  * 2) It runs the script specified by the mwimonitornotify option to allow
03653  *    some custom handling of the state change.
03654  */
03655 static void notify_message(char *mailbox_full, int thereornot)
03656 {
03657    char s[sizeof(mwimonitornotify) + 80];
03658    struct ast_event *event;
03659    char *mailbox, *context;
03660 
03661    /* Strip off @default */
03662    context = mailbox = ast_strdupa(mailbox_full);
03663    strsep(&context, "@");
03664    if (ast_strlen_zero(context))
03665       context = "default";
03666 
03667    if (!(event = ast_event_new(AST_EVENT_MWI,
03668          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03669          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03670          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03671          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03672          AST_EVENT_IE_END))) {
03673       return;
03674    }
03675 
03676    ast_event_queue_and_cache(event);
03677 
03678    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03679       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03680       ast_safe_system(s);
03681    }
03682 }
03683 
03684 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03685 {
03686    struct dahdi_pvt *p = pvt;
03687 
03688    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03689       return;
03690 
03691    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03692       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03693       notify_message(p->mailbox, 1);
03694    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03695       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03696       notify_message(p->mailbox, 0);
03697    }
03698    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03699    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03700    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03701       ast_hangup(chan);
03702       return;
03703    }
03704 }
03705 
03706 static int my_have_progressdetect(void *pvt)
03707 {
03708    struct dahdi_pvt *p = pvt;
03709 
03710    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03711       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03712       return 1;
03713    } else {
03714       /* Don't have progress detection. */
03715       return 0;
03716    }
03717 }
03718 
03719 static struct analog_callback dahdi_analog_callbacks =
03720 {
03721    .play_tone = my_play_tone,
03722    .get_event = my_get_event,
03723    .wait_event = my_wait_event,
03724    .is_off_hook = my_is_off_hook,
03725    .set_echocanceller = my_set_echocanceller,
03726    .ring = my_ring,
03727    .flash = my_flash,
03728    .off_hook = my_off_hook,
03729    .dial_digits = my_dial_digits,
03730    .train_echocanceller = my_train_echocanceller,
03731    .on_hook = my_on_hook,
03732    .is_dialing = my_is_dialing,
03733    .allocate_sub = my_allocate_sub,
03734    .unallocate_sub = my_unallocate_sub,
03735    .swap_subs = my_swap_subchannels,
03736    .has_voicemail = my_has_voicemail,
03737    .check_for_conference = my_check_for_conference,
03738    .conf_add = my_conf_add,
03739    .conf_del = my_conf_del,
03740    .complete_conference_update = my_complete_conference_update,
03741    .start = my_start,
03742    .all_subchannels_hungup = my_all_subchannels_hungup,
03743    .lock_private = my_lock_private,
03744    .unlock_private = my_unlock_private,
03745    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03746    .handle_dtmf = my_handle_dtmf,
03747    .wink = my_wink,
03748    .new_ast_channel = my_new_analog_ast_channel,
03749    .dsp_set_digitmode = my_dsp_set_digitmode,
03750    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03751    .send_callerid = my_send_callerid,
03752    .callwait = my_callwait,
03753    .stop_callwait = my_stop_callwait,
03754    .get_callerid = my_get_callerid,
03755    .start_cid_detect = my_start_cid_detect,
03756    .stop_cid_detect = my_stop_cid_detect,
03757    .handle_notify_message = my_handle_notify_message,
03758    .increase_ss_count = my_increase_ss_count,
03759    .decrease_ss_count = my_decrease_ss_count,
03760    .distinctive_ring = my_distinctive_ring,
03761    .set_linear_mode = my_set_linear_mode,
03762    .set_inthreeway = my_set_inthreeway,
03763    .get_and_handle_alarms = my_get_and_handle_alarms,
03764    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03765    .get_sub_fd = my_get_sub_fd,
03766    .set_cadence = my_set_cadence,
03767    .set_alarm = my_set_alarm,
03768    .set_dialing = my_set_dialing,
03769    .set_outgoing = my_set_outgoing,
03770    .set_ringtimeout = my_set_ringtimeout,
03771    .set_waitingfordt = my_set_waitingfordt,
03772    .check_waitingfordt = my_check_waitingfordt,
03773    .set_confirmanswer = my_set_confirmanswer,
03774    .check_confirmanswer = my_check_confirmanswer,
03775    .set_callwaiting = my_set_callwaiting,
03776    .cancel_cidspill = my_cancel_cidspill,
03777    .confmute = my_confmute,
03778    .set_pulsedial = my_set_pulsedial,
03779    .set_new_owner = my_set_new_owner,
03780    .get_orig_dialstring = my_get_orig_dialstring,
03781    .set_needringing = my_set_needringing,
03782    .set_polarity = my_set_polarity,
03783    .start_polarityswitch = my_start_polarityswitch,
03784    .answer_polarityswitch = my_answer_polarityswitch,
03785    .hangup_polarityswitch = my_hangup_polarityswitch,
03786    .have_progressdetect = my_have_progressdetect,
03787 };
03788 
03789 /*! Round robin search locations. */
03790 static struct dahdi_pvt *round_robin[32];
03791 
03792 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03793 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03794 {
03795    int res;
03796    if (p->subs[SUB_REAL].owner == ast)
03797       res = 0;
03798    else if (p->subs[SUB_CALLWAIT].owner == ast)
03799       res = 1;
03800    else if (p->subs[SUB_THREEWAY].owner == ast)
03801       res = 2;
03802    else {
03803       res = -1;
03804       if (!nullok)
03805          ast_log(LOG_WARNING,
03806             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03807             ast ? ast->name : "", p->channel, fname, line);
03808    }
03809    return res;
03810 }
03811 
03812 /*!
03813  * \internal
03814  * \brief Obtain the specified subchannel owner lock if the owner exists.
03815  *
03816  * \param pvt Channel private struct.
03817  * \param sub_idx Subchannel owner to lock.
03818  *
03819  * \note Assumes the pvt->lock is already obtained.
03820  *
03821  * \note
03822  * Because deadlock avoidance may have been necessary, you need to confirm
03823  * the state of things before continuing.
03824  *
03825  * \return Nothing
03826  */
03827 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03828 {
03829    for (;;) {
03830       if (!pvt->subs[sub_idx].owner) {
03831          /* No subchannel owner pointer */
03832          break;
03833       }
03834       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03835          /* Got subchannel owner lock */
03836          break;
03837       }
03838       /* We must unlock the private to avoid the possibility of a deadlock */
03839       DEADLOCK_AVOIDANCE(&pvt->lock);
03840    }
03841 }
03842 
03843 static void wakeup_sub(struct dahdi_pvt *p, int a)
03844 {
03845    dahdi_lock_sub_owner(p, a);
03846    if (p->subs[a].owner) {
03847       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03848       ast_channel_unlock(p->subs[a].owner);
03849    }
03850 }
03851 
03852 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03853 {
03854    for (;;) {
03855       if (p->owner) {
03856          if (ast_channel_trylock(p->owner)) {
03857             DEADLOCK_AVOIDANCE(&p->lock);
03858          } else {
03859             ast_queue_frame(p->owner, f);
03860             ast_channel_unlock(p->owner);
03861             break;
03862          }
03863       } else
03864          break;
03865    }
03866 }
03867 
03868 static void handle_clear_alarms(struct dahdi_pvt *p)
03869 {
03870 #if defined(HAVE_PRI)
03871    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03872       return;
03873    }
03874 #endif   /* defined(HAVE_PRI) */
03875 
03876    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03877       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03878       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03879    }
03880    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03881       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03882       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03883    }
03884 }
03885 
03886 #ifdef HAVE_OPENR2
03887 
03888 static int dahdi_r2_answer(struct dahdi_pvt *p)
03889 {
03890    int res = 0;
03891    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03892    * and does not has support for openr2_chan_answer_call_with_mode
03893    *  */
03894 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03895    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03896    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03897    if (!double_answer) {
03898       /* this still can result in double answer if the channel context
03899       * was configured that way */
03900       res = openr2_chan_answer_call(p->r2chan);
03901    } else if (wants_double_answer) {
03902       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03903    } else {
03904       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03905    }
03906 #else
03907    res = openr2_chan_answer_call(p->r2chan);
03908 #endif
03909    return res;
03910 }
03911 
03912 
03913 
03914 /* should be called with the ast_channel locked */
03915 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03916 {
03917    openr2_calling_party_category_t cat;
03918    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03919    struct dahdi_pvt *p = c->tech_pvt;
03920    if (ast_strlen_zero(catstr)) {
03921       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03922             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03923       return p->mfcr2_category;
03924    }
03925    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03926       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03927             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03928       return p->mfcr2_category;
03929    }
03930    ast_debug(1, "Using category %s\n", catstr);
03931    return cat;
03932 }
03933 
03934 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03935 {
03936    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03937    ast_mutex_lock(&p->lock);
03938    if (p->mfcr2call) {
03939       ast_mutex_unlock(&p->lock);
03940       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03941          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03942          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03943          the other end will see our seize as a forced release and drop the call, we will see an invalid
03944          pattern that will be seen and treated as protocol error. */
03945       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03946       return;
03947    }
03948    p->mfcr2call = 1;
03949    /* better safe than sorry ... */
03950    p->cid_name[0] = '\0';
03951    p->cid_num[0] = '\0';
03952    p->cid_subaddr[0] = '\0';
03953    p->rdnis[0] = '\0';
03954    p->exten[0] = '\0';
03955    p->mfcr2_ani_index = '\0';
03956    p->mfcr2_dnis_index = '\0';
03957    p->mfcr2_dnis_matched = 0;
03958    p->mfcr2_answer_pending = 0;
03959    p->mfcr2_call_accepted = 0;
03960    ast_mutex_unlock(&p->lock);
03961    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03962 }
03963 
03964 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03965 {
03966    int res;
03967    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03968    ast_mutex_lock(&p->lock);
03969    p->inalarm = alarm ? 1 : 0;
03970    if (p->inalarm) {
03971       res = get_alarms(p);
03972       handle_alarms(p, res);
03973    } else {
03974       handle_clear_alarms(p);
03975    }
03976    ast_mutex_unlock(&p->lock);
03977 }
03978 
03979 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03980 {
03981    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03982 }
03983 
03984 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03985 {
03986    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03987    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03988    if (p->owner) {
03989       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03990       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03991    }
03992    ast_mutex_lock(&p->lock);
03993    p->mfcr2call = 0;
03994    ast_mutex_unlock(&p->lock);
03995 }
03996 
03997 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03998 {
03999    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04000       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04001          p->channel, openr2_proto_get_disconnect_string(cause));
04002       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
04003       openr2_chan_set_idle(p->r2chan);
04004       ast_mutex_lock(&p->lock);
04005       p->mfcr2call = 0;
04006       ast_mutex_unlock(&p->lock);
04007    }
04008 }
04009 
04010 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04011 {
04012    struct dahdi_pvt *p;
04013    struct ast_channel *c;
04014    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04015          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04016          openr2_proto_get_category_string(category));
04017    p = openr2_chan_get_client_data(r2chan);
04018    /* if collect calls are not allowed and this is a collect call, reject it! */
04019    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04020       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04021       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04022       return;
04023    }
04024    ast_mutex_lock(&p->lock);
04025    p->mfcr2_recvd_category = category;
04026    /* if we're not supposed to use CID, clear whatever we have */
04027    if (!p->use_callerid) {
04028       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04029       p->cid_num[0] = 0;
04030       p->cid_name[0] = 0;
04031    }
04032    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04033    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04034       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04035       p->exten[0] = 's';
04036       p->exten[1] = 0;
04037    }
04038    ast_mutex_unlock(&p->lock);
04039    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04040       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04041             p->channel, p->exten, p->context);
04042       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04043       return;
04044    }
04045    if (!p->mfcr2_accept_on_offer) {
04046       /* The user wants us to start the PBX thread right away without accepting the call first */
04047       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04048       if (c) {
04049          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04050             the call or reject it and detect the tone off condition of the other end, all of this
04051             will be done in the PBX thread now */
04052          return;
04053       }
04054       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04055       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04056    } else if (p->mfcr2_charge_calls) {
04057       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04058       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04059    } else {
04060       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04061       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04062    }
04063 }
04064 
04065 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04066 {
04067    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04068    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04069    ast_mutex_lock(&p->lock);
04070    p->mfcr2call = 0;
04071    ast_mutex_unlock(&p->lock);
04072 }
04073 
04074 static void dahdi_enable_ec(struct dahdi_pvt *p);
04075 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04076 {
04077    struct dahdi_pvt *p = NULL;
04078    struct ast_channel *c = NULL;
04079    p = openr2_chan_get_client_data(r2chan);
04080    dahdi_enable_ec(p);
04081    p->mfcr2_call_accepted = 1;
04082    /* if it's an incoming call ... */
04083    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04084       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04085       /* If accept on offer is not set, it means at this point the PBX thread is already
04086          launched (was launched in the 'on call offered' handler) and therefore this callback
04087          is being executed already in the PBX thread rather than the monitor thread, don't launch
04088          any other thread, just disable the openr2 reading and answer the call if needed */
04089       if (!p->mfcr2_accept_on_offer) {
04090          openr2_chan_disable_read(r2chan);
04091          if (p->mfcr2_answer_pending) {
04092             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04093             dahdi_r2_answer(p);
04094          }
04095          return;
04096       }
04097       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04098       if (c) {
04099          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04100             library to forget about it */
04101          openr2_chan_disable_read(r2chan);
04102          return;
04103       }
04104       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04105       /* failed to create the channel, bail out and report it as an out of order line */
04106       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04107       return;
04108    }
04109    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04110    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04111    p->subs[SUB_REAL].needringing = 1;
04112    p->dialing = 0;
04113    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04114    openr2_chan_disable_read(r2chan);
04115 }
04116 
04117 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04118 {
04119    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04120    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04121    p->subs[SUB_REAL].needanswer = 1;
04122 }
04123 
04124 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04125 {
04126    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04127 }
04128 
04129 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04130 {
04131    switch (cause) {
04132    case OR2_CAUSE_BUSY_NUMBER:
04133       return AST_CAUSE_BUSY;
04134    case OR2_CAUSE_NETWORK_CONGESTION:
04135       return AST_CAUSE_CONGESTION;
04136    case OR2_CAUSE_OUT_OF_ORDER:
04137       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04138    case OR2_CAUSE_UNALLOCATED_NUMBER:
04139       return AST_CAUSE_UNREGISTERED;
04140    case OR2_CAUSE_NO_ANSWER:
04141       return AST_CAUSE_NO_ANSWER;
04142    case OR2_CAUSE_NORMAL_CLEARING:
04143       return AST_CAUSE_NORMAL_CLEARING;
04144    case OR2_CAUSE_UNSPECIFIED:
04145    default:
04146       return AST_CAUSE_NOTDEFINED;
04147    }
04148 }
04149 
04150 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04151 {
04152    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04153    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04154    ast_mutex_lock(&p->lock);
04155    if (!p->owner) {
04156       ast_mutex_unlock(&p->lock);
04157       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04158       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04159       return;
04160    }
04161    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04162       be done in dahdi_hangup */
04163    if (p->owner->_state == AST_STATE_UP) {
04164       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04165       ast_mutex_unlock(&p->lock);
04166    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04167       /* being the forward side we must report what happened to the call to whoever requested it */
04168       switch (cause) {
04169       case OR2_CAUSE_BUSY_NUMBER:
04170          p->subs[SUB_REAL].needbusy = 1;
04171          break;
04172       case OR2_CAUSE_NETWORK_CONGESTION:
04173       case OR2_CAUSE_OUT_OF_ORDER:
04174       case OR2_CAUSE_UNALLOCATED_NUMBER:
04175       case OR2_CAUSE_NO_ANSWER:
04176       case OR2_CAUSE_UNSPECIFIED:
04177       case OR2_CAUSE_NORMAL_CLEARING:
04178          p->subs[SUB_REAL].needcongestion = 1;
04179          break;
04180       default:
04181          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04182       }
04183       ast_mutex_unlock(&p->lock);
04184    } else {
04185       ast_mutex_unlock(&p->lock);
04186       /* being the backward side and not UP yet, we only need to request hangup */
04187       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04188       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04189    }
04190 }
04191 
04192 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04193 {
04194    switch (level) {
04195    case OR2_LOG_NOTICE:
04196       ast_verbose("%s", logmessage);
04197       break;
04198    case OR2_LOG_WARNING:
04199       ast_log(LOG_WARNING, "%s", logmessage);
04200       break;
04201    case OR2_LOG_ERROR:
04202       ast_log(LOG_ERROR, "%s", logmessage);
04203       break;
04204    case OR2_LOG_STACK_TRACE:
04205    case OR2_LOG_MF_TRACE:
04206    case OR2_LOG_CAS_TRACE:
04207    case OR2_LOG_DEBUG:
04208    case OR2_LOG_EX_DEBUG:
04209       ast_log(LOG_DEBUG, "%s", logmessage);
04210       break;
04211    default:
04212       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04213       ast_log(LOG_DEBUG, "%s", logmessage);
04214       break;
04215    }
04216 }
04217 
04218 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04219 {
04220    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04221    ast_mutex_lock(&p->lock);
04222    p->remotelyblocked = 1;
04223    ast_mutex_unlock(&p->lock);
04224    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04225 }
04226 
04227 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04228 {
04229    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04230    ast_mutex_lock(&p->lock);
04231    p->remotelyblocked = 0;
04232    ast_mutex_unlock(&p->lock);
04233    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04234 }
04235 
04236 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04237    __attribute__((format (printf, 3, 0)));
04238 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04239 {
04240 #define CONTEXT_TAG "Context - "
04241    char logmsg[256];
04242    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04243    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04244    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04245    dahdi_r2_write_log(level, completemsg);
04246 #undef CONTEXT_TAG
04247 }
04248 
04249 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04250    __attribute__((format (printf, 3, 0)));
04251 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04252 {
04253 #define CHAN_TAG "Chan "
04254    char logmsg[256];
04255    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04256    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04257    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04258    dahdi_r2_write_log(level, completemsg);
04259 }
04260 
04261 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04262 {
04263    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04264    /* if 'immediate' is set, let's stop requesting DNIS */
04265    if (p->immediate) {
04266       return 0;
04267    }
04268    p->exten[p->mfcr2_dnis_index] = digit;
04269    p->rdnis[p->mfcr2_dnis_index] = digit;
04270    p->mfcr2_dnis_index++;
04271    p->exten[p->mfcr2_dnis_index] = 0;
04272    p->rdnis[p->mfcr2_dnis_index] = 0;
04273    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04274    if ((p->mfcr2_dnis_matched ||
04275        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04276        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04277       return 0;
04278    }
04279    /* otherwise keep going */
04280    return 1;
04281 }
04282 
04283 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04284 {
04285    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04286    p->cid_num[p->mfcr2_ani_index] = digit;
04287    p->cid_name[p->mfcr2_ani_index] = digit;
04288    p->mfcr2_ani_index++;
04289    p->cid_num[p->mfcr2_ani_index] = 0;
04290    p->cid_name[p->mfcr2_ani_index] = 0;
04291 }
04292 
04293 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04294 {
04295    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04296 }
04297 
04298 static openr2_event_interface_t dahdi_r2_event_iface = {
04299    .on_call_init = dahdi_r2_on_call_init,
04300    .on_call_offered = dahdi_r2_on_call_offered,
04301    .on_call_accepted = dahdi_r2_on_call_accepted,
04302    .on_call_answered = dahdi_r2_on_call_answered,
04303    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04304    .on_call_end = dahdi_r2_on_call_end,
04305    .on_call_read = dahdi_r2_on_call_read,
04306    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04307    .on_os_error = dahdi_r2_on_os_error,
04308    .on_protocol_error = dahdi_r2_on_protocol_error,
04309    .on_line_blocked = dahdi_r2_on_line_blocked,
04310    .on_line_idle = dahdi_r2_on_line_idle,
04311    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04312    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04313    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04314    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04315    /* so far we do nothing with billing pulses */
04316    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04317 };
04318 
04319 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04320 {
04321    return AST_ALAW(sample);
04322 }
04323 
04324 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04325 {
04326    return AST_LIN2A(sample);
04327 }
04328 
04329 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04330    dahdi_r2_alaw_to_linear,
04331    dahdi_r2_linear_to_alaw
04332 };
04333 
04334 #endif /* HAVE_OPENR2 */
04335 
04336 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04337 {
04338    int tchan;
04339    int tinthreeway;
04340    struct ast_channel *towner;
04341 
04342    ast_debug(1, "Swapping %d and %d\n", a, b);
04343 
04344    tchan = p->subs[a].chan;
04345    towner = p->subs[a].owner;
04346    tinthreeway = p->subs[a].inthreeway;
04347 
04348    p->subs[a].chan = p->subs[b].chan;
04349    p->subs[a].owner = p->subs[b].owner;
04350    p->subs[a].inthreeway = p->subs[b].inthreeway;
04351 
04352    p->subs[b].chan = tchan;
04353    p->subs[b].owner = towner;
04354    p->subs[b].inthreeway = tinthreeway;
04355 
04356    if (p->subs[a].owner)
04357       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04358    if (p->subs[b].owner)
04359       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04360    wakeup_sub(p, a);
04361    wakeup_sub(p, b);
04362 }
04363 
04364 static int dahdi_open(char *fn)
04365 {
04366    int fd;
04367    int isnum;
04368    int chan = 0;
04369    int bs;
04370    int x;
04371    isnum = 1;
04372    for (x = 0; x < strlen(fn); x++) {
04373       if (!isdigit(fn[x])) {
04374          isnum = 0;
04375          break;
04376       }
04377    }
04378    if (isnum) {
04379       chan = atoi(fn);
04380       if (chan < 1) {
04381          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04382          return -1;
04383       }
04384       fn = "/dev/dahdi/channel";
04385    }
04386    fd = open(fn, O_RDWR | O_NONBLOCK);
04387    if (fd < 0) {
04388       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04389       return -1;
04390    }
04391    if (chan) {
04392       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04393          x = errno;
04394          close(fd);
04395          errno = x;
04396          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04397          return -1;
04398       }
04399    }
04400    bs = READ_SIZE;
04401    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04402       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04403       x = errno;
04404       close(fd);
04405       errno = x;
04406       return -1;
04407    }
04408    return fd;
04409 }
04410 
04411 static void dahdi_close(int fd)
04412 {
04413    if (fd > 0)
04414       close(fd);
04415 }
04416 
04417 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04418 {
04419    dahdi_close(chan_pvt->subs[sub_num].dfd);
04420    chan_pvt->subs[sub_num].dfd = -1;
04421 }
04422 
04423 #if defined(HAVE_PRI)
04424 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04425 {
04426    dahdi_close(pri->pri.fds[fd_num]);
04427    pri->pri.fds[fd_num] = -1;
04428 }
04429 #endif   /* defined(HAVE_PRI) */
04430 
04431 #if defined(HAVE_SS7)
04432 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04433 {
04434    dahdi_close(ss7->ss7.fds[fd_num]);
04435    ss7->ss7.fds[fd_num] = -1;
04436 }
04437 #endif   /* defined(HAVE_SS7) */
04438 
04439 static int dahdi_setlinear(int dfd, int linear)
04440 {
04441    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04442 }
04443 
04444 
04445 static int alloc_sub(struct dahdi_pvt *p, int x)
04446 {
04447    struct dahdi_bufferinfo bi;
04448    int res;
04449    if (p->subs[x].dfd >= 0) {
04450       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04451       return -1;
04452    }
04453 
04454    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04455    if (p->subs[x].dfd <= -1) {
04456       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04457       return -1;
04458    }
04459 
04460    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04461    if (!res) {
04462       bi.txbufpolicy = p->buf_policy;
04463       bi.rxbufpolicy = p->buf_policy;
04464       bi.numbufs = p->buf_no;
04465       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04466       if (res < 0) {
04467          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04468       }
04469    } else
04470       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04471 
04472    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04473       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04474       dahdi_close_sub(p, x);
04475       p->subs[x].dfd = -1;
04476       return -1;
04477    }
04478    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04479    return 0;
04480 }
04481 
04482 static int unalloc_sub(struct dahdi_pvt *p, int x)
04483 {
04484    if (!x) {
04485       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04486       return -1;
04487    }
04488    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04489    dahdi_close_sub(p, x);
04490    p->subs[x].linear = 0;
04491    p->subs[x].chan = 0;
04492    p->subs[x].owner = NULL;
04493    p->subs[x].inthreeway = 0;
04494    p->polarity = POLARITY_IDLE;
04495    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04496    return 0;
04497 }
04498 
04499 static int digit_to_dtmfindex(char digit)
04500 {
04501    if (isdigit(digit))
04502       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04503    else if (digit >= 'A' && digit <= 'D')
04504       return DAHDI_TONE_DTMF_A + (digit - 'A');
04505    else if (digit >= 'a' && digit <= 'd')
04506       return DAHDI_TONE_DTMF_A + (digit - 'a');
04507    else if (digit == '*')
04508       return DAHDI_TONE_DTMF_s;
04509    else if (digit == '#')
04510       return DAHDI_TONE_DTMF_p;
04511    else
04512       return -1;
04513 }
04514 
04515 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04516 {
04517    struct dahdi_pvt *pvt;
04518    int idx;
04519    int dtmf = -1;
04520    int res;
04521 
04522    pvt = chan->tech_pvt;
04523 
04524    ast_mutex_lock(&pvt->lock);
04525 
04526    idx = dahdi_get_index(chan, pvt, 0);
04527 
04528    if ((idx != SUB_REAL) || !pvt->owner)
04529       goto out;
04530 
04531 #ifdef HAVE_PRI
04532    switch (pvt->sig) {
04533    case SIG_PRI_LIB_HANDLE_CASES:
04534       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04535       if (!res)
04536          goto out;
04537       break;
04538    default:
04539       break;
04540    }
04541 #endif
04542    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04543       goto out;
04544 
04545    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04546       struct dahdi_dialoperation zo = {
04547          .op = DAHDI_DIAL_OP_APPEND,
04548       };
04549 
04550       zo.dialstr[0] = 'T';
04551       zo.dialstr[1] = digit;
04552       zo.dialstr[2] = '\0';
04553       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04554          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04555             chan->name, digit, strerror(errno));
04556       else
04557          pvt->dialing = 1;
04558    } else {
04559       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04560          chan->name, digit);
04561       pvt->dialing = 1;
04562       pvt->begindigit = digit;
04563    }
04564 
04565 out:
04566    ast_mutex_unlock(&pvt->lock);
04567 
04568    return 0;
04569 }
04570 
04571 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04572 {
04573    struct dahdi_pvt *pvt;
04574    int res = 0;
04575    int idx;
04576    int x;
04577 
04578    pvt = chan->tech_pvt;
04579 
04580    ast_mutex_lock(&pvt->lock);
04581 
04582    idx = dahdi_get_index(chan, pvt, 0);
04583 
04584    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04585       goto out;
04586 
04587 #ifdef HAVE_PRI
04588    /* This means that the digit was already sent via PRI signalling */
04589    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04590       goto out;
04591    }
04592 #endif
04593 
04594    if (pvt->begindigit) {
04595       x = -1;
04596       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04597          chan->name, digit);
04598       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04599       pvt->dialing = 0;
04600       pvt->begindigit = 0;
04601    }
04602 
04603 out:
04604    ast_mutex_unlock(&pvt->lock);
04605 
04606    return res;
04607 }
04608 
04609 static const char * const events[] = {
04610    "No event",
04611    "On hook",
04612    "Ring/Answered",
04613    "Wink/Flash",
04614    "Alarm",
04615    "No more alarm",
04616    "HDLC Abort",
04617    "HDLC Overrun",
04618    "HDLC Bad FCS",
04619    "Dial Complete",
04620    "Ringer On",
04621    "Ringer Off",
04622    "Hook Transition Complete",
04623    "Bits Changed",
04624    "Pulse Start",
04625    "Timer Expired",
04626    "Timer Ping",
04627    "Polarity Reversal",
04628    "Ring Begin",
04629 };
04630 
04631 static struct {
04632    int alarm;
04633    char *name;
04634 } alarms[] = {
04635    { DAHDI_ALARM_RED, "Red Alarm" },
04636    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04637    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04638    { DAHDI_ALARM_RECOVER, "Recovering" },
04639    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04640    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04641    { DAHDI_ALARM_NONE, "None" },
04642 };
04643 
04644 static char *alarm2str(int alm)
04645 {
04646    int x;
04647    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04648       if (alarms[x].alarm & alm)
04649          return alarms[x].name;
04650    }
04651    return alm ? "Unknown Alarm" : "No Alarm";
04652 }
04653 
04654 static const char *event2str(int event)
04655 {
04656    static char buf[256];
04657    if ((event < (ARRAY_LEN(events))) && (event > -1))
04658       return events[event];
04659    sprintf(buf, "Event %d", event); /* safe */
04660    return buf;
04661 }
04662 
04663 static char *dahdi_sig2str(int sig)
04664 {
04665    static char buf[256];
04666    switch (sig) {
04667    case SIG_EM:
04668       return "E & M Immediate";
04669    case SIG_EMWINK:
04670       return "E & M Wink";
04671    case SIG_EM_E1:
04672       return "E & M E1";
04673    case SIG_FEATD:
04674       return "Feature Group D (DTMF)";
04675    case SIG_FEATDMF:
04676       return "Feature Group D (MF)";
04677    case SIG_FEATDMF_TA:
04678       return "Feature Groud D (MF) Tandem Access";
04679    case SIG_FEATB:
04680       return "Feature Group B (MF)";
04681    case SIG_E911:
04682       return "E911 (MF)";
04683    case SIG_FGC_CAMA:
04684       return "FGC/CAMA (Dialpulse)";
04685    case SIG_FGC_CAMAMF:
04686       return "FGC/CAMA (MF)";
04687    case SIG_FXSLS:
04688       return "FXS Loopstart";
04689    case SIG_FXSGS:
04690       return "FXS Groundstart";
04691    case SIG_FXSKS:
04692       return "FXS Kewlstart";
04693    case SIG_FXOLS:
04694       return "FXO Loopstart";
04695    case SIG_FXOGS:
04696       return "FXO Groundstart";
04697    case SIG_FXOKS:
04698       return "FXO Kewlstart";
04699    case SIG_PRI:
04700       return "ISDN PRI";
04701    case SIG_BRI:
04702       return "ISDN BRI Point to Point";
04703    case SIG_BRI_PTMP:
04704       return "ISDN BRI Point to MultiPoint";
04705    case SIG_SS7:
04706       return "SS7";
04707    case SIG_MFCR2:
04708       return "MFC/R2";
04709    case SIG_SF:
04710       return "SF (Tone) Immediate";
04711    case SIG_SFWINK:
04712       return "SF (Tone) Wink";
04713    case SIG_SF_FEATD:
04714       return "SF (Tone) with Feature Group D (DTMF)";
04715    case SIG_SF_FEATDMF:
04716       return "SF (Tone) with Feature Group D (MF)";
04717    case SIG_SF_FEATB:
04718       return "SF (Tone) with Feature Group B (MF)";
04719    case 0:
04720       return "Pseudo";
04721    default:
04722       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04723       return buf;
04724    }
04725 }
04726 
04727 #define sig2str dahdi_sig2str
04728 
04729 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04730 {
04731    /* If the conference already exists, and we're already in it
04732       don't bother doing anything */
04733    struct dahdi_confinfo zi;
04734 
04735    memset(&zi, 0, sizeof(zi));
04736    zi.chan = 0;
04737 
04738    if (slavechannel > 0) {
04739       /* If we have only one slave, do a digital mon */
04740       zi.confmode = DAHDI_CONF_DIGITALMON;
04741       zi.confno = slavechannel;
04742    } else {
04743       if (!idx) {
04744          /* Real-side and pseudo-side both participate in conference */
04745          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04746             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04747       } else
04748          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04749       zi.confno = p->confno;
04750    }
04751    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04752       return 0;
04753    if (c->dfd < 0)
04754       return 0;
04755    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04756       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04757       return -1;
04758    }
04759    if (slavechannel < 1) {
04760       p->confno = zi.confno;
04761    }
04762    c->curconf = zi;
04763    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04764    return 0;
04765 }
04766 
04767 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04768 {
04769    /* If they're listening to our channel, they're ours */
04770    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04771       return 1;
04772    /* If they're a talker on our (allocated) conference, they're ours */
04773    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04774       return 1;
04775    return 0;
04776 }
04777 
04778 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04779 {
04780    struct dahdi_confinfo zi;
04781    if (/* Can't delete if there's no dfd */
04782       (c->dfd < 0) ||
04783       /* Don't delete from the conference if it's not our conference */
04784       !isourconf(p, c)
04785       /* Don't delete if we don't think it's conferenced at all (implied) */
04786       ) return 0;
04787    memset(&zi, 0, sizeof(zi));
04788    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04789       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04790       return -1;
04791    }
04792    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04793    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04794    return 0;
04795 }
04796 
04797 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04798 {
04799    int x;
04800    int useslavenative;
04801    struct dahdi_pvt *slave = NULL;
04802    /* Start out optimistic */
04803    useslavenative = 1;
04804    /* Update conference state in a stateless fashion */
04805    for (x = 0; x < 3; x++) {
04806       /* Any three-way calling makes slave native mode *definitely* out
04807          of the question */
04808       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04809          useslavenative = 0;
04810    }
04811    /* If we don't have any 3-way calls, check to see if we have
04812       precisely one slave */
04813    if (useslavenative) {
04814       for (x = 0; x < MAX_SLAVES; x++) {
04815          if (p->slaves[x]) {
04816             if (slave) {
04817                /* Whoops already have a slave!  No
04818                   slave native and stop right away */
04819                slave = NULL;
04820                useslavenative = 0;
04821                break;
04822             } else {
04823                /* We have one slave so far */
04824                slave = p->slaves[x];
04825             }
04826          }
04827       }
04828    }
04829    /* If no slave, slave native definitely out */
04830    if (!slave)
04831       useslavenative = 0;
04832    else if (slave->law != p->law) {
04833       useslavenative = 0;
04834       slave = NULL;
04835    }
04836    if (out)
04837       *out = slave;
04838    return useslavenative;
04839 }
04840 
04841 static int reset_conf(struct dahdi_pvt *p)
04842 {
04843    p->confno = -1;
04844    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04845    if (p->subs[SUB_REAL].dfd > -1) {
04846       struct dahdi_confinfo zi;
04847 
04848       memset(&zi, 0, sizeof(zi));
04849       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04850          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04851    }
04852    return 0;
04853 }
04854 
04855 static int update_conf(struct dahdi_pvt *p)
04856 {
04857    int needconf = 0;
04858    int x;
04859    int useslavenative;
04860    struct dahdi_pvt *slave = NULL;
04861 
04862    useslavenative = isslavenative(p, &slave);
04863    /* Start with the obvious, general stuff */
04864    for (x = 0; x < 3; x++) {
04865       /* Look for three way calls */
04866       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04867          conf_add(p, &p->subs[x], x, 0);
04868          needconf++;
04869       } else {
04870          conf_del(p, &p->subs[x], x);
04871       }
04872    }
04873    /* If we have a slave, add him to our conference now. or DAX
04874       if this is slave native */
04875    for (x = 0; x < MAX_SLAVES; x++) {
04876       if (p->slaves[x]) {
04877          if (useslavenative)
04878             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04879          else {
04880             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04881             needconf++;
04882          }
04883       }
04884    }
04885    /* If we're supposed to be in there, do so now */
04886    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04887       if (useslavenative)
04888          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04889       else {
04890          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04891          needconf++;
04892       }
04893    }
04894    /* If we have a master, add ourselves to his conference */
04895    if (p->master) {
04896       if (isslavenative(p->master, NULL)) {
04897          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04898       } else {
04899          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04900       }
04901    }
04902    if (!needconf) {
04903       /* Nobody is left (or should be left) in our conference.
04904          Kill it. */
04905       p->confno = -1;
04906    }
04907    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04908    return 0;
04909 }
04910 
04911 static void dahdi_enable_ec(struct dahdi_pvt *p)
04912 {
04913    int res;
04914    if (!p)
04915       return;
04916    if (p->echocanon) {
04917       ast_debug(1, "Echo cancellation already on\n");
04918       return;
04919    }
04920    if (p->digital) {
04921       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04922       return;
04923    }
04924    if (p->echocancel.head.tap_length) {
04925 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04926       switch (p->sig) {
04927 #if defined(HAVE_PRI)
04928       case SIG_PRI_LIB_HANDLE_CASES:
04929          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04930             /*
04931              * PRI nobch pseudo channel.  Does not need ec anyway.
04932              * Does not handle ioctl(DAHDI_AUDIOMODE)
04933              */
04934             return;
04935          }
04936          /* Fall through */
04937 #endif   /* defined(HAVE_PRI) */
04938 #if defined(HAVE_SS7)
04939       case SIG_SS7:
04940 #endif   /* defined(HAVE_SS7) */
04941          {
04942             int x = 1;
04943 
04944             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04945             if (res)
04946                ast_log(LOG_WARNING,
04947                   "Unable to enable audio mode on channel %d (%s)\n",
04948                   p->channel, strerror(errno));
04949          }
04950          break;
04951       default:
04952          break;
04953       }
04954 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04955       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04956       if (res) {
04957          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04958       } else {
04959          p->echocanon = 1;
04960          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04961       }
04962    } else
04963       ast_debug(1, "No echo cancellation requested\n");
04964 }
04965 
04966 static void dahdi_train_ec(struct dahdi_pvt *p)
04967 {
04968    int x;
04969    int res;
04970 
04971    if (p && p->echocanon && p->echotraining) {
04972       x = p->echotraining;
04973       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04974       if (res)
04975          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04976       else
04977          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04978    } else {
04979       ast_debug(1, "No echo training requested\n");
04980    }
04981 }
04982 
04983 static void dahdi_disable_ec(struct dahdi_pvt *p)
04984 {
04985    int res;
04986 
04987    if (p->echocanon) {
04988       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04989 
04990       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04991 
04992       if (res)
04993          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04994       else
04995          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04996    }
04997 
04998    p->echocanon = 0;
04999 }
05000 
05001 /* perform a dynamic range compression transform on the given sample */
05002 static int drc_sample(int sample, float drc)
05003 {
05004    float neg;
05005    float shallow, steep;
05006    float max = SHRT_MAX;
05007    
05008    neg = (sample < 0 ? -1 : 1);
05009    steep = drc*sample;
05010    shallow = neg*(max-max/drc)+(float)sample/drc;
05011    if (abs(steep) < abs(shallow)) {
05012       sample = steep;
05013    }
05014    else {
05015       sample = shallow;
05016    }
05017 
05018    return sample;
05019 }
05020 
05021 
05022 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05023 {
05024    int j;
05025    int k;
05026 
05027    float linear_gain = pow(10.0, gain / 20.0);
05028 
05029    switch (law) {
05030    case DAHDI_LAW_ALAW:
05031       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05032          if (gain || drc) {
05033             k = AST_ALAW(j);
05034             if (drc) {
05035                k = drc_sample(k, drc);
05036             }
05037             k = (float)k*linear_gain;
05038             if (k > 32767) k = 32767;
05039             if (k < -32767) k = -32767;
05040             g->txgain[j] = AST_LIN2A(k);
05041          } else {
05042             g->txgain[j] = j;
05043          }
05044       }
05045       break;
05046    case DAHDI_LAW_MULAW:
05047       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05048          if (gain || drc) {
05049             k = AST_MULAW(j);
05050             if (drc) {
05051                k = drc_sample(k, drc);
05052             }
05053             k = (float)k*linear_gain;
05054             if (k > 32767) k = 32767;
05055             if (k < -32767) k = -32767;
05056             g->txgain[j] = AST_LIN2MU(k);
05057 
05058          } else {
05059             g->txgain[j] = j;
05060          }
05061       }
05062       break;
05063    }
05064 }
05065 
05066 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05067 {
05068    int j;
05069    int k;
05070    float linear_gain = pow(10.0, gain / 20.0);
05071 
05072    switch (law) {
05073    case DAHDI_LAW_ALAW:
05074       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05075          if (gain || drc) {
05076             k = AST_ALAW(j);
05077             if (drc) {
05078                k = drc_sample(k, drc);
05079             }
05080             k = (float)k*linear_gain;
05081             if (k > 32767) k = 32767;
05082             if (k < -32767) k = -32767;
05083             g->rxgain[j] = AST_LIN2A(k);
05084          } else {
05085             g->rxgain[j] = j;
05086          }
05087       }
05088       break;
05089    case DAHDI_LAW_MULAW:
05090       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05091          if (gain || drc) {
05092             k = AST_MULAW(j);
05093             if (drc) {
05094                k = drc_sample(k, drc);
05095             }
05096             k = (float)k*linear_gain;
05097             if (k > 32767) k = 32767;
05098             if (k < -32767) k = -32767;
05099             g->rxgain[j] = AST_LIN2MU(k);
05100          } else {
05101             g->rxgain[j] = j;
05102          }
05103       }
05104       break;
05105    }
05106 }
05107 
05108 static int set_actual_txgain(int fd, float gain, float drc, int law)
05109 {
05110    struct dahdi_gains g;
05111    int res;
05112 
05113    memset(&g, 0, sizeof(g));
05114    res = ioctl(fd, DAHDI_GETGAINS, &g);
05115    if (res) {
05116       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05117       return res;
05118    }
05119 
05120    fill_txgain(&g, gain, drc, law);
05121 
05122    return ioctl(fd, DAHDI_SETGAINS, &g);
05123 }
05124 
05125 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05126 {
05127    struct dahdi_gains g;
05128    int res;
05129 
05130    memset(&g, 0, sizeof(g));
05131    res = ioctl(fd, DAHDI_GETGAINS, &g);
05132    if (res) {
05133       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05134       return res;
05135    }
05136 
05137    fill_rxgain(&g, gain, drc, law);
05138 
05139    return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }
05141 
05142 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05143 {
05144    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05145 }
05146 
05147 static int bump_gains(struct dahdi_pvt *p)
05148 {
05149    int res;
05150 
05151    /* Bump receive gain by value stored in cid_rxgain */
05152    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153    if (res) {
05154       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05155       return -1;
05156    }
05157 
05158    return 0;
05159 }
05160 
05161 static int restore_gains(struct dahdi_pvt *p)
05162 {
05163    int res;
05164 
05165    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05166    if (res) {
05167       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05168       return -1;
05169    }
05170 
05171    return 0;
05172 }
05173 
05174 static inline int dahdi_set_hook(int fd, int hs)
05175 {
05176    int x, res;
05177 
05178    x = hs;
05179    res = ioctl(fd, DAHDI_HOOK, &x);
05180 
05181    if (res < 0) {
05182       if (errno == EINPROGRESS)
05183          return 0;
05184       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05185       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05186    }
05187 
05188    return res;
05189 }
05190 
05191 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05192 {
05193    int x, res;
05194 
05195    x = muted;
05196 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05197    switch (p->sig) {
05198 #if defined(HAVE_PRI)
05199    case SIG_PRI_LIB_HANDLE_CASES:
05200       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05201          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05202          break;
05203       }
05204       /* Fall through */
05205 #endif   /* defined(HAVE_PRI) */
05206 #if defined(HAVE_SS7)
05207    case SIG_SS7:
05208 #endif   /* defined(HAVE_SS7) */
05209       {
05210          int y = 1;
05211 
05212          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05213          if (res)
05214             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05215                p->channel, strerror(errno));
05216       }
05217       break;
05218    default:
05219       break;
05220    }
05221 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05222    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05223    if (res < 0)
05224       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05225    return res;
05226 }
05227 
05228 static int save_conference(struct dahdi_pvt *p)
05229 {
05230    struct dahdi_confinfo c;
05231    int res;
05232    if (p->saveconf.confmode) {
05233       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05234       return -1;
05235    }
05236    p->saveconf.chan = 0;
05237    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05238    if (res) {
05239       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05240       p->saveconf.confmode = 0;
05241       return -1;
05242    }
05243    memset(&c, 0, sizeof(c));
05244    c.confmode = DAHDI_CONF_NORMAL;
05245    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05246    if (res) {
05247       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05248       return -1;
05249    }
05250    ast_debug(1, "Disabled conferencing\n");
05251    return 0;
05252 }
05253 
05254 static int restore_conference(struct dahdi_pvt *p)
05255 {
05256    int res;
05257    if (p->saveconf.confmode) {
05258       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05259       p->saveconf.confmode = 0;
05260       if (res) {
05261          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05262          return -1;
05263       }
05264       ast_debug(1, "Restored conferencing\n");
05265    }
05266    return 0;
05267 }
05268 
05269 static int send_cwcidspill(struct dahdi_pvt *p)
05270 {
05271    p->callwaitcas = 0;
05272    p->cidcwexpire = 0;
05273    p->cid_suppress_expire = 0;
05274    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05275       return -1;
05276    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05277    /* Make sure we account for the end */
05278    p->cidlen += READ_SIZE * 4;
05279    p->cidpos = 0;
05280    send_callerid(p);
05281    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05282    return 0;
05283 }
05284 
05285 static int has_voicemail(struct dahdi_pvt *p)
05286 {
05287    int new_msgs;
05288    struct ast_event *event;
05289    char *mailbox, *context;
05290 
05291    mailbox = context = ast_strdupa(p->mailbox);
05292    strsep(&context, "@");
05293    if (ast_strlen_zero(context))
05294       context = "default";
05295 
05296    event = ast_event_get_cached(AST_EVENT_MWI,
05297       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05298       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05299       AST_EVENT_IE_END);
05300 
05301    if (event) {
05302       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05303       ast_event_destroy(event);
05304    } else
05305       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05306 
05307    return new_msgs;
05308 }
05309 
05310 
05311 
05312 static int send_callerid(struct dahdi_pvt *p)
05313 {
05314    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05315    int res;
05316    /* Take out of linear mode if necessary */
05317    if (p->subs[SUB_REAL].linear) {
05318       p->subs[SUB_REAL].linear = 0;
05319       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05320    }
05321    while (p->cidpos < p->cidlen) {
05322       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05323       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05324       if (res < 0) {
05325          if (errno == EAGAIN)
05326             return 0;
05327          else {
05328             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05329             return -1;
05330          }
05331       }
05332       if (!res)
05333          return 0;
05334       p->cidpos += res;
05335    }
05336    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05337    ast_free(p->cidspill);
05338    p->cidspill = NULL;
05339    if (p->callwaitcas) {
05340       /* Wait for CID/CW to expire */
05341       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05342       p->cid_suppress_expire = p->cidcwexpire;
05343    } else
05344       restore_conference(p);
05345    return 0;
05346 }
05347 
05348 static int dahdi_callwait(struct ast_channel *ast)
05349 {
05350    struct dahdi_pvt *p = ast->tech_pvt;
05351    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05352    if (p->cidspill) {
05353       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05354       ast_free(p->cidspill);
05355    }
05356 
05357    /*
05358     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05359     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05360     */
05361    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05362       return -1;
05363    save_conference(p);
05364    /* Silence */
05365    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05366    if (!p->callwaitrings && p->callwaitingcallerid) {
05367       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05368       p->callwaitcas = 1;
05369       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05370    } else {
05371       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05372       p->callwaitcas = 0;
05373       p->cidlen = 2400 + READ_SIZE * 4;
05374    }
05375    p->cidpos = 0;
05376    send_callerid(p);
05377 
05378    return 0;
05379 }
05380 
05381 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05382 {
05383    struct dahdi_pvt *p = ast->tech_pvt;
05384    int x, res, mysig;
05385    char dest[256]; /* must be same length as p->dialdest */
05386 
05387    ast_mutex_lock(&p->lock);
05388    ast_copy_string(dest, rdest, sizeof(dest));
05389    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05390    if ((ast->_state == AST_STATE_BUSY)) {
05391       p->subs[SUB_REAL].needbusy = 1;
05392       ast_mutex_unlock(&p->lock);
05393       return 0;
05394    }
05395    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05396       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05397       ast_mutex_unlock(&p->lock);
05398       return -1;
05399    }
05400    p->waitingfordt.tv_sec = 0;
05401    p->dialednone = 0;
05402    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05403    {
05404       /* Special pseudo -- automatically up */
05405       ast_setstate(ast, AST_STATE_UP);
05406       ast_mutex_unlock(&p->lock);
05407       return 0;
05408    }
05409    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05410    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05411    if (res)
05412       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05413    p->outgoing = 1;
05414 
05415    if (IS_DIGITAL(ast->transfercapability)){
05416       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05417    } else {
05418       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05419    }  
05420 
05421 #ifdef HAVE_PRI
05422    if (dahdi_sig_pri_lib_handles(p->sig)) {
05423       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05424          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05425       ast_mutex_unlock(&p->lock);
05426       return res;
05427    }
05428 #endif
05429 
05430 #if defined(HAVE_SS7)
05431    if (p->sig == SIG_SS7) {
05432       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05433       ast_mutex_unlock(&p->lock);
05434       return res;
05435    }
05436 #endif   /* defined(HAVE_SS7) */
05437 
05438    /* If this is analog signalling we can exit here */
05439    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05440       p->callwaitrings = 0;
05441       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05442       ast_mutex_unlock(&p->lock);
05443       return res;
05444    }
05445 
05446    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05447    switch (mysig) {
05448    case 0:
05449       /* Special pseudo -- automatically up*/
05450       ast_setstate(ast, AST_STATE_UP);
05451       break;
05452    case SIG_MFCR2:
05453       break;
05454    default:
05455       ast_debug(1, "not yet implemented\n");
05456       ast_mutex_unlock(&p->lock);
05457       return -1;
05458    }
05459 
05460 #ifdef HAVE_OPENR2
05461    if (p->mfcr2) {
05462       openr2_calling_party_category_t chancat;
05463       int callres = 0;
05464       char *c, *l;
05465 
05466       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05467       p->dialdest[0] = '\0';
05468 
05469       c = strchr(dest, '/');
05470       if (c) {
05471          c++;
05472       } else {
05473          c = "";
05474       }
05475       if (!p->hidecallerid) {
05476          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05477       } else {
05478          l = NULL;
05479       }
05480       if (strlen(c) < p->stripmsd) {
05481          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05482          ast_mutex_unlock(&p->lock);
05483          return -1;
05484       }
05485       p->dialing = 1;
05486       chancat = dahdi_r2_get_channel_category(ast);
05487       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05488       if (-1 == callres) {
05489          ast_mutex_unlock(&p->lock);
05490          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05491          return -1;
05492       }
05493       p->mfcr2_call_accepted = 0;
05494       p->mfcr2_progress = 0;
05495       ast_setstate(ast, AST_STATE_DIALING);
05496    }
05497 #endif /* HAVE_OPENR2 */
05498    ast_mutex_unlock(&p->lock);
05499    return 0;
05500 }
05501 
05502 /*!
05503  * \internal
05504  * \brief Insert the given chan_dahdi interface structure into the interface list.
05505  * \since 1.8
05506  *
05507  * \param pvt chan_dahdi private interface structure to insert.
05508  *
05509  * \details
05510  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05511  * Any duplicates are inserted after the existing entries.
05512  *
05513  * \note The new interface must not already be in the list.
05514  *
05515  * \return Nothing
05516  */
05517 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05518 {
05519    struct dahdi_pvt *cur;
05520 
05521    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05522 
05523    /* Find place in middle of list for the new interface. */
05524    for (cur = iflist; cur; cur = cur->next) {
05525       if (pvt->channel < cur->channel) {
05526          /* New interface goes before the current interface. */
05527          pvt->prev = cur->prev;
05528          pvt->next = cur;
05529          if (cur->prev) {
05530             /* Insert into the middle of the list. */
05531             cur->prev->next = pvt;
05532          } else {
05533             /* Insert at head of list. */
05534             iflist = pvt;
05535          }
05536          cur->prev = pvt;
05537          return;
05538       }
05539    }
05540 
05541    /* New interface goes onto the end of the list */
05542    pvt->prev = ifend;
05543    pvt->next = NULL;
05544    if (ifend) {
05545       ifend->next = pvt;
05546    }
05547    ifend = pvt;
05548    if (!iflist) {
05549       /* List was empty */
05550       iflist = pvt;
05551    }
05552 }
05553 
05554 /*!
05555  * \internal
05556  * \brief Extract the given chan_dahdi interface structure from the interface list.
05557  * \since 1.8
05558  *
05559  * \param pvt chan_dahdi private interface structure to extract.
05560  *
05561  * \note
05562  * The given interface structure can be either in the interface list or a stand alone
05563  * structure that has not been put in the list if the next and prev pointers are NULL.
05564  *
05565  * \return Nothing
05566  */
05567 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05568 {
05569    /* Extract from the forward chain. */
05570    if (pvt->prev) {
05571       pvt->prev->next = pvt->next;
05572    } else if (iflist == pvt) {
05573       /* Node is at the head of the list. */
05574       iflist = pvt->next;
05575    }
05576 
05577    /* Extract from the reverse chain. */
05578    if (pvt->next) {
05579       pvt->next->prev = pvt->prev;
05580    } else if (ifend == pvt) {
05581       /* Node is at the end of the list. */
05582       ifend = pvt->prev;
05583    }
05584 
05585    /* Node is no longer in the list. */
05586    pvt->which_iflist = DAHDI_IFLIST_NONE;
05587    pvt->prev = NULL;
05588    pvt->next = NULL;
05589 }
05590 
05591 #if defined(HAVE_PRI)
05592 /*!
05593  * \internal
05594  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05595  * \since 1.8
05596  *
05597  * \param pri sig_pri span control structure holding no B channel list.
05598  * \param pvt chan_dahdi private interface structure to insert.
05599  *
05600  * \details
05601  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05602  * Any duplicates are inserted after the existing entries.
05603  *
05604  * \note The new interface must not already be in the list.
05605  *
05606  * \return Nothing
05607  */
05608 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05609 {
05610    struct dahdi_pvt *cur;
05611 
05612    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05613 
05614    /* Find place in middle of list for the new interface. */
05615    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05616       if (pvt->channel < cur->channel) {
05617          /* New interface goes before the current interface. */
05618          pvt->prev = cur->prev;
05619          pvt->next = cur;
05620          if (cur->prev) {
05621             /* Insert into the middle of the list. */
05622             cur->prev->next = pvt;
05623          } else {
05624             /* Insert at head of list. */
05625             pri->no_b_chan_iflist = pvt;
05626          }
05627          cur->prev = pvt;
05628          return;
05629       }
05630    }
05631 
05632    /* New interface goes onto the end of the list */
05633    pvt->prev = pri->no_b_chan_end;
05634    pvt->next = NULL;
05635    if (pri->no_b_chan_end) {
05636       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05637    }
05638    pri->no_b_chan_end = pvt;
05639    if (!pri->no_b_chan_iflist) {
05640       /* List was empty */
05641       pri->no_b_chan_iflist = pvt;
05642    }
05643 }
05644 #endif   /* defined(HAVE_PRI) */
05645 
05646 #if defined(HAVE_PRI)
05647 /*!
05648  * \internal
05649  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05650  * \since 1.8
05651  *
05652  * \param pri sig_pri span control structure holding no B channel list.
05653  * \param pvt chan_dahdi private interface structure to extract.
05654  *
05655  * \note
05656  * The given interface structure can be either in the interface list or a stand alone
05657  * structure that has not been put in the list if the next and prev pointers are NULL.
05658  *
05659  * \return Nothing
05660  */
05661 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05662 {
05663    /* Extract from the forward chain. */
05664    if (pvt->prev) {
05665       pvt->prev->next = pvt->next;
05666    } else if (pri->no_b_chan_iflist == pvt) {
05667       /* Node is at the head of the list. */
05668       pri->no_b_chan_iflist = pvt->next;
05669    }
05670 
05671    /* Extract from the reverse chain. */
05672    if (pvt->next) {
05673       pvt->next->prev = pvt->prev;
05674    } else if (pri->no_b_chan_end == pvt) {
05675       /* Node is at the end of the list. */
05676       pri->no_b_chan_end = pvt->prev;
05677    }
05678 
05679    /* Node is no longer in the list. */
05680    pvt->which_iflist = DAHDI_IFLIST_NONE;
05681    pvt->prev = NULL;
05682    pvt->next = NULL;
05683 }
05684 #endif   /* defined(HAVE_PRI) */
05685 
05686 #if defined(HAVE_PRI)
05687 /*!
05688  * \internal
05689  * \brief Unlink the channel interface from the PRI private pointer array.
05690  * \since 1.8
05691  *
05692  * \param pvt chan_dahdi private interface structure to unlink.
05693  *
05694  * \return Nothing
05695  */
05696 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05697 {
05698    unsigned idx;
05699    struct sig_pri_span *pri;
05700 
05701    pri = pvt->pri;
05702    if (!pri) {
05703       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05704       return;
05705    }
05706    ast_mutex_lock(&pri->lock);
05707    for (idx = 0; idx < pri->numchans; ++idx) {
05708       if (pri->pvts[idx] == pvt->sig_pvt) {
05709          pri->pvts[idx] = NULL;
05710          ast_mutex_unlock(&pri->lock);
05711          return;
05712       }
05713    }
05714    ast_mutex_unlock(&pri->lock);
05715 }
05716 #endif   /* defined(HAVE_PRI) */
05717 
05718 #if defined(HAVE_SS7)
05719 /*!
05720  * \internal
05721  * \brief Unlink the channel interface from the SS7 private pointer array.
05722  * \since 1.8
05723  *
05724  * \param pvt chan_dahdi private interface structure to unlink.
05725  *
05726  * \return Nothing
05727  */
05728 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05729 {
05730    unsigned idx;
05731    struct sig_ss7_linkset *ss7;
05732 
05733    ss7 = pvt->ss7;
05734    if (!ss7) {
05735       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05736       return;
05737    }
05738    ast_mutex_lock(&ss7->lock);
05739    for (idx = 0; idx < ss7->numchans; ++idx) {
05740       if (ss7->pvts[idx] == pvt->sig_pvt) {
05741          ss7->pvts[idx] = NULL;
05742          ast_mutex_unlock(&ss7->lock);
05743          return;
05744       }
05745    }
05746    ast_mutex_unlock(&ss7->lock);
05747 }
05748 #endif   /* defined(HAVE_SS7) */
05749 
05750 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05751 {
05752    if (cur->next && cur->next->span == cur->span) {
05753       return cur->next;
05754    } else if (cur->prev && cur->prev->span == cur->span) {
05755       return cur->prev;
05756    }
05757 
05758    return NULL;
05759 }
05760 
05761 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05762 {
05763    struct dahdi_pvt *p = pvt;
05764 
05765    if (p->manages_span_alarms) {
05766       struct dahdi_pvt *next = find_next_iface_in_span(p);
05767       if (next) {
05768          next->manages_span_alarms = 1;
05769       }
05770    }
05771 
05772    /* Remove channel from the list */
05773 #if defined(HAVE_PRI)
05774    dahdi_unlink_pri_pvt(p);
05775 #endif   /* defined(HAVE_PRI) */
05776 #if defined(HAVE_SS7)
05777    dahdi_unlink_ss7_pvt(p);
05778 #endif   /* defined(HAVE_SS7) */
05779    switch (pvt->which_iflist) {
05780    case DAHDI_IFLIST_NONE:
05781       break;
05782    case DAHDI_IFLIST_MAIN:
05783       dahdi_iflist_extract(p);
05784       break;
05785 #if defined(HAVE_PRI)
05786    case DAHDI_IFLIST_NO_B_CHAN:
05787       if (p->pri) {
05788          dahdi_nobch_extract(p->pri, p);
05789       }
05790       break;
05791 #endif   /* defined(HAVE_PRI) */
05792    }
05793 
05794    if (p->sig_pvt) {
05795       if (analog_lib_handles(p->sig, 0, 0)) {
05796          analog_delete(p->sig_pvt);
05797       }
05798       switch (p->sig) {
05799 #if defined(HAVE_PRI)
05800       case SIG_PRI_LIB_HANDLE_CASES:
05801          sig_pri_chan_delete(p->sig_pvt);
05802          break;
05803 #endif   /* defined(HAVE_PRI) */
05804 #if defined(HAVE_SS7)
05805       case SIG_SS7:
05806          sig_ss7_chan_delete(p->sig_pvt);
05807          break;
05808 #endif   /* defined(HAVE_SS7) */
05809       default:
05810          break;
05811       }
05812    }
05813    ast_free(p->cidspill);
05814    if (p->use_smdi)
05815       ast_smdi_interface_unref(p->smdi_iface);
05816    if (p->mwi_event_sub)
05817       ast_event_unsubscribe(p->mwi_event_sub);
05818    if (p->vars) {
05819       ast_variables_destroy(p->vars);
05820    }
05821    if (p->cc_params) {
05822       ast_cc_config_params_destroy(p->cc_params);
05823    }
05824    ast_mutex_destroy(&p->lock);
05825    dahdi_close_sub(p, SUB_REAL);
05826    if (p->owner)
05827       p->owner->tech_pvt = NULL;
05828    ast_free(p);
05829 }
05830 
05831 static void destroy_channel(struct dahdi_pvt *cur, int now)
05832 {
05833    int i;
05834 
05835    if (!now) {
05836       /* Do not destroy the channel now if it is owned by someone. */
05837       if (cur->owner) {
05838          return;
05839       }
05840       for (i = 0; i < 3; i++) {
05841          if (cur->subs[i].owner) {
05842             return;
05843          }
05844       }
05845    }
05846    destroy_dahdi_pvt(cur);
05847 }
05848 
05849 static void destroy_all_channels(void)
05850 {
05851    int chan;
05852 #if defined(HAVE_PRI)
05853    unsigned span;
05854    struct sig_pri_span *pri;
05855 #endif   /* defined(HAVE_PRI) */
05856    struct dahdi_pvt *p;
05857 
05858    while (num_restart_pending) {
05859       usleep(1);
05860    }
05861 
05862    ast_mutex_lock(&iflock);
05863    /* Destroy all the interfaces and free their memory */
05864    while (iflist) {
05865       p = iflist;
05866 
05867       chan = p->channel;
05868 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05869       {
05870          char db_chan_name[20];
05871          char db_answer[5];
05872          char state;
05873          int why = -1;
05874 
05875          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05876          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05877             sscanf(db_answer, "%1c:%30d", &state, &why);
05878          }
05879          if (!why) {
05880             /* SRVST persistence is not required */
05881             ast_db_del(db_chan_name, SRVST_DBKEY);
05882          }
05883       }
05884 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05885       /* Free associated memory */
05886       destroy_dahdi_pvt(p);
05887       ast_verb(3, "Unregistered channel %d\n", chan);
05888    }
05889    ifcount = 0;
05890    ast_mutex_unlock(&iflock);
05891 
05892 #if defined(HAVE_PRI)
05893    /* Destroy all of the no B channel interface lists */
05894    for (span = 0; span < NUM_SPANS; ++span) {
05895       if (!pris[span].dchannels[0]) {
05896          break;
05897       }
05898       pri = &pris[span].pri;
05899       ast_mutex_lock(&pri->lock);
05900       while (pri->no_b_chan_iflist) {
05901          p = pri->no_b_chan_iflist;
05902 
05903          /* Free associated memory */
05904          destroy_dahdi_pvt(p);
05905       }
05906       ast_mutex_unlock(&pri->lock);
05907    }
05908 #endif   /* defined(HAVE_PRI) */
05909 }
05910 
05911 #if defined(HAVE_PRI)
05912 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05913 
05914 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05915 {
05916    /* Data will be our digit string */
05917    struct dahdi_pvt *p;
05918 
05919    if (ast_strlen_zero(digits)) {
05920       ast_debug(1, "No digit string sent to application!\n");
05921       return -1;
05922    }
05923 
05924    p = (struct dahdi_pvt *)chan->tech_pvt;
05925 
05926    if (!p) {
05927       ast_debug(1, "Unable to find technology private\n");
05928       return -1;
05929    }
05930 
05931    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05932 
05933    return 0;
05934 }
05935 #endif   /* defined(HAVE_PRI) */
05936 
05937 #if defined(HAVE_PRI)
05938 #if defined(HAVE_PRI_PROG_W_CAUSE)
05939 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05940 
05941 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05942 {
05943    /* Data will be our digit string */
05944    struct dahdi_pvt *pvt;
05945    char *parse;
05946    int res;
05947    AST_DECLARE_APP_ARGS(args,
05948       AST_APP_ARG(destination);
05949       AST_APP_ARG(original);
05950       AST_APP_ARG(reason);
05951    );
05952 
05953    if (ast_strlen_zero(data)) {
05954       ast_log(LOG_DEBUG, "No data sent to application!\n");
05955       return -1;
05956    }
05957    if (chan->tech != &dahdi_tech) {
05958       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05959       return -1;
05960    }
05961    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05962    if (!pvt) {
05963       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05964       return -1;
05965    }
05966    switch (pvt->sig) {
05967    case SIG_PRI_LIB_HANDLE_CASES:
05968       break;
05969    default:
05970       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05971          chan->name);
05972       return -1;
05973    }
05974 
05975    parse = ast_strdupa(data);
05976    AST_STANDARD_APP_ARGS(args, parse);
05977 
05978    if (ast_strlen_zero(args.destination)) {
05979       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05980       return -1;
05981    }
05982 
05983    if (ast_strlen_zero(args.original)) {
05984       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05985       args.original = NULL;
05986    }
05987 
05988    if (ast_strlen_zero(args.reason)) {
05989       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05990       args.reason = NULL;
05991    }
05992 
05993    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05994       args.destination, args.original, args.reason);
05995    if (!res) {
05996       /*
05997        * Wait up to 5 seconds for a reply before hanging up this call
05998        * leg if the peer does not disconnect first.
05999        */
06000       ast_safe_sleep(chan, 5000);
06001    }
06002 
06003    return -1;
06004 }
06005 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06006 #endif   /* defined(HAVE_PRI) */
06007 
06008 #if defined(HAVE_OPENR2)
06009 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06010 
06011 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06012 {
06013    /* data is whether to accept with charge or no charge */
06014    openr2_call_mode_t accept_mode;
06015    int res, timeout, maxloops;
06016    struct ast_frame *f;
06017    struct dahdi_pvt *p;
06018    char *parse;
06019    AST_DECLARE_APP_ARGS(args,
06020          AST_APP_ARG(charge);
06021    );
06022 
06023    if (ast_strlen_zero(data)) {
06024       ast_log(LOG_DEBUG, "No data sent to application!\n");
06025       return -1;
06026    }
06027 
06028    if (chan->tech != &dahdi_tech) {
06029       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06030       return -1;
06031    }
06032 
06033    p = (struct dahdi_pvt *)chan->tech_pvt;
06034    if (!p) {
06035       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06036       return -1;
06037    }
06038 
06039    parse = ast_strdupa(data);
06040    AST_STANDARD_APP_ARGS(args, parse);
06041 
06042    if (ast_strlen_zero(args.charge)) {
06043       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06044       return -1;
06045    }
06046 
06047    ast_mutex_lock(&p->lock);
06048    if (!p->mfcr2 || !p->mfcr2call) {
06049       ast_mutex_unlock(&p->lock);
06050       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06051       return -1;
06052    }
06053 
06054    if (p->mfcr2_call_accepted) {
06055       ast_mutex_unlock(&p->lock);
06056       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06057       return 0;
06058    }
06059    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06060    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06061       ast_mutex_unlock(&p->lock);
06062       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06063       return -1;
06064    }
06065    ast_mutex_unlock(&p->lock);
06066 
06067    res = 0;
06068    timeout = 100;
06069    maxloops = 50; /* wait up to 5 seconds */
06070    /* we need to read() until the call is accepted */
06071    while (maxloops > 0) {
06072       maxloops--;
06073       if (ast_check_hangup(chan)) {
06074          break;
06075       }
06076       res = ast_waitfor(chan, timeout);
06077       if (res < 0) {
06078          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06079          res = -1;
06080          break;
06081       }
06082       if (res == 0) {
06083          continue;
06084       }
06085       res = 0;
06086       f = ast_read(chan);
06087       if (!f) {
06088          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06089          res = -1;
06090          break;
06091       }
06092       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06093          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06094          ast_frfree(f);
06095          res = -1;
06096          break;
06097       }
06098       ast_frfree(f);
06099       ast_mutex_lock(&p->lock);
06100       if (p->mfcr2_call_accepted) {
06101          ast_mutex_unlock(&p->lock);
06102          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06103          break;
06104       }
06105       ast_mutex_unlock(&p->lock);
06106    }
06107    if (res == -1) {
06108       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06109    }
06110    return res;
06111 }
06112 
06113 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06114 {
06115    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06116    switch (cause) {
06117    case AST_CAUSE_USER_BUSY:
06118    case AST_CAUSE_CALL_REJECTED:
06119    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06120       r2cause = OR2_CAUSE_BUSY_NUMBER;
06121       break;
06122 
06123    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06124    case AST_CAUSE_SWITCH_CONGESTION:
06125       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06126       break;
06127 
06128    case AST_CAUSE_UNALLOCATED:
06129       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06130       break;
06131 
06132    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06133    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06134       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06135       break;
06136 
06137    case AST_CAUSE_NO_ANSWER:
06138    case AST_CAUSE_NO_USER_RESPONSE:
06139       r2cause = OR2_CAUSE_NO_ANSWER;
06140       break;
06141 
06142    default:
06143       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06144       break;
06145    }
06146    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06147          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06148    return r2cause;
06149 }
06150 #endif
06151 
06152 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06153 {
06154    if (p->bufferoverrideinuse) {
06155       /* faxbuffers are in use, revert them */
06156       struct dahdi_bufferinfo bi = {
06157          .txbufpolicy = p->buf_policy,
06158          .rxbufpolicy = p->buf_policy,
06159          .bufsize = p->bufsize,
06160          .numbufs = p->buf_no
06161       };
06162       int bpres;
06163 
06164       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06165          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06166       }
06167       p->bufferoverrideinuse = 0;
06168       return bpres;
06169    }
06170 
06171    return -1;
06172 }
06173 
06174 static int dahdi_hangup(struct ast_channel *ast)
06175 {
06176    int res = 0;
06177    int idx,x;
06178    int law;
06179    /*static int restore_gains(struct dahdi_pvt *p);*/
06180    struct dahdi_pvt *p = ast->tech_pvt;
06181    struct dahdi_params par;
06182 
06183    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06184    if (!ast->tech_pvt) {
06185       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06186       return 0;
06187    }
06188 
06189    ast_mutex_lock(&p->lock);
06190    p->exten[0] = '\0';
06191    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06192       dahdi_confmute(p, 0);
06193       restore_gains(p);
06194       p->ignoredtmf = 0;
06195       p->waitingfordt.tv_sec = 0;
06196 
06197       res = analog_hangup(p->sig_pvt, ast);
06198       revert_fax_buffers(p, ast);
06199 
06200       goto hangup_out;
06201    } else {
06202       p->cid_num[0] = '\0';
06203       p->cid_name[0] = '\0';
06204       p->cid_subaddr[0] = '\0';
06205    }
06206 
06207 #if defined(HAVE_PRI)
06208    if (dahdi_sig_pri_lib_handles(p->sig)) {
06209       x = 1;
06210       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06211 
06212       dahdi_confmute(p, 0);
06213       p->muting = 0;
06214       restore_gains(p);
06215       if (p->dsp) {
06216          ast_dsp_free(p->dsp);
06217          p->dsp = NULL;
06218       }
06219       p->ignoredtmf = 0;
06220 
06221       /* Real channel, do some fixup */
06222       p->subs[SUB_REAL].owner = NULL;
06223       p->subs[SUB_REAL].needbusy = 0;
06224       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06225 
06226       p->owner = NULL;
06227       p->cid_tag[0] = '\0';
06228       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06229       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06230       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06231       p->outgoing = 0;
06232       p->digital = 0;
06233       p->faxhandled = 0;
06234       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06235 
06236       revert_fax_buffers(p, ast);
06237 
06238       p->law = p->law_default;
06239       law = p->law_default;
06240       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06241       if (res < 0) {
06242          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06243             p->channel, strerror(errno));
06244       }
06245 
06246       sig_pri_hangup(p->sig_pvt, ast);
06247 
06248       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06249       dahdi_disable_ec(p);
06250 
06251       x = 0;
06252       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06253       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06254 
06255       p->rdnis[0] = '\0';
06256       update_conf(p);
06257       reset_conf(p);
06258 
06259       /* Restore data mode */
06260       x = 0;
06261       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06262 
06263       if (num_restart_pending == 0) {
06264          restart_monitor();
06265       }
06266       goto hangup_out;
06267    }
06268 #endif   /* defined(HAVE_PRI) */
06269 
06270 #if defined(HAVE_SS7)
06271    if (p->sig == SIG_SS7) {
06272       x = 1;
06273       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06274 
06275       dahdi_confmute(p, 0);
06276       p->muting = 0;
06277       restore_gains(p);
06278       if (p->dsp) {
06279          ast_dsp_free(p->dsp);
06280          p->dsp = NULL;
06281       }
06282       p->ignoredtmf = 0;
06283 
06284       /* Real channel, do some fixup */
06285       p->subs[SUB_REAL].owner = NULL;
06286       p->subs[SUB_REAL].needbusy = 0;
06287       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06288 
06289       p->owner = NULL;
06290       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06291       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06292       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06293       p->outgoing = 0;
06294       p->digital = 0;
06295       p->faxhandled = 0;
06296       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06297 
06298       revert_fax_buffers(p, ast);
06299 
06300       p->law = p->law_default;
06301       law = p->law_default;
06302       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06303       if (res < 0) {
06304          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06305             p->channel, strerror(errno));
06306       }
06307 
06308       sig_ss7_hangup(p->sig_pvt, ast);
06309 
06310       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06311       dahdi_disable_ec(p);
06312 
06313       x = 0;
06314       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06315       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06316 
06317       update_conf(p);
06318       reset_conf(p);
06319 
06320       /* Restore data mode */
06321       x = 0;
06322       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06323 
06324       if (num_restart_pending == 0) {
06325          restart_monitor();
06326       }
06327       goto hangup_out;
06328    }
06329 #endif   /* defined(HAVE_SS7) */
06330 
06331    idx = dahdi_get_index(ast, p, 1);
06332 
06333    dahdi_confmute(p, 0);
06334    p->muting = 0;
06335    restore_gains(p);
06336    if (p->origcid_num) {
06337       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06338       ast_free(p->origcid_num);
06339       p->origcid_num = NULL;
06340    }
06341    if (p->origcid_name) {
06342       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06343       ast_free(p->origcid_name);
06344       p->origcid_name = NULL;
06345    }
06346    if (p->dsp)
06347       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06348 
06349    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06350       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06351    p->ignoredtmf = 0;
06352 
06353    if (idx > -1) {
06354       /* Real channel, do some fixup */
06355       p->subs[idx].owner = NULL;
06356       p->subs[idx].needanswer = 0;
06357       p->subs[idx].needflash = 0;
06358       p->subs[idx].needringing = 0;
06359       p->subs[idx].needbusy = 0;
06360       p->subs[idx].needcongestion = 0;
06361       p->subs[idx].linear = 0;
06362       p->polarity = POLARITY_IDLE;
06363       dahdi_setlinear(p->subs[idx].dfd, 0);
06364       if (idx == SUB_REAL) {
06365          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06366             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06367             if (p->subs[SUB_CALLWAIT].inthreeway) {
06368                /* We had flipped over to answer a callwait and now it's gone */
06369                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06370                /* Move to the call-wait, but un-own us until they flip back. */
06371                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06372                unalloc_sub(p, SUB_CALLWAIT);
06373                p->owner = NULL;
06374             } else {
06375                /* The three way hung up, but we still have a call wait */
06376                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06377                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06378                unalloc_sub(p, SUB_THREEWAY);
06379                if (p->subs[SUB_REAL].inthreeway) {
06380                   /* This was part of a three way call.  Immediately make way for
06381                      another call */
06382                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06383                   p->owner = p->subs[SUB_REAL].owner;
06384                } else {
06385                   /* This call hasn't been completed yet...  Set owner to NULL */
06386                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06387                   p->owner = NULL;
06388                }
06389                p->subs[SUB_REAL].inthreeway = 0;
06390             }
06391          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06392             /* Move to the call-wait and switch back to them. */
06393             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06394             unalloc_sub(p, SUB_CALLWAIT);
06395             p->owner = p->subs[SUB_REAL].owner;
06396             if (p->owner->_state != AST_STATE_UP)
06397                p->subs[SUB_REAL].needanswer = 1;
06398             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06399                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06400          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06401             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06402             unalloc_sub(p, SUB_THREEWAY);
06403             if (p->subs[SUB_REAL].inthreeway) {
06404                /* This was part of a three way call.  Immediately make way for
06405                   another call */
06406                ast_debug(1, "Call was complete, setting owner to former third call\n");
06407                p->owner = p->subs[SUB_REAL].owner;
06408             } else {
06409                /* This call hasn't been completed yet...  Set owner to NULL */
06410                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06411                p->owner = NULL;
06412             }
06413             p->subs[SUB_REAL].inthreeway = 0;
06414          }
06415       } else if (idx == SUB_CALLWAIT) {
06416          /* Ditch the holding callwait call, and immediately make it availabe */
06417          if (p->subs[SUB_CALLWAIT].inthreeway) {
06418             /* This is actually part of a three way, placed on hold.  Place the third part
06419                on music on hold now */
06420             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06421                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06422                   S_OR(p->mohsuggest, NULL),
06423                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06424             }
06425             p->subs[SUB_THREEWAY].inthreeway = 0;
06426             /* Make it the call wait now */
06427             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06428             unalloc_sub(p, SUB_THREEWAY);
06429          } else
06430             unalloc_sub(p, SUB_CALLWAIT);
06431       } else if (idx == SUB_THREEWAY) {
06432          if (p->subs[SUB_CALLWAIT].inthreeway) {
06433             /* The other party of the three way call is currently in a call-wait state.
06434                Start music on hold for them, and take the main guy out of the third call */
06435             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06436                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06437                   S_OR(p->mohsuggest, NULL),
06438                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06439             }
06440             p->subs[SUB_CALLWAIT].inthreeway = 0;
06441          }
06442          p->subs[SUB_REAL].inthreeway = 0;
06443          /* If this was part of a three way call index, let us make
06444             another three way call */
06445          unalloc_sub(p, SUB_THREEWAY);
06446       } else {
06447          /* This wasn't any sort of call, but how are we an index? */
06448          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06449       }
06450    }
06451 
06452    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06453       p->owner = NULL;
06454       p->ringt = 0;
06455       p->distinctivering = 0;
06456       p->confirmanswer = 0;
06457       p->outgoing = 0;
06458       p->digital = 0;
06459       p->faxhandled = 0;
06460       p->pulsedial = 0;
06461       if (p->dsp) {
06462          ast_dsp_free(p->dsp);
06463          p->dsp = NULL;
06464       }
06465 
06466       revert_fax_buffers(p, ast);
06467 
06468       p->law = p->law_default;
06469       law = p->law_default;
06470       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06471       if (res < 0)
06472          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06473       /* Perform low level hangup if no owner left */
06474 #ifdef HAVE_OPENR2
06475       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06476          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06477          /* If it's an incoming call, check the mfcr2_forced_release setting */
06478          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06479             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06480          } else {
06481             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06482             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06483             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06484                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06485             dahdi_r2_disconnect_call(p, r2cause);
06486          }
06487       } else if (p->mfcr2call) {
06488          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06489          /* since ast_request() was called but not ast_call() we have not yet dialed
06490          and the openr2 stack will not call on_call_end callback, we need to unset
06491          the mfcr2call flag and bump the monitor count so the monitor thread can take
06492          care of this channel events from now on */
06493          p->mfcr2call = 0;
06494       }
06495 #endif
06496       switch (p->sig) {
06497       case SIG_SS7:
06498       case SIG_MFCR2:
06499       case SIG_PRI_LIB_HANDLE_CASES:
06500       case 0:
06501          break;
06502       default:
06503          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06504          break;
06505       }
06506       if (res < 0) {
06507          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06508       }
06509       switch (p->sig) {
06510       case SIG_FXOGS:
06511       case SIG_FXOLS:
06512       case SIG_FXOKS:
06513          memset(&par, 0, sizeof(par));
06514          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06515          if (!res) {
06516             struct analog_pvt *analog_p = p->sig_pvt;
06517 #if 0
06518             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06519 #endif
06520             /* If they're off hook, try playing congestion */
06521             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06522                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06523             else
06524                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06525             analog_p->fxsoffhookstate = par.rxisoffhook;
06526          }
06527          break;
06528       case SIG_FXSGS:
06529       case SIG_FXSLS:
06530       case SIG_FXSKS:
06531          /* Make sure we're not made available for at least two seconds assuming
06532          we were actually used for an inbound or outbound call. */
06533          if (ast->_state != AST_STATE_RESERVED) {
06534             time(&p->guardtime);
06535             p->guardtime += 2;
06536          }
06537          break;
06538       default:
06539          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06540          break;
06541       }
06542       if (p->sig)
06543          dahdi_disable_ec(p);
06544       x = 0;
06545       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06546       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06547       p->didtdd = 0;
06548       p->callwaitcas = 0;
06549       p->callwaiting = p->permcallwaiting;
06550       p->hidecallerid = p->permhidecallerid;
06551       p->waitingfordt.tv_sec = 0;
06552       p->dialing = 0;
06553       p->rdnis[0] = '\0';
06554       update_conf(p);
06555       reset_conf(p);
06556       /* Restore data mode */
06557       switch (p->sig) {
06558       case SIG_PRI_LIB_HANDLE_CASES:
06559       case SIG_SS7:
06560          x = 0;
06561          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06562          break;
06563       default:
06564          break;
06565       }
06566       if (num_restart_pending == 0)
06567          restart_monitor();
06568    }
06569 
06570    p->callwaitingrepeat = 0;
06571    p->cidcwexpire = 0;
06572    p->cid_suppress_expire = 0;
06573    p->oprmode = 0;
06574 hangup_out:
06575    ast->tech_pvt = NULL;
06576    ast_free(p->cidspill);
06577    p->cidspill = NULL;
06578 
06579    ast_mutex_unlock(&p->lock);
06580    ast_verb(3, "Hungup '%s'\n", ast->name);
06581 
06582    ast_mutex_lock(&iflock);
06583    if (p->restartpending) {
06584       num_restart_pending--;
06585    }
06586 
06587    if (p->destroy) {
06588       destroy_channel(p, 0);
06589    }
06590    ast_mutex_unlock(&iflock);
06591 
06592    ast_module_unref(ast_module_info->self);
06593    return 0;
06594 }
06595 
06596 static int dahdi_answer(struct ast_channel *ast)
06597 {
06598    struct dahdi_pvt *p = ast->tech_pvt;
06599    int res = 0;
06600    int idx;
06601    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06602    ast_mutex_lock(&p->lock);
06603    idx = dahdi_get_index(ast, p, 0);
06604    if (idx < 0)
06605       idx = SUB_REAL;
06606    /* nothing to do if a radio channel */
06607    if ((p->radio || (p->oprmode < 0))) {
06608       ast_mutex_unlock(&p->lock);
06609       return 0;
06610    }
06611 
06612    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06613       res = analog_answer(p->sig_pvt, ast);
06614       ast_mutex_unlock(&p->lock);
06615       return res;
06616    }
06617 
06618    switch (p->sig) {
06619 #if defined(HAVE_PRI)
06620    case SIG_PRI_LIB_HANDLE_CASES:
06621       res = sig_pri_answer(p->sig_pvt, ast);
06622       break;
06623 #endif   /* defined(HAVE_PRI) */
06624 #if defined(HAVE_SS7)
06625    case SIG_SS7:
06626       res = sig_ss7_answer(p->sig_pvt, ast);
06627       break;
06628 #endif   /* defined(HAVE_SS7) */
06629 #ifdef HAVE_OPENR2
06630    case SIG_MFCR2:
06631       if (!p->mfcr2_call_accepted) {
06632          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06633             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06634          p->mfcr2_answer_pending = 1;
06635          if (p->mfcr2_charge_calls) {
06636             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06637             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06638          } else {
06639             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06640             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06641          }
06642       } else {
06643          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06644          dahdi_r2_answer(p);
06645       }
06646       break;
06647 #endif
06648    case 0:
06649       ast_mutex_unlock(&p->lock);
06650       return 0;
06651    default:
06652       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06653       res = -1;
06654       break;
06655    }
06656    ast_mutex_unlock(&p->lock);
06657    return res;
06658 }
06659 
06660 static void disable_dtmf_detect(struct dahdi_pvt *p)
06661 {
06662    int val = 0;
06663 
06664    p->ignoredtmf = 1;
06665 
06666    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06667 
06668    if (!p->hardwaredtmf && p->dsp) {
06669       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06670       ast_dsp_set_features(p->dsp, p->dsp_features);
06671    }
06672 }
06673 
06674 static void enable_dtmf_detect(struct dahdi_pvt *p)
06675 {
06676    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06677 
06678    if (p->channel == CHAN_PSEUDO)
06679       return;
06680 
06681    p->ignoredtmf = 0;
06682 
06683    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06684 
06685    if (!p->hardwaredtmf && p->dsp) {
06686       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06687       ast_dsp_set_features(p->dsp, p->dsp_features);
06688    }
06689 }
06690 
06691 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06692 {
06693    char *cp;
06694    struct dahdi_pvt *p = chan->tech_pvt;
06695 
06696    /* all supported options require data */
06697    if (!p || !data || (*datalen < 1)) {
06698       errno = EINVAL;
06699       return -1;
06700    }
06701 
06702    switch (option) {
06703    case AST_OPTION_DIGIT_DETECT:
06704       cp = (char *) data;
06705       *cp = p->ignoredtmf ? 0 : 1;
06706       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06707       break;
06708    case AST_OPTION_FAX_DETECT:
06709       cp = (char *) data;
06710       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06711       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06712       break;
06713    case AST_OPTION_CC_AGENT_TYPE:
06714 #if defined(HAVE_PRI)
06715 #if defined(HAVE_PRI_CCSS)
06716       if (dahdi_sig_pri_lib_handles(p->sig)) {
06717          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06718          break;
06719       }
06720 #endif   /* defined(HAVE_PRI_CCSS) */
06721 #endif   /* defined(HAVE_PRI) */
06722       return -1;
06723    default:
06724       return -1;
06725    }
06726 
06727    errno = 0;
06728 
06729    return 0;
06730 }
06731 
06732 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06733 {
06734    char *cp;
06735    signed char *scp;
06736    int x;
06737    int idx;
06738    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06739    struct oprmode *oprmode;
06740 
06741 
06742    /* all supported options require data */
06743    if (!p || !data || (datalen < 1)) {
06744       errno = EINVAL;
06745       return -1;
06746    }
06747 
06748    switch (option) {
06749    case AST_OPTION_TXGAIN:
06750       scp = (signed char *) data;
06751       idx = dahdi_get_index(chan, p, 0);
06752       if (idx < 0) {
06753          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06754          return -1;
06755       }
06756       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06757       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06758    case AST_OPTION_RXGAIN:
06759       scp = (signed char *) data;
06760       idx = dahdi_get_index(chan, p, 0);
06761       if (idx < 0) {
06762          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06763          return -1;
06764       }
06765       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06766       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06767    case AST_OPTION_TONE_VERIFY:
06768       if (!p->dsp)
06769          break;
06770       cp = (char *) data;
06771       switch (*cp) {
06772       case 1:
06773          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06774          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06775          break;
06776       case 2:
06777          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06778          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06779          break;
06780       default:
06781          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06782          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06783          break;
06784       }
06785       break;
06786    case AST_OPTION_TDD:
06787       /* turn on or off TDD */
06788       cp = (char *) data;
06789       p->mate = 0;
06790       if (!*cp) { /* turn it off */
06791          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06792          if (p->tdd)
06793             tdd_free(p->tdd);
06794          p->tdd = 0;
06795          break;
06796       }
06797       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06798          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06799       dahdi_disable_ec(p);
06800       /* otherwise, turn it on */
06801       if (!p->didtdd) { /* if havent done it yet */
06802          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06803          unsigned char *buf;
06804          int size, res, fd, len;
06805          struct pollfd fds[1];
06806 
06807          buf = mybuf;
06808          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06809          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06810          len = 40000;
06811          idx = dahdi_get_index(chan, p, 0);
06812          if (idx < 0) {
06813             ast_log(LOG_WARNING, "No index in TDD?\n");
06814             return -1;
06815          }
06816          fd = p->subs[idx].dfd;
06817          while (len) {
06818             if (ast_check_hangup(chan))
06819                return -1;
06820             size = len;
06821             if (size > READ_SIZE)
06822                size = READ_SIZE;
06823             fds[0].fd = fd;
06824             fds[0].events = POLLPRI | POLLOUT;
06825             fds[0].revents = 0;
06826             res = poll(fds, 1, -1);
06827             if (!res) {
06828                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06829                continue;
06830             }
06831             /* if got exception */
06832             if (fds[0].revents & POLLPRI)
06833                return -1;
06834             if (!(fds[0].revents & POLLOUT)) {
06835                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06836                continue;
06837             }
06838             res = write(fd, buf, size);
06839             if (res != size) {
06840                if (res == -1) return -1;
06841                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06842                break;
06843             }
06844             len -= size;
06845             buf += size;
06846          }
06847          p->didtdd = 1; /* set to have done it now */
06848       }
06849       if (*cp == 2) { /* Mate mode */
06850          if (p->tdd)
06851             tdd_free(p->tdd);
06852          p->tdd = 0;
06853          p->mate = 1;
06854          break;
06855       }
06856       if (!p->tdd) { /* if we don't have one yet */
06857          p->tdd = tdd_new(); /* allocate one */
06858       }
06859       break;
06860    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06861       if (!p->dsp)
06862          break;
06863       cp = (char *) data;
06864       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06865          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06866       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06867       break;
06868    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06869 #if defined(HAVE_PRI)
06870       if (dahdi_sig_pri_lib_handles(p->sig)
06871          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06872          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06873          break;
06874       }
06875 #endif   /* defined(HAVE_PRI) */
06876 
06877       cp = (char *) data;
06878       if (!*cp) {
06879          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06880          x = 0;
06881          dahdi_disable_ec(p);
06882       } else {
06883          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06884          x = 1;
06885       }
06886       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06887          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06888       break;
06889    case AST_OPTION_OPRMODE:  /* Operator services mode */
06890       oprmode = (struct oprmode *) data;
06891       /* We don't support operator mode across technologies */
06892       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06893          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06894                chan->tech->type, oprmode->peer->tech->type);
06895          errno = EINVAL;
06896          return -1;
06897       }
06898       pp = oprmode->peer->tech_pvt;
06899       p->oprmode = pp->oprmode = 0;
06900       /* setup peers */
06901       p->oprpeer = pp;
06902       pp->oprpeer = p;
06903       /* setup modes, if any */
06904       if (oprmode->mode)
06905       {
06906          pp->oprmode = oprmode->mode;
06907          p->oprmode = -oprmode->mode;
06908       }
06909       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06910          oprmode->mode, chan->name,oprmode->peer->name);
06911       break;
06912    case AST_OPTION_ECHOCAN:
06913       cp = (char *) data;
06914       if (*cp) {
06915          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06916          dahdi_enable_ec(p);
06917       } else {
06918          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06919          dahdi_disable_ec(p);
06920       }
06921       break;
06922    case AST_OPTION_DIGIT_DETECT:
06923       cp = (char *) data;
06924       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06925       if (*cp) {
06926          enable_dtmf_detect(p);
06927       } else {
06928          disable_dtmf_detect(p);
06929       }
06930       break;
06931    case AST_OPTION_FAX_DETECT:
06932       cp = (char *) data;
06933       if (p->dsp) {
06934          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06935          if (*cp) {
06936             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06937          } else {
06938             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06939          }
06940          ast_dsp_set_features(p->dsp, p->dsp_features);
06941       }
06942       break;
06943    default:
06944       return -1;
06945    }
06946    errno = 0;
06947 
06948    return 0;
06949 }
06950 
06951 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06952 {
06953    struct dahdi_pvt *p = chan->tech_pvt;
06954    int res = 0;
06955 
06956    if (!p) {
06957       /* No private structure! */
06958       *buf = '\0';
06959       return -1;
06960    }
06961 
06962    if (!strcasecmp(data, "rxgain")) {
06963       ast_mutex_lock(&p->lock);
06964       snprintf(buf, len, "%f", p->rxgain);
06965       ast_mutex_unlock(&p->lock);
06966    } else if (!strcasecmp(data, "txgain")) {
06967       ast_mutex_lock(&p->lock);
06968       snprintf(buf, len, "%f", p->txgain);
06969       ast_mutex_unlock(&p->lock);
06970    } else if (!strcasecmp(data, "dahdi_channel")) {
06971       ast_mutex_lock(&p->lock);
06972       snprintf(buf, len, "%d", p->channel);
06973       ast_mutex_unlock(&p->lock);
06974    } else if (!strcasecmp(data, "dahdi_span")) {
06975       ast_mutex_lock(&p->lock);
06976       snprintf(buf, len, "%d", p->span);
06977       ast_mutex_unlock(&p->lock);
06978    } else if (!strcasecmp(data, "dahdi_type")) {
06979       ast_mutex_lock(&p->lock);
06980       switch (p->sig) {
06981 #if defined(HAVE_OPENR2)
06982       case SIG_MFCR2:
06983          ast_copy_string(buf, "mfc/r2", len);
06984          break;
06985 #endif   /* defined(HAVE_OPENR2) */
06986 #if defined(HAVE_PRI)
06987       case SIG_PRI_LIB_HANDLE_CASES:
06988          ast_copy_string(buf, "pri", len);
06989          break;
06990 #endif   /* defined(HAVE_PRI) */
06991       case 0:
06992          ast_copy_string(buf, "pseudo", len);
06993          break;
06994 #if defined(HAVE_SS7)
06995       case SIG_SS7:
06996          ast_copy_string(buf, "ss7", len);
06997          break;
06998 #endif   /* defined(HAVE_SS7) */
06999       default:
07000          /* The only thing left is analog ports. */
07001          ast_copy_string(buf, "analog", len);
07002          break;
07003       }
07004       ast_mutex_unlock(&p->lock);
07005 #if defined(HAVE_PRI)
07006 #if defined(HAVE_PRI_REVERSE_CHARGE)
07007    } else if (!strcasecmp(data, "reversecharge")) {
07008       ast_mutex_lock(&p->lock);
07009       switch (p->sig) {
07010       case SIG_PRI_LIB_HANDLE_CASES:
07011          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07012          break;
07013       default:
07014          *buf = '\0';
07015          res = -1;
07016          break;
07017       }
07018       ast_mutex_unlock(&p->lock);
07019 #endif
07020 #if defined(HAVE_PRI_SETUP_KEYPAD)
07021    } else if (!strcasecmp(data, "keypad_digits")) {
07022       ast_mutex_lock(&p->lock);
07023       switch (p->sig) {
07024       case SIG_PRI_LIB_HANDLE_CASES:
07025          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07026             len);
07027          break;
07028       default:
07029          *buf = '\0';
07030          res = -1;
07031          break;
07032       }
07033       ast_mutex_unlock(&p->lock);
07034 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07035    } else if (!strcasecmp(data, "no_media_path")) {
07036       ast_mutex_lock(&p->lock);
07037       switch (p->sig) {
07038       case SIG_PRI_LIB_HANDLE_CASES:
07039          /*
07040           * TRUE if the call is on hold or is call waiting because
07041           * there is no media path available.
07042           */
07043          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07044          break;
07045       default:
07046          *buf = '\0';
07047          res = -1;
07048          break;
07049       }
07050       ast_mutex_unlock(&p->lock);
07051 #endif   /* defined(HAVE_PRI) */
07052    } else {
07053       *buf = '\0';
07054       res = -1;
07055    }
07056 
07057    return res;
07058 }
07059 
07060 
07061 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07062 {
07063    int res;
07064    char policy_str[21] = "";
07065 
07066    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07067       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07068       return 1;
07069    }
07070    if (*num_buffers < 0) {
07071       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07072       return -1;
07073    }
07074    if (!strcasecmp(policy_str, "full")) {
07075       *policy = DAHDI_POLICY_WHEN_FULL;
07076    } else if (!strcasecmp(policy_str, "immediate")) {
07077       *policy = DAHDI_POLICY_IMMEDIATE;
07078 #if defined(HAVE_DAHDI_HALF_FULL)
07079    } else if (!strcasecmp(policy_str, "half")) {
07080       *policy = DAHDI_POLICY_HALF_FULL;
07081 #endif
07082    } else {
07083       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07084       return -1;
07085    }
07086 
07087    return 0;
07088 }
07089 
07090 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07091 {
07092    struct dahdi_pvt *p = chan->tech_pvt;
07093    int res = 0;
07094 
07095    if (!p) {
07096       /* No private structure! */
07097       return -1;
07098    }
07099 
07100    if (!strcasecmp(data, "buffers")) {
07101       int num_bufs, policy;
07102 
07103       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07104          struct dahdi_bufferinfo bi = {
07105             .txbufpolicy = policy,
07106             .rxbufpolicy = policy,
07107             .bufsize = p->bufsize,
07108             .numbufs = num_bufs,
07109          };
07110          int bpres;
07111 
07112          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07113             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07114          } else {
07115             p->bufferoverrideinuse = 1;
07116          }
07117       } else {
07118          res = -1;
07119       }
07120    } else if (!strcasecmp(data, "echocan_mode")) {
07121       if (!strcasecmp(value, "on")) {
07122          ast_mutex_lock(&p->lock);
07123          dahdi_enable_ec(p);
07124          ast_mutex_unlock(&p->lock);
07125       } else if (!strcasecmp(value, "off")) {
07126          ast_mutex_lock(&p->lock);
07127          dahdi_disable_ec(p);
07128          ast_mutex_unlock(&p->lock);
07129 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07130       } else if (!strcasecmp(value, "fax")) {
07131          int blah = 1;
07132 
07133          ast_mutex_lock(&p->lock);
07134          if (!p->echocanon) {
07135             dahdi_enable_ec(p);
07136          }
07137          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07138             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07139          }
07140          ast_mutex_unlock(&p->lock);
07141       } else if (!strcasecmp(value, "voice")) {
07142          int blah = 0;
07143 
07144          ast_mutex_lock(&p->lock);
07145          if (!p->echocanon) {
07146             dahdi_enable_ec(p);
07147          }
07148          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07149             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07150          }
07151          ast_mutex_unlock(&p->lock);
07152 #endif
07153       } else {
07154          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07155          res = -1;
07156       }
07157    } else {
07158       res = -1;
07159    }
07160 
07161    return res;
07162 }
07163 
07164 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07165 {
07166    /* Unlink a specific slave or all slaves/masters from a given master */
07167    int x;
07168    int hasslaves;
07169    if (!master)
07170       return;
07171    if (needlock) {
07172       ast_mutex_lock(&master->lock);
07173       if (slave) {
07174          while (ast_mutex_trylock(&slave->lock)) {
07175             DEADLOCK_AVOIDANCE(&master->lock);
07176          }
07177       }
07178    }
07179    hasslaves = 0;
07180    for (x = 0; x < MAX_SLAVES; x++) {
07181       if (master->slaves[x]) {
07182          if (!slave || (master->slaves[x] == slave)) {
07183             /* Take slave out of the conference */
07184             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07185             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07186             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07187             master->slaves[x]->master = NULL;
07188             master->slaves[x] = NULL;
07189          } else
07190             hasslaves = 1;
07191       }
07192       if (!hasslaves)
07193          master->inconference = 0;
07194    }
07195    if (!slave) {
07196       if (master->master) {
07197          /* Take master out of the conference */
07198          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07199          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07200          hasslaves = 0;
07201          for (x = 0; x < MAX_SLAVES; x++) {
07202             if (master->master->slaves[x] == master)
07203                master->master->slaves[x] = NULL;
07204             else if (master->master->slaves[x])
07205                hasslaves = 1;
07206          }
07207          if (!hasslaves)
07208             master->master->inconference = 0;
07209       }
07210       master->master = NULL;
07211    }
07212    update_conf(master);
07213    if (needlock) {
07214       if (slave)
07215          ast_mutex_unlock(&slave->lock);
07216       ast_mutex_unlock(&master->lock);
07217    }
07218 }
07219 
07220 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07221    int x;
07222    if (!slave || !master) {
07223       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07224       return;
07225    }
07226    for (x = 0; x < MAX_SLAVES; x++) {
07227       if (!master->slaves[x]) {
07228          master->slaves[x] = slave;
07229          break;
07230       }
07231    }
07232    if (x >= MAX_SLAVES) {
07233       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07234       master->slaves[MAX_SLAVES - 1] = slave;
07235    }
07236    if (slave->master)
07237       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07238    slave->master = master;
07239 
07240    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07241 }
07242 
07243 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)
07244 {
07245    struct ast_channel *who;
07246    struct dahdi_pvt *p0, *p1, *op0, *op1;
07247    struct dahdi_pvt *master = NULL, *slave = NULL;
07248    struct ast_frame *f;
07249    int inconf = 0;
07250    int nothingok = 1;
07251    int ofd0, ofd1;
07252    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07253    int os0 = -1, os1 = -1;
07254    int priority = 0;
07255    struct ast_channel *oc0, *oc1;
07256    enum ast_bridge_result res;
07257    struct timeval start = ast_tvnow();
07258 #ifdef PRI_2BCT
07259    int triedtopribridge = 0;
07260    q931_call *q931c0;
07261    q931_call *q931c1;
07262 #endif
07263 
07264    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07265       There is code below to handle it properly until DTMF is actually seen,
07266       but due to currently unresolved issues it's ignored...
07267    */
07268 
07269    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07270       return AST_BRIDGE_FAILED_NOWARN;
07271 
07272    ast_channel_lock(c0);
07273    while (ast_channel_trylock(c1)) {
07274       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07275    }
07276 
07277    p0 = c0->tech_pvt;
07278    p1 = c1->tech_pvt;
07279    /* cant do pseudo-channels here */
07280    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07281       ast_channel_unlock(c0);
07282       ast_channel_unlock(c1);
07283       return AST_BRIDGE_FAILED_NOWARN;
07284    }
07285 
07286    oi0 = dahdi_get_index(c0, p0, 0);
07287    oi1 = dahdi_get_index(c1, p1, 0);
07288    if ((oi0 < 0) || (oi1 < 0)) {
07289       ast_channel_unlock(c0);
07290       ast_channel_unlock(c1);
07291       return AST_BRIDGE_FAILED;
07292    }
07293 
07294    op0 = p0 = c0->tech_pvt;
07295    op1 = p1 = c1->tech_pvt;
07296    ofd0 = c0->fds[0];
07297    ofd1 = c1->fds[0];
07298    oc0 = p0->owner;
07299    oc1 = p1->owner;
07300 
07301    if (ast_mutex_trylock(&p0->lock)) {
07302       /* Don't block, due to potential for deadlock */
07303       ast_channel_unlock(c0);
07304       ast_channel_unlock(c1);
07305       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07306       return AST_BRIDGE_RETRY;
07307    }
07308    if (ast_mutex_trylock(&p1->lock)) {
07309       /* Don't block, due to potential for deadlock */
07310       ast_mutex_unlock(&p0->lock);
07311       ast_channel_unlock(c0);
07312       ast_channel_unlock(c1);
07313       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07314       return AST_BRIDGE_RETRY;
07315    }
07316 
07317    if ((p0->callwaiting && p0->callwaitingcallerid)
07318       || (p1->callwaiting && p1->callwaitingcallerid)) {
07319       /*
07320        * Call Waiting Caller ID requires DTMF detection to know if it
07321        * can send the CID spill.
07322        *
07323        * For now, don't attempt to native bridge if either channel
07324        * needs DTMF detection.  There is code below to handle it
07325        * properly until DTMF is actually seen, but due to currently
07326        * unresolved issues it's ignored...
07327        */
07328       ast_mutex_unlock(&p0->lock);
07329       ast_mutex_unlock(&p1->lock);
07330       ast_channel_unlock(c0);
07331       ast_channel_unlock(c1);
07332       return AST_BRIDGE_FAILED_NOWARN;
07333    }
07334 
07335 #if defined(HAVE_PRI)
07336    if ((dahdi_sig_pri_lib_handles(p0->sig)
07337          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07338       || (dahdi_sig_pri_lib_handles(p1->sig)
07339          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07340       /*
07341        * PRI nobch channels (hold and call waiting) are equivalent to
07342        * pseudo channels and cannot be done here.
07343        */
07344       ast_mutex_unlock(&p0->lock);
07345       ast_mutex_unlock(&p1->lock);
07346       ast_channel_unlock(c0);
07347       ast_channel_unlock(c1);
07348       return AST_BRIDGE_FAILED_NOWARN;
07349    }
07350 #endif   /* defined(HAVE_PRI) */
07351 
07352    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07353       if (p0->owner && p1->owner) {
07354          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07355          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07356             master = p0;
07357             slave = p1;
07358             inconf = 1;
07359          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07360             master = p1;
07361             slave = p0;
07362             inconf = 1;
07363          } else {
07364             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07365             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07366                p0->channel,
07367                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07368                p0->subs[SUB_REAL].inthreeway, p0->channel,
07369                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07370                p1->subs[SUB_REAL].inthreeway);
07371          }
07372          nothingok = 0;
07373       }
07374    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07375       if (p1->subs[SUB_THREEWAY].inthreeway) {
07376          master = p1;
07377          slave = p0;
07378          nothingok = 0;
07379       }
07380    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07381       if (p0->subs[SUB_THREEWAY].inthreeway) {
07382          master = p0;
07383          slave = p1;
07384          nothingok = 0;
07385       }
07386    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07387       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07388          don't put us in anything */
07389       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07390          master = p1;
07391          slave = p0;
07392          nothingok = 0;
07393       }
07394    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07395       /* Same as previous */
07396       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07397          master = p0;
07398          slave = p1;
07399          nothingok = 0;
07400       }
07401    }
07402    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07403       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07404    if (master && slave) {
07405       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07406          in an active threeway call with a channel that is ringing, we should
07407          indicate ringing. */
07408       if ((oi1 == SUB_THREEWAY) &&
07409          p1->subs[SUB_THREEWAY].inthreeway &&
07410          p1->subs[SUB_REAL].owner &&
07411          p1->subs[SUB_REAL].inthreeway &&
07412          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07413          ast_debug(1,
07414             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07415             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07416          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07417          os1 = p1->subs[SUB_REAL].owner->_state;
07418       } else {
07419          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07420             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07421          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07422       }
07423       if ((oi0 == SUB_THREEWAY) &&
07424          p0->subs[SUB_THREEWAY].inthreeway &&
07425          p0->subs[SUB_REAL].owner &&
07426          p0->subs[SUB_REAL].inthreeway &&
07427          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07428          ast_debug(1,
07429             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07430             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07431          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07432          os0 = p0->subs[SUB_REAL].owner->_state;
07433       } else {
07434          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07435             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07436          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07437       }
07438       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07439          if (!p0->echocanbridged || !p1->echocanbridged) {
07440             /* Disable echo cancellation if appropriate */
07441             dahdi_disable_ec(p0);
07442             dahdi_disable_ec(p1);
07443          }
07444       }
07445       dahdi_link(slave, master);
07446       master->inconference = inconf;
07447    } else if (!nothingok)
07448       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07449 
07450    update_conf(p0);
07451    update_conf(p1);
07452    t0 = p0->subs[SUB_REAL].inthreeway;
07453    t1 = p1->subs[SUB_REAL].inthreeway;
07454 
07455    ast_mutex_unlock(&p0->lock);
07456    ast_mutex_unlock(&p1->lock);
07457 
07458    ast_channel_unlock(c0);
07459    ast_channel_unlock(c1);
07460 
07461    /* Native bridge failed */
07462    if ((!master || !slave) && !nothingok) {
07463       dahdi_enable_ec(p0);
07464       dahdi_enable_ec(p1);
07465       return AST_BRIDGE_FAILED;
07466    }
07467 
07468    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07469 
07470    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07471       disable_dtmf_detect(op0);
07472 
07473    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07474       disable_dtmf_detect(op1);
07475 
07476    for (;;) {
07477       struct ast_channel *c0_priority[2] = {c0, c1};
07478       struct ast_channel *c1_priority[2] = {c1, c0};
07479       int ms;
07480 
07481       /* Here's our main loop...  Start by locking things, looking for private parts,
07482          and then balking if anything is wrong */
07483 
07484       ast_channel_lock(c0);
07485       while (ast_channel_trylock(c1)) {
07486          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07487       }
07488 
07489       p0 = c0->tech_pvt;
07490       p1 = c1->tech_pvt;
07491 
07492       if (op0 == p0)
07493          i0 = dahdi_get_index(c0, p0, 1);
07494       if (op1 == p1)
07495          i1 = dahdi_get_index(c1, p1, 1);
07496 
07497       ast_channel_unlock(c0);
07498       ast_channel_unlock(c1);
07499       ms = ast_remaining_ms(start, timeoutms);
07500       if (!ms ||
07501          (op0 != p0) ||
07502          (op1 != p1) ||
07503          (ofd0 != c0->fds[0]) ||
07504          (ofd1 != c1->fds[0]) ||
07505          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07506          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07507          (oc0 != p0->owner) ||
07508          (oc1 != p1->owner) ||
07509          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07510          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07511          (oi0 != i0) ||
07512          (oi1 != i1)) {
07513          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07514             op0->channel, oi0, op1->channel, oi1);
07515          res = AST_BRIDGE_RETRY;
07516          goto return_from_bridge;
07517       }
07518 
07519 #ifdef PRI_2BCT
07520       if (!triedtopribridge) {
07521          triedtopribridge = 1;
07522          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07523             ast_mutex_lock(&p0->pri->lock);
07524             switch (p0->sig) {
07525             case SIG_PRI_LIB_HANDLE_CASES:
07526                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07527                break;
07528             default:
07529                q931c0 = NULL;
07530                break;
07531             }
07532             switch (p1->sig) {
07533             case SIG_PRI_LIB_HANDLE_CASES:
07534                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07535                break;
07536             default:
07537                q931c1 = NULL;
07538                break;
07539             }
07540             if (q931c0 && q931c1) {
07541                pri_channel_bridge(q931c0, q931c1);
07542             }
07543             ast_mutex_unlock(&p0->pri->lock);
07544          }
07545       }
07546 #endif
07547 
07548       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07549       if (!who) {
07550          ast_debug(1, "Ooh, empty read...\n");
07551          continue;
07552       }
07553       f = ast_read(who);
07554       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07555          *fo = f;
07556          *rc = who;
07557          res = AST_BRIDGE_COMPLETE;
07558          goto return_from_bridge;
07559       }
07560       if (f->frametype == AST_FRAME_DTMF) {
07561          if ((who == c0) && p0->pulsedial) {
07562             ast_write(c1, f);
07563          } else if ((who == c1) && p1->pulsedial) {
07564             ast_write(c0, f);
07565          } else {
07566             *fo = f;
07567             *rc = who;
07568             res = AST_BRIDGE_COMPLETE;
07569             goto return_from_bridge;
07570          }
07571       }
07572       ast_frfree(f);
07573 
07574       /* Swap who gets priority */
07575       priority = !priority;
07576    }
07577 
07578 return_from_bridge:
07579    if (op0 == p0)
07580       dahdi_enable_ec(p0);
07581 
07582    if (op1 == p1)
07583       dahdi_enable_ec(p1);
07584 
07585    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07586       enable_dtmf_detect(op0);
07587 
07588    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07589       enable_dtmf_detect(op1);
07590 
07591    dahdi_unlink(slave, master, 1);
07592 
07593    return res;
07594 }
07595 
07596 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07597 {
07598    struct dahdi_pvt *p = newchan->tech_pvt;
07599    int x;
07600 
07601    ast_mutex_lock(&p->lock);
07602 
07603    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07604    if (p->owner == oldchan) {
07605       p->owner = newchan;
07606    }
07607    for (x = 0; x < 3; x++) {
07608       if (p->subs[x].owner == oldchan) {
07609          if (!x) {
07610             dahdi_unlink(NULL, p, 0);
07611          }
07612          p->subs[x].owner = newchan;
07613       }
07614    }
07615    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07616       analog_fixup(oldchan, newchan, p->sig_pvt);
07617 #if defined(HAVE_PRI)
07618    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07619       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07620 #endif   /* defined(HAVE_PRI) */
07621 #if defined(HAVE_SS7)
07622    } else if (p->sig == SIG_SS7) {
07623       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07624 #endif   /* defined(HAVE_SS7) */
07625    }
07626    update_conf(p);
07627 
07628    ast_mutex_unlock(&p->lock);
07629 
07630    if (newchan->_state == AST_STATE_RINGING) {
07631       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07632    }
07633    return 0;
07634 }
07635 
07636 static int dahdi_ring_phone(struct dahdi_pvt *p)
07637 {
07638    int x;
07639    int res;
07640    /* Make sure our transmit state is on hook */
07641    x = 0;
07642    x = DAHDI_ONHOOK;
07643    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07644    do {
07645       x = DAHDI_RING;
07646       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07647       if (res) {
07648          switch (errno) {
07649          case EBUSY:
07650          case EINTR:
07651             /* Wait just in case */
07652             usleep(10000);
07653             continue;
07654          case EINPROGRESS:
07655             res = 0;
07656             break;
07657          default:
07658             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07659             res = 0;
07660          }
07661       }
07662    } while (res);
07663    return res;
07664 }
07665 
07666 static void *analog_ss_thread(void *data);
07667 
07668 static int attempt_transfer(struct dahdi_pvt *p)
07669 {
07670    /* In order to transfer, we need at least one of the channels to
07671       actually be in a call bridge.  We can't conference two applications
07672       together (but then, why would we want to?) */
07673    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07674       /* The three-way person we're about to transfer to could still be in MOH, so
07675          stop if now if appropriate */
07676       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07677          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07678       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07679          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07680       }
07681       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07682          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07683       }
07684        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07685          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07686                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07687          return -1;
07688       }
07689       /* Orphan the channel after releasing the lock */
07690       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07691       unalloc_sub(p, SUB_THREEWAY);
07692    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07693       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07694       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07695          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07696       }
07697       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07698          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07699       }
07700       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07701          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07702                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07703          return -1;
07704       }
07705       /* Three-way is now the REAL */
07706       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07707       ast_channel_unlock(p->subs[SUB_REAL].owner);
07708       unalloc_sub(p, SUB_THREEWAY);
07709       /* Tell the caller not to hangup */
07710       return 1;
07711    } else {
07712       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07713          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07714       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07715       return -1;
07716    }
07717    return 0;
07718 }
07719 
07720 static int check_for_conference(struct dahdi_pvt *p)
07721 {
07722    struct dahdi_confinfo ci;
07723    /* Fine if we already have a master, etc */
07724    if (p->master || (p->confno > -1))
07725       return 0;
07726    memset(&ci, 0, sizeof(ci));
07727    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07728       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07729       return 0;
07730    }
07731    /* If we have no master and don't have a confno, then
07732       if we're in a conference, it's probably a MeetMe room or
07733       some such, so don't let us 3-way out! */
07734    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07735       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07736       return 1;
07737    }
07738    return 0;
07739 }
07740 
07741 /*! Checks channel for alarms
07742  * \param p a channel to check for alarms.
07743  * \returns the alarms on the span to which the channel belongs, or alarms on
07744  *          the channel if no span alarms.
07745  */
07746 static int get_alarms(struct dahdi_pvt *p)
07747 {
07748    int res;
07749    struct dahdi_spaninfo zi;
07750    struct dahdi_params params;
07751 
07752    memset(&zi, 0, sizeof(zi));
07753    zi.spanno = p->span;
07754 
07755    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07756       if (zi.alarms != DAHDI_ALARM_NONE)
07757          return zi.alarms;
07758    } else {
07759       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07760       return 0;
07761    }
07762 
07763    /* No alarms on the span. Check for channel alarms. */
07764    memset(&params, 0, sizeof(params));
07765    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07766       return params.chan_alarms;
07767 
07768    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07769 
07770    return DAHDI_ALARM_NONE;
07771 }
07772 
07773 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07774 {
07775    struct dahdi_pvt *p = ast->tech_pvt;
07776    struct ast_frame *f = *dest;
07777 
07778    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07779       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07780       f->subclass.integer, f->subclass.integer, ast->name);
07781 
07782    if (p->confirmanswer) {
07783       if (f->frametype == AST_FRAME_DTMF_END) {
07784          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07785          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07786             of a DTMF digit */
07787          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07788          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07789          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07790          p->confirmanswer = 0;
07791       } else {
07792          p->subs[idx].f.frametype = AST_FRAME_NULL;
07793          p->subs[idx].f.subclass.integer = 0;
07794       }
07795       *dest = &p->subs[idx].f;
07796    } else if (p->callwaitcas) {
07797       if (f->frametype == AST_FRAME_DTMF_END) {
07798          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07799             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07800             ast_free(p->cidspill);
07801             p->cidspill = NULL;
07802             send_cwcidspill(p);
07803          }
07804          p->callwaitcas = 0;
07805       }
07806       p->subs[idx].f.frametype = AST_FRAME_NULL;
07807       p->subs[idx].f.subclass.integer = 0;
07808       *dest = &p->subs[idx].f;
07809    } else if (f->subclass.integer == 'f') {
07810       if (f->frametype == AST_FRAME_DTMF_END) {
07811          /* Fax tone -- Handle and return NULL */
07812          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07813             /* If faxbuffers are configured, use them for the fax transmission */
07814             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07815                struct dahdi_bufferinfo bi = {
07816                   .txbufpolicy = p->faxbuf_policy,
07817                   .bufsize = p->bufsize,
07818                   .numbufs = p->faxbuf_no
07819                };
07820                int res;
07821 
07822                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07823                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07824                } else {
07825                   p->bufferoverrideinuse = 1;
07826                }
07827             }
07828             p->faxhandled = 1;
07829             if (p->dsp) {
07830                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07831                ast_dsp_set_features(p->dsp, p->dsp_features);
07832                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07833             }
07834             if (strcmp(ast->exten, "fax")) {
07835                const char *target_context = S_OR(ast->macrocontext, ast->context);
07836 
07837                /* We need to unlock 'ast' here because ast_exists_extension has the
07838                 * potential to start autoservice on the channel. Such action is prone
07839                 * to deadlock.
07840                 */
07841                ast_mutex_unlock(&p->lock);
07842                ast_channel_unlock(ast);
07843                if (ast_exists_extension(ast, target_context, "fax", 1,
07844                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07845                   ast_channel_lock(ast);
07846                   ast_mutex_lock(&p->lock);
07847                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07848                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07849                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07850                   if (ast_async_goto(ast, target_context, "fax", 1))
07851                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07852                } else {
07853                   ast_channel_lock(ast);
07854                   ast_mutex_lock(&p->lock);
07855                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07856                }
07857             } else {
07858                ast_debug(1, "Already in a fax extension, not redirecting\n");
07859             }
07860          } else {
07861             ast_debug(1, "Fax already handled\n");
07862          }
07863          dahdi_confmute(p, 0);
07864       }
07865       p->subs[idx].f.frametype = AST_FRAME_NULL;
07866       p->subs[idx].f.subclass.integer = 0;
07867       *dest = &p->subs[idx].f;
07868    }
07869 }
07870 
07871 static void handle_alarms(struct dahdi_pvt *p, int alms)
07872 {
07873    const char *alarm_str;
07874 
07875 #if defined(HAVE_PRI)
07876    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07877       return;
07878    }
07879 #endif   /* defined(HAVE_PRI) */
07880 
07881    alarm_str = alarm2str(alms);
07882    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07883       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07884       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07885                  "Alarm: %s\r\n"
07886                  "Channel: %d\r\n",
07887                  alarm_str, p->channel);
07888    }
07889 
07890    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07891       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07892       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07893                  "Alarm: %s\r\n"
07894                  "Span: %d\r\n",
07895                  alarm_str, p->span);
07896    }
07897 }
07898 
07899 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07900 {
07901    int res, x;
07902    int idx, mysig;
07903    char *c;
07904    struct dahdi_pvt *p = ast->tech_pvt;
07905    pthread_t threadid;
07906    struct ast_channel *chan;
07907    struct ast_frame *f;
07908 
07909    idx = dahdi_get_index(ast, p, 0);
07910    if (idx < 0) {
07911       return &ast_null_frame;
07912    }
07913    mysig = p->sig;
07914    if (p->outsigmod > -1)
07915       mysig = p->outsigmod;
07916    p->subs[idx].f.frametype = AST_FRAME_NULL;
07917    p->subs[idx].f.subclass.integer = 0;
07918    p->subs[idx].f.datalen = 0;
07919    p->subs[idx].f.samples = 0;
07920    p->subs[idx].f.mallocd = 0;
07921    p->subs[idx].f.offset = 0;
07922    p->subs[idx].f.src = "dahdi_handle_event";
07923    p->subs[idx].f.data.ptr = NULL;
07924    f = &p->subs[idx].f;
07925 
07926    if (p->fake_event) {
07927       res = p->fake_event;
07928       p->fake_event = 0;
07929    } else
07930       res = dahdi_get_event(p->subs[idx].dfd);
07931 
07932    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07933 
07934    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07935       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07936       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07937 #if defined(HAVE_PRI)
07938       if (dahdi_sig_pri_lib_handles(p->sig)
07939          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07940          && p->pri
07941          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07942          /* absorb event */
07943       } else
07944 #endif   /* defined(HAVE_PRI) */
07945       {
07946          /* Unmute conference */
07947          dahdi_confmute(p, 0);
07948          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07949          p->subs[idx].f.subclass.integer = res & 0xff;
07950          dahdi_handle_dtmf(ast, idx, &f);
07951       }
07952       return f;
07953    }
07954 
07955    if (res & DAHDI_EVENT_DTMFDOWN) {
07956       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07957 #if defined(HAVE_PRI)
07958       if (dahdi_sig_pri_lib_handles(p->sig)
07959          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07960          && p->pri
07961          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07962          /* absorb event */
07963       } else
07964 #endif   /* defined(HAVE_PRI) */
07965       {
07966          /* Mute conference */
07967          dahdi_confmute(p, 1);
07968          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07969          p->subs[idx].f.subclass.integer = res & 0xff;
07970          dahdi_handle_dtmf(ast, idx, &f);
07971       }
07972       return &p->subs[idx].f;
07973    }
07974 
07975    switch (res) {
07976    case DAHDI_EVENT_EC_DISABLED:
07977       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07978       p->echocanon = 0;
07979       break;
07980 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07981    case DAHDI_EVENT_TX_CED_DETECTED:
07982       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07983       break;
07984    case DAHDI_EVENT_RX_CED_DETECTED:
07985       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07986       break;
07987    case DAHDI_EVENT_EC_NLP_DISABLED:
07988       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07989       break;
07990    case DAHDI_EVENT_EC_NLP_ENABLED:
07991       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07992       break;
07993 #endif
07994    case DAHDI_EVENT_BITSCHANGED:
07995 #ifdef HAVE_OPENR2
07996       if (p->sig != SIG_MFCR2) {
07997          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07998       } else {
07999          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
08000          openr2_chan_handle_cas(p->r2chan);
08001       }
08002 #else
08003       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08004 #endif
08005       break;
08006    case DAHDI_EVENT_PULSE_START:
08007       /* Stop tone if there's a pulse start and the PBX isn't started */
08008       if (!ast->pbx)
08009          tone_zone_play_tone(p->subs[idx].dfd, -1);
08010       break;
08011    case DAHDI_EVENT_DIALCOMPLETE:
08012       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08013 #if defined(HAVE_PRI)
08014       if (dahdi_sig_pri_lib_handles(p->sig)) {
08015          if (p->inalarm) {
08016             break;
08017          }
08018          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08019             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08020                strerror(errno));
08021             return NULL;
08022          }
08023          if (x) {
08024             /* Still dialing in DAHDI driver */
08025             break;
08026          }
08027          /*
08028           * The ast channel is locked and the private may be locked more
08029           * than once.
08030           */
08031          sig_pri_dial_complete(p->sig_pvt, ast);
08032          break;
08033       }
08034 #endif   /* defined(HAVE_PRI) */
08035 #ifdef HAVE_OPENR2
08036       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08037          /* we don't need to do anything for this event for R2 signaling
08038             if the call is being setup */
08039          break;
08040       }
08041 #endif
08042       if (p->inalarm) break;
08043       if ((p->radio || (p->oprmode < 0))) break;
08044       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08045          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08046          return NULL;
08047       }
08048       if (!x) { /* if not still dialing in driver */
08049          dahdi_enable_ec(p);
08050          if (p->echobreak) {
08051             dahdi_train_ec(p);
08052             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08053             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08054             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08055             p->echobreak = 0;
08056          } else {
08057             p->dialing = 0;
08058             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08059                /* if thru with dialing after offhook */
08060                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08061                   ast_setstate(ast, AST_STATE_UP);
08062                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064                   break;
08065                } else { /* if to state wait for offhook to dial rest */
08066                   /* we now wait for off hook */
08067                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08068                }
08069             }
08070             if (ast->_state == AST_STATE_DIALING) {
08071                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08072                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08073                } else if (p->confirmanswer || (!p->dialednone
08074                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08075                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08076                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08077                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08078                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08079                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08080                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08081                      || (mysig == SIG_SF_FEATB)))) {
08082                   ast_setstate(ast, AST_STATE_RINGING);
08083                } else if (!p->answeronpolarityswitch) {
08084                   ast_setstate(ast, AST_STATE_UP);
08085                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08086                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08087                   /* If aops=0 and hops=1, this is necessary */
08088                   p->polarity = POLARITY_REV;
08089                } else {
08090                   /* Start clean, so we can catch the change to REV polarity when party answers */
08091                   p->polarity = POLARITY_IDLE;
08092                }
08093             }
08094          }
08095       }
08096       break;
08097    case DAHDI_EVENT_ALARM:
08098       switch (p->sig) {
08099 #if defined(HAVE_PRI)
08100       case SIG_PRI_LIB_HANDLE_CASES:
08101          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08102          break;
08103 #endif   /* defined(HAVE_PRI) */
08104 #if defined(HAVE_SS7)
08105       case SIG_SS7:
08106          sig_ss7_set_alarm(p->sig_pvt, 1);
08107          break;
08108 #endif   /* defined(HAVE_SS7) */
08109       default:
08110          p->inalarm = 1;
08111          break;
08112       }
08113       res = get_alarms(p);
08114       handle_alarms(p, res);
08115 #ifdef HAVE_PRI
08116       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08117          /* fall through intentionally */
08118       } else {
08119          break;
08120       }
08121 #endif
08122 #if defined(HAVE_SS7)
08123       if (p->sig == SIG_SS7)
08124          break;
08125 #endif   /* defined(HAVE_SS7) */
08126 #ifdef HAVE_OPENR2
08127       if (p->sig == SIG_MFCR2)
08128          break;
08129 #endif
08130    case DAHDI_EVENT_ONHOOK:
08131       if (p->radio) {
08132          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08134          break;
08135       }
08136       if (p->oprmode < 0)
08137       {
08138          if (p->oprmode != -1) break;
08139          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08140          {
08141             /* Make sure it starts ringing */
08142             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08143             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08144             save_conference(p->oprpeer);
08145             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08146          }
08147          break;
08148       }
08149       switch (p->sig) {
08150       case SIG_FXOLS:
08151       case SIG_FXOGS:
08152       case SIG_FXOKS:
08153          /* Check for some special conditions regarding call waiting */
08154          if (idx == SUB_REAL) {
08155             /* The normal line was hung up */
08156             if (p->subs[SUB_CALLWAIT].owner) {
08157                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08158                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08159                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08160                unalloc_sub(p, SUB_CALLWAIT);
08161 #if 0
08162                p->subs[idx].needanswer = 0;
08163                p->subs[idx].needringing = 0;
08164 #endif
08165                p->callwaitingrepeat = 0;
08166                p->cidcwexpire = 0;
08167                p->cid_suppress_expire = 0;
08168                p->owner = NULL;
08169                /* Don't start streaming audio yet if the incoming call isn't up yet */
08170                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08171                   p->dialing = 1;
08172                dahdi_ring_phone(p);
08173             } else if (p->subs[SUB_THREEWAY].owner) {
08174                unsigned int mssinceflash;
08175                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08176                   the private structure -- not especially easy or clean */
08177                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08178                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08179                   DLA_UNLOCK(&p->lock);
08180                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08181                   /* We can grab ast and p in that order, without worry.  We should make sure
08182                      nothing seriously bad has happened though like some sort of bizarre double
08183                      masquerade! */
08184                   DLA_LOCK(&p->lock);
08185                   if (p->owner != ast) {
08186                      ast_log(LOG_WARNING, "This isn't good...\n");
08187                      return NULL;
08188                   }
08189                }
08190                if (!p->subs[SUB_THREEWAY].owner) {
08191                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08192                   return NULL;
08193                }
08194                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08195                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08196                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08197                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08198                      hanging up.  Hangup both channels now */
08199                   if (p->subs[SUB_THREEWAY].owner)
08200                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08201                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08202                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08203                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08204                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08205                   if (p->transfer) {
08206                      /* In any case this isn't a threeway call anymore */
08207                      p->subs[SUB_REAL].inthreeway = 0;
08208                      p->subs[SUB_THREEWAY].inthreeway = 0;
08209                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08210                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08211                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08212                         /* Swap subs and dis-own channel */
08213                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08214                         p->owner = NULL;
08215                         /* Ring the phone */
08216                         dahdi_ring_phone(p);
08217                      } else {
08218                         if ((res = attempt_transfer(p)) < 0) {
08219                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08220                            if (p->subs[SUB_THREEWAY].owner)
08221                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222                         } else if (res) {
08223                            /* Don't actually hang up at this point */
08224                            if (p->subs[SUB_THREEWAY].owner)
08225                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08226                            break;
08227                         }
08228                      }
08229                   } else {
08230                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08231                      if (p->subs[SUB_THREEWAY].owner)
08232                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233                   }
08234                } else {
08235                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08236                   /* Swap subs and dis-own channel */
08237                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08238                   p->owner = NULL;
08239                   /* Ring the phone */
08240                   dahdi_ring_phone(p);
08241                }
08242             }
08243          } else {
08244             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08245          }
08246          /* Fall through */
08247       default:
08248          dahdi_disable_ec(p);
08249          return NULL;
08250       }
08251       break;
08252    case DAHDI_EVENT_RINGOFFHOOK:
08253       if (p->inalarm) break;
08254       if (p->oprmode < 0)
08255       {
08256          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08257          {
08258             /* Make sure it stops ringing */
08259             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08260             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08261             restore_conference(p->oprpeer);
08262          }
08263          break;
08264       }
08265       if (p->radio)
08266       {
08267          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08268          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08269          break;
08270       }
08271       /* for E911, its supposed to wait for offhook then dial
08272          the second half of the dial string */
08273       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08274          c = strchr(p->dialdest, '/');
08275          if (c)
08276             c++;
08277          else
08278             c = p->dialdest;
08279          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08280          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08281          if (strlen(p->dop.dialstr) > 4) {
08282             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08283             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08284             p->echorest[sizeof(p->echorest) - 1] = '\0';
08285             p->echobreak = 1;
08286             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08287          } else
08288             p->echobreak = 0;
08289          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08290             int saveerr = errno;
08291 
08292             x = DAHDI_ONHOOK;
08293             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08294             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08295             return NULL;
08296             }
08297          p->dialing = 1;
08298          return &p->subs[idx].f;
08299       }
08300       switch (p->sig) {
08301       case SIG_FXOLS:
08302       case SIG_FXOGS:
08303       case SIG_FXOKS:
08304          switch (ast->_state) {
08305          case AST_STATE_RINGING:
08306             dahdi_enable_ec(p);
08307             dahdi_train_ec(p);
08308             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08309             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08310             /* Make sure it stops ringing */
08311             p->subs[SUB_REAL].needringing = 0;
08312             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08313             ast_debug(1, "channel %d answered\n", p->channel);
08314 
08315             /* Cancel any running CallerID spill */
08316             ast_free(p->cidspill);
08317             p->cidspill = NULL;
08318             restore_conference(p);
08319 
08320             p->dialing = 0;
08321             p->callwaitcas = 0;
08322             if (p->confirmanswer) {
08323                /* Ignore answer if "confirm answer" is enabled */
08324                p->subs[idx].f.frametype = AST_FRAME_NULL;
08325                p->subs[idx].f.subclass.integer = 0;
08326             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08327                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08328                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08329                if (res < 0) {
08330                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08331                   p->dop.dialstr[0] = '\0';
08332                   return NULL;
08333                } else {
08334                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08335                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08336                   p->subs[idx].f.subclass.integer = 0;
08337                   p->dialing = 1;
08338                }
08339                p->dop.dialstr[0] = '\0';
08340                ast_setstate(ast, AST_STATE_DIALING);
08341             } else
08342                ast_setstate(ast, AST_STATE_UP);
08343             return &p->subs[idx].f;
08344          case AST_STATE_DOWN:
08345             ast_setstate(ast, AST_STATE_RING);
08346             ast->rings = 1;
08347             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08348             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08349             ast_debug(1, "channel %d picked up\n", p->channel);
08350             return &p->subs[idx].f;
08351          case AST_STATE_UP:
08352             /* Make sure it stops ringing */
08353             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08354             /* Okay -- probably call waiting*/
08355             if (ast_bridged_channel(p->owner))
08356                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08357             p->subs[idx].needunhold = 1;
08358             break;
08359          case AST_STATE_RESERVED:
08360             /* Start up dialtone */
08361             if (has_voicemail(p))
08362                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08363             else
08364                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08365             break;
08366          default:
08367             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08368          }
08369          break;
08370       case SIG_FXSLS:
08371       case SIG_FXSGS:
08372       case SIG_FXSKS:
08373          if (ast->_state == AST_STATE_RING) {
08374             p->ringt = p->ringt_base;
08375          }
08376 
08377          /* If we get a ring then we cannot be in
08378           * reversed polarity. So we reset to idle */
08379          ast_debug(1, "Setting IDLE polarity due "
08380             "to ring. Old polarity was %d\n",
08381             p->polarity);
08382          p->polarity = POLARITY_IDLE;
08383 
08384          /* Fall through */
08385       case SIG_EM:
08386       case SIG_EM_E1:
08387       case SIG_EMWINK:
08388       case SIG_FEATD:
08389       case SIG_FEATDMF:
08390       case SIG_FEATDMF_TA:
08391       case SIG_E911:
08392       case SIG_FGC_CAMA:
08393       case SIG_FGC_CAMAMF:
08394       case SIG_FEATB:
08395       case SIG_SF:
08396       case SIG_SFWINK:
08397       case SIG_SF_FEATD:
08398       case SIG_SF_FEATDMF:
08399       case SIG_SF_FEATB:
08400          if (ast->_state == AST_STATE_PRERING)
08401             ast_setstate(ast, AST_STATE_RING);
08402          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08403             ast_debug(1, "Ring detected\n");
08404             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08405             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08406          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08407             ast_debug(1, "Line answered\n");
08408             if (p->confirmanswer) {
08409                p->subs[idx].f.frametype = AST_FRAME_NULL;
08410                p->subs[idx].f.subclass.integer = 0;
08411             } else {
08412                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08413                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08414                ast_setstate(ast, AST_STATE_UP);
08415             }
08416          } else if (ast->_state != AST_STATE_RING)
08417             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08418          break;
08419       default:
08420          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08421       }
08422       break;
08423    case DAHDI_EVENT_RINGBEGIN:
08424       switch (p->sig) {
08425       case SIG_FXSLS:
08426       case SIG_FXSGS:
08427       case SIG_FXSKS:
08428          if (ast->_state == AST_STATE_RING) {
08429             p->ringt = p->ringt_base;
08430          }
08431          break;
08432       }
08433       break;
08434    case DAHDI_EVENT_RINGERON:
08435       break;
08436    case DAHDI_EVENT_NOALARM:
08437       switch (p->sig) {
08438 #if defined(HAVE_PRI)
08439       case SIG_PRI_LIB_HANDLE_CASES:
08440          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08441          break;
08442 #endif   /* defined(HAVE_PRI) */
08443 #if defined(HAVE_SS7)
08444       case SIG_SS7:
08445          sig_ss7_set_alarm(p->sig_pvt, 0);
08446          break;
08447 #endif   /* defined(HAVE_SS7) */
08448       default:
08449          p->inalarm = 0;
08450          break;
08451       }
08452       handle_clear_alarms(p);
08453       break;
08454    case DAHDI_EVENT_WINKFLASH:
08455       if (p->inalarm) break;
08456       if (p->radio) break;
08457       if (p->oprmode < 0) break;
08458       if (p->oprmode > 1)
08459       {
08460          struct dahdi_params par;
08461 
08462          memset(&par, 0, sizeof(par));
08463          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08464          {
08465             if (!par.rxisoffhook)
08466             {
08467                /* Make sure it stops ringing */
08468                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08469                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08470                save_conference(p);
08471                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08472             }
08473          }
08474          break;
08475       }
08476       /* Remember last time we got a flash-hook */
08477       p->flashtime = ast_tvnow();
08478       switch (mysig) {
08479       case SIG_FXOLS:
08480       case SIG_FXOGS:
08481       case SIG_FXOKS:
08482          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08483             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08484 
08485          /* Cancel any running CallerID spill */
08486          ast_free(p->cidspill);
08487          p->cidspill = NULL;
08488          restore_conference(p);
08489          p->callwaitcas = 0;
08490 
08491          if (idx != SUB_REAL) {
08492             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08493             goto winkflashdone;
08494          }
08495 
08496          if (p->subs[SUB_CALLWAIT].owner) {
08497             /* Swap to call-wait */
08498             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08499             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08500             p->owner = p->subs[SUB_REAL].owner;
08501             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08502             if (p->owner->_state == AST_STATE_RINGING) {
08503                ast_setstate(p->owner, AST_STATE_UP);
08504                p->subs[SUB_REAL].needanswer = 1;
08505             }
08506             p->callwaitingrepeat = 0;
08507             p->cidcwexpire = 0;
08508             p->cid_suppress_expire = 0;
08509             /* Start music on hold if appropriate */
08510             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08511                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08512                   S_OR(p->mohsuggest, NULL),
08513                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08514             }
08515             p->subs[SUB_CALLWAIT].needhold = 1;
08516             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08517                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08518                   S_OR(p->mohsuggest, NULL),
08519                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08520             }
08521             p->subs[SUB_REAL].needunhold = 1;
08522          } else if (!p->subs[SUB_THREEWAY].owner) {
08523             if (!p->threewaycalling) {
08524                /* Just send a flash if no 3-way calling */
08525                p->subs[SUB_REAL].needflash = 1;
08526                goto winkflashdone;
08527             } else if (!check_for_conference(p)) {
08528                char cid_num[256];
08529                char cid_name[256];
08530 
08531                cid_num[0] = 0;
08532                cid_name[0] = 0;
08533                if (p->dahditrcallerid && p->owner) {
08534                   if (p->owner->caller.id.number.valid
08535                      && p->owner->caller.id.number.str) {
08536                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08537                         sizeof(cid_num));
08538                   }
08539                   if (p->owner->caller.id.name.valid
08540                      && p->owner->caller.id.name.str) {
08541                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08542                         sizeof(cid_name));
08543                   }
08544                }
08545                /* XXX This section needs much more error checking!!! XXX */
08546                /* Start a 3-way call if feasible */
08547                if (!((ast->pbx) ||
08548                   (ast->_state == AST_STATE_UP) ||
08549                   (ast->_state == AST_STATE_RING))) {
08550                   ast_debug(1, "Flash when call not up or ringing\n");
08551                   goto winkflashdone;
08552                }
08553                if (alloc_sub(p, SUB_THREEWAY)) {
08554                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08555                   goto winkflashdone;
08556                }
08557 
08558                /*
08559                 * Make new channel
08560                 *
08561                 * We cannot hold the p or ast locks while creating a new
08562                 * channel.
08563                 */
08564                ast_mutex_unlock(&p->lock);
08565                ast_channel_unlock(ast);
08566                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08567                ast_channel_lock(ast);
08568                ast_mutex_lock(&p->lock);
08569                if (p->dahditrcallerid) {
08570                   if (!p->origcid_num)
08571                      p->origcid_num = ast_strdup(p->cid_num);
08572                   if (!p->origcid_name)
08573                      p->origcid_name = ast_strdup(p->cid_name);
08574                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08575                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08576                }
08577                /* Swap things around between the three-way and real call */
08578                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08579                /* Disable echo canceller for better dialing */
08580                dahdi_disable_ec(p);
08581                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08582                if (res)
08583                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08584                p->owner = chan;
08585                if (!chan) {
08586                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08587                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08588                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08589                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08590                   dahdi_enable_ec(p);
08591                   ast_hangup(chan);
08592                } else {
08593                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08594 
08595                   /* Start music on hold if appropriate */
08596                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08597                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08598                         S_OR(p->mohsuggest, NULL),
08599                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08600                   }
08601                   p->subs[SUB_THREEWAY].needhold = 1;
08602                }
08603             }
08604          } else {
08605             /* Already have a 3 way call */
08606             if (p->subs[SUB_THREEWAY].inthreeway) {
08607                /* Call is already up, drop the last person */
08608                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08609                /* If the primary call isn't answered yet, use it */
08610                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08611                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08612                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08613                   p->owner = p->subs[SUB_REAL].owner;
08614                }
08615                /* Drop the last call and stop the conference */
08616                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08617                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08618                p->subs[SUB_REAL].inthreeway = 0;
08619                p->subs[SUB_THREEWAY].inthreeway = 0;
08620             } else {
08621                /* Lets see what we're up to */
08622                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08623                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08624                   int otherindex = SUB_THREEWAY;
08625 
08626                   ast_verb(3, "Building conference call with %s and %s\n",
08627                      p->subs[SUB_THREEWAY].owner->name,
08628                      p->subs[SUB_REAL].owner->name);
08629                   /* Put them in the threeway, and flip */
08630                   p->subs[SUB_THREEWAY].inthreeway = 1;
08631                   p->subs[SUB_REAL].inthreeway = 1;
08632                   if (ast->_state == AST_STATE_UP) {
08633                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08634                      otherindex = SUB_REAL;
08635                   }
08636                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08637                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08638                   p->subs[otherindex].needunhold = 1;
08639                   p->owner = p->subs[SUB_REAL].owner;
08640                } else {
08641                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08642                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08643                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08644                   p->owner = p->subs[SUB_REAL].owner;
08645                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08646                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08647                   p->subs[SUB_REAL].needunhold = 1;
08648                   dahdi_enable_ec(p);
08649                }
08650             }
08651          }
08652 winkflashdone:
08653          update_conf(p);
08654          break;
08655       case SIG_EM:
08656       case SIG_EM_E1:
08657       case SIG_FEATD:
08658       case SIG_SF:
08659       case SIG_SFWINK:
08660       case SIG_SF_FEATD:
08661       case SIG_FXSLS:
08662       case SIG_FXSGS:
08663          if (p->dialing)
08664             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08665          else
08666             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08667          break;
08668       case SIG_FEATDMF_TA:
08669          switch (p->whichwink) {
08670          case 0:
08671             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08672                S_COR(p->owner->caller.ani.number.valid,
08673                   p->owner->caller.ani.number.str, ""));
08674             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08675                p->owner->caller.ani2,
08676                S_COR(p->owner->caller.ani.number.valid,
08677                   p->owner->caller.ani.number.str, ""));
08678             break;
08679          case 1:
08680             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08681             break;
08682          case 2:
08683             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08684             return NULL;
08685          }
08686          p->whichwink++;
08687          /* Fall through */
08688       case SIG_FEATDMF:
08689       case SIG_E911:
08690       case SIG_FGC_CAMAMF:
08691       case SIG_FGC_CAMA:
08692       case SIG_FEATB:
08693       case SIG_SF_FEATDMF:
08694       case SIG_SF_FEATB:
08695       case SIG_EMWINK:
08696          /* FGD MF and EMWINK *Must* wait for wink */
08697          if (!ast_strlen_zero(p->dop.dialstr)) {
08698             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08699             if (res < 0) {
08700                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08701                p->dop.dialstr[0] = '\0';
08702                return NULL;
08703             } else
08704                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08705          }
08706          p->dop.dialstr[0] = '\0';
08707          break;
08708       default:
08709          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08710       }
08711       break;
08712    case DAHDI_EVENT_HOOKCOMPLETE:
08713       if (p->inalarm) break;
08714       if ((p->radio || (p->oprmode < 0))) break;
08715       if (p->waitingfordt.tv_sec) break;
08716       switch (mysig) {
08717       case SIG_FXSLS:  /* only interesting for FXS */
08718       case SIG_FXSGS:
08719       case SIG_FXSKS:
08720       case SIG_EM:
08721       case SIG_EM_E1:
08722       case SIG_EMWINK:
08723       case SIG_FEATD:
08724       case SIG_SF:
08725       case SIG_SFWINK:
08726       case SIG_SF_FEATD:
08727          if (!ast_strlen_zero(p->dop.dialstr)) {
08728             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08729             if (res < 0) {
08730                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08731                p->dop.dialstr[0] = '\0';
08732                return NULL;
08733             } else
08734                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08735          }
08736          p->dop.dialstr[0] = '\0';
08737          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08738          break;
08739       case SIG_FEATDMF:
08740       case SIG_FEATDMF_TA:
08741       case SIG_E911:
08742       case SIG_FGC_CAMA:
08743       case SIG_FGC_CAMAMF:
08744       case SIG_FEATB:
08745       case SIG_SF_FEATDMF:
08746       case SIG_SF_FEATB:
08747          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08748          break;
08749       default:
08750          break;
08751       }
08752       break;
08753    case DAHDI_EVENT_POLARITY:
08754       /*
08755        * If we get a Polarity Switch event, check to see
08756        * if we should change the polarity state and
08757        * mark the channel as UP or if this is an indication
08758        * of remote end disconnect.
08759        */
08760       if (p->polarity == POLARITY_IDLE) {
08761          p->polarity = POLARITY_REV;
08762          if (p->answeronpolarityswitch &&
08763             ((ast->_state == AST_STATE_DIALING) ||
08764             (ast->_state == AST_STATE_RINGING))) {
08765             ast_debug(1, "Answering on polarity switch!\n");
08766             ast_setstate(p->owner, AST_STATE_UP);
08767             if (p->hanguponpolarityswitch) {
08768                p->polaritydelaytv = ast_tvnow();
08769             }
08770          } else
08771             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08772       }
08773       /* Removed else statement from here as it was preventing hangups from ever happening*/
08774       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08775       if (p->hanguponpolarityswitch &&
08776          (p->polarityonanswerdelay > 0) &&
08777          (p->polarity == POLARITY_REV) &&
08778          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08779          /* Added log_debug information below to provide a better indication of what is going on */
08780          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) );
08781 
08782          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08783             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08784             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08785             p->polarity = POLARITY_IDLE;
08786          } else
08787             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);
08788 
08789       } else {
08790          p->polarity = POLARITY_IDLE;
08791          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08792       }
08793       /* Added more log_debug information below to provide a better indication of what is going on */
08794       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) );
08795       break;
08796    default:
08797       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08798    }
08799    return &p->subs[idx].f;
08800 }
08801 
08802 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08803 {
08804    int res;
08805    int idx;
08806    struct ast_frame *f;
08807    int usedindex = -1;
08808    struct dahdi_pvt *p = ast->tech_pvt;
08809 
08810    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08811       idx = SUB_REAL;
08812    }
08813 
08814    p->subs[idx].f.frametype = AST_FRAME_NULL;
08815    p->subs[idx].f.datalen = 0;
08816    p->subs[idx].f.samples = 0;
08817    p->subs[idx].f.mallocd = 0;
08818    p->subs[idx].f.offset = 0;
08819    p->subs[idx].f.subclass.integer = 0;
08820    p->subs[idx].f.delivery = ast_tv(0,0);
08821    p->subs[idx].f.src = "dahdi_exception";
08822    p->subs[idx].f.data.ptr = NULL;
08823 
08824 
08825    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08826       /* If nobody owns us, absorb the event appropriately, otherwise
08827          we loop indefinitely.  This occurs when, during call waiting, the
08828          other end hangs up our channel so that it no longer exists, but we
08829          have neither FLASH'd nor ONHOOK'd to signify our desire to
08830          change to the other channel. */
08831       if (p->fake_event) {
08832          res = p->fake_event;
08833          p->fake_event = 0;
08834       } else
08835          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08836       /* Switch to real if there is one and this isn't something really silly... */
08837       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08838          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08839          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08840          p->owner = p->subs[SUB_REAL].owner;
08841          if (p->owner && ast_bridged_channel(p->owner))
08842             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08843          p->subs[SUB_REAL].needunhold = 1;
08844       }
08845       switch (res) {
08846       case DAHDI_EVENT_ONHOOK:
08847          dahdi_disable_ec(p);
08848          if (p->owner) {
08849             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08850             dahdi_ring_phone(p);
08851             p->callwaitingrepeat = 0;
08852             p->cidcwexpire = 0;
08853             p->cid_suppress_expire = 0;
08854          } else
08855             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08856          update_conf(p);
08857          break;
08858       case DAHDI_EVENT_RINGOFFHOOK:
08859          dahdi_enable_ec(p);
08860          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08861          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08862             p->subs[SUB_REAL].needanswer = 1;
08863             p->dialing = 0;
08864          }
08865          break;
08866       case DAHDI_EVENT_HOOKCOMPLETE:
08867       case DAHDI_EVENT_RINGERON:
08868       case DAHDI_EVENT_RINGEROFF:
08869          /* Do nothing */
08870          break;
08871       case DAHDI_EVENT_WINKFLASH:
08872          p->flashtime = ast_tvnow();
08873          if (p->owner) {
08874             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08875             if (p->owner->_state != AST_STATE_UP) {
08876                /* Answer if necessary */
08877                usedindex = dahdi_get_index(p->owner, p, 0);
08878                if (usedindex > -1) {
08879                   p->subs[usedindex].needanswer = 1;
08880                }
08881                ast_setstate(p->owner, AST_STATE_UP);
08882             }
08883             p->callwaitingrepeat = 0;
08884             p->cidcwexpire = 0;
08885             p->cid_suppress_expire = 0;
08886             if (ast_bridged_channel(p->owner))
08887                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08888             p->subs[SUB_REAL].needunhold = 1;
08889          } else
08890             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08891          update_conf(p);
08892          break;
08893       default:
08894          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08895       }
08896       f = &p->subs[idx].f;
08897       return f;
08898    }
08899    if (!(p->radio || (p->oprmode < 0)))
08900       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08901    /* If it's not us, return NULL immediately */
08902    if (ast != p->owner) {
08903       if (p->owner) {
08904          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08905       }
08906       f = &p->subs[idx].f;
08907       return f;
08908    }
08909 
08910    f = dahdi_handle_event(ast);
08911    if (!f) {
08912       const char *name = ast_strdupa(ast->name);
08913 
08914       /* Tell the CDR this DAHDI device hung up */
08915       ast_mutex_unlock(&p->lock);
08916       ast_channel_unlock(ast);
08917       ast_set_hangupsource(ast, name, 0);
08918       ast_channel_lock(ast);
08919       ast_mutex_lock(&p->lock);
08920    }
08921    return f;
08922 }
08923 
08924 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08925 {
08926    struct dahdi_pvt *p = ast->tech_pvt;
08927    struct ast_frame *f;
08928    ast_mutex_lock(&p->lock);
08929    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08930       struct analog_pvt *analog_p = p->sig_pvt;
08931       f = analog_exception(analog_p, ast);
08932    } else {
08933       f = __dahdi_exception(ast);
08934    }
08935    ast_mutex_unlock(&p->lock);
08936    return f;
08937 }
08938 
08939 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08940 {
08941    struct dahdi_pvt *p;
08942    int res;
08943    int idx;
08944    void *readbuf;
08945    struct ast_frame *f;
08946 
08947    /*
08948     * For analog channels, we must do deadlock avoidance because
08949     * analog ports can have more than one Asterisk channel using
08950     * the same private structure.
08951     */
08952    p = ast->tech_pvt;
08953    while (ast_mutex_trylock(&p->lock)) {
08954       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08955 
08956       /*
08957        * Check to see if the channel is still associated with the same
08958        * private structure.  While the Asterisk channel was unlocked
08959        * the following events may have occured:
08960        *
08961        * 1) A masquerade may have associated the channel with another
08962        * technology or private structure.
08963        *
08964        * 2) For PRI calls, call signaling could change the channel
08965        * association to another B channel (private structure).
08966        */
08967       if (ast->tech_pvt != p) {
08968          /* The channel is no longer associated.  Quit gracefully. */
08969          return &ast_null_frame;
08970       }
08971    }
08972 
08973    idx = dahdi_get_index(ast, p, 0);
08974 
08975    /* Hang up if we don't really exist */
08976    if (idx < 0)   {
08977       ast_log(LOG_WARNING, "We don't exist?\n");
08978       ast_mutex_unlock(&p->lock);
08979       return NULL;
08980    }
08981 
08982    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08983       ast_mutex_unlock(&p->lock);
08984       return NULL;
08985    }
08986 
08987    p->subs[idx].f.frametype = AST_FRAME_NULL;
08988    p->subs[idx].f.datalen = 0;
08989    p->subs[idx].f.samples = 0;
08990    p->subs[idx].f.mallocd = 0;
08991    p->subs[idx].f.offset = 0;
08992    p->subs[idx].f.subclass.integer = 0;
08993    p->subs[idx].f.delivery = ast_tv(0,0);
08994    p->subs[idx].f.src = "dahdi_read";
08995    p->subs[idx].f.data.ptr = NULL;
08996 
08997    /* make sure it sends initial key state as first frame */
08998    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08999    {
09000       struct dahdi_params ps;
09001 
09002       memset(&ps, 0, sizeof(ps));
09003       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09004          ast_mutex_unlock(&p->lock);
09005          return NULL;
09006       }
09007       p->firstradio = 1;
09008       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09009       if (ps.rxisoffhook)
09010       {
09011          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09012       }
09013       else
09014       {
09015          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09016       }
09017       ast_mutex_unlock(&p->lock);
09018       return &p->subs[idx].f;
09019    }
09020    if (p->ringt > 0) {
09021       if (!(--p->ringt)) {
09022          ast_mutex_unlock(&p->lock);
09023          return NULL;
09024       }
09025    }
09026 
09027 #ifdef HAVE_OPENR2
09028    if (p->mfcr2) {
09029       openr2_chan_process_event(p->r2chan);
09030       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09031          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09032          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09033           * now enqueue a progress frame to bridge the media up */
09034          if (p->mfcr2_call_accepted &&
09035              !p->mfcr2_progress && 
09036              ast->_state == AST_STATE_RINGING) {
09037             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09038             ast_queue_frame(p->owner, &f);
09039             p->mfcr2_progress = 1;
09040          }
09041       }
09042    }
09043 #endif
09044 
09045    if (p->subs[idx].needringing) {
09046       /* Send ringing frame if requested */
09047       p->subs[idx].needringing = 0;
09048       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09049       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09050       ast_setstate(ast, AST_STATE_RINGING);
09051       ast_mutex_unlock(&p->lock);
09052       return &p->subs[idx].f;
09053    }
09054 
09055    if (p->subs[idx].needbusy) {
09056       /* Send busy frame if requested */
09057       p->subs[idx].needbusy = 0;
09058       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09059       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09060       ast_mutex_unlock(&p->lock);
09061       return &p->subs[idx].f;
09062    }
09063 
09064    if (p->subs[idx].needcongestion) {
09065       /* Send congestion frame if requested */
09066       p->subs[idx].needcongestion = 0;
09067       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09069       ast_mutex_unlock(&p->lock);
09070       return &p->subs[idx].f;
09071    }
09072 
09073    if (p->subs[idx].needanswer) {
09074       /* Send answer frame if requested */
09075       p->subs[idx].needanswer = 0;
09076       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09077       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09078       ast_mutex_unlock(&p->lock);
09079       return &p->subs[idx].f;
09080    }
09081 #ifdef HAVE_OPENR2
09082    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09083       /* openr2 took care of reading and handling any event
09084         (needanswer, needbusy etc), if we continue we will read()
09085         twice, lets just return a null frame. This should only
09086         happen when openr2 is dialing out */
09087       ast_mutex_unlock(&p->lock);
09088       return &ast_null_frame;
09089    }
09090 #endif
09091 
09092    if (p->subs[idx].needflash) {
09093       /* Send answer frame if requested */
09094       p->subs[idx].needflash = 0;
09095       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09096       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09097       ast_mutex_unlock(&p->lock);
09098       return &p->subs[idx].f;
09099    }
09100 
09101    if (p->subs[idx].needhold) {
09102       /* Send answer frame if requested */
09103       p->subs[idx].needhold = 0;
09104       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09105       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09106       ast_mutex_unlock(&p->lock);
09107       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09108       return &p->subs[idx].f;
09109    }
09110 
09111    if (p->subs[idx].needunhold) {
09112       /* Send answer frame if requested */
09113       p->subs[idx].needunhold = 0;
09114       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09115       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09116       ast_mutex_unlock(&p->lock);
09117       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09118       return &p->subs[idx].f;
09119    }
09120 
09121    /*
09122     * If we have a fake_event, fake an exception to handle it only
09123     * if this channel owns the private.
09124     */
09125    if (p->fake_event && p->owner == ast) {
09126       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09127          struct analog_pvt *analog_p = p->sig_pvt;
09128 
09129          f = analog_exception(analog_p, ast);
09130       } else {
09131          f = __dahdi_exception(ast);
09132       }
09133       ast_mutex_unlock(&p->lock);
09134       return f;
09135    }
09136 
09137    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09138       if (!p->subs[idx].linear) {
09139          p->subs[idx].linear = 1;
09140          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09141          if (res)
09142             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09143       }
09144    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09145       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09146       if (p->subs[idx].linear) {
09147          p->subs[idx].linear = 0;
09148          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09149          if (res)
09150             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09151       }
09152    } else {
09153       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09154       ast_mutex_unlock(&p->lock);
09155       return NULL;
09156    }
09157    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09158    CHECK_BLOCKING(ast);
09159    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09160    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09161    /* Check for hangup */
09162    if (res < 0) {
09163       f = NULL;
09164       if (res == -1) {
09165          if (errno == EAGAIN) {
09166             /* Return "NULL" frame if there is nobody there */
09167             ast_mutex_unlock(&p->lock);
09168             return &p->subs[idx].f;
09169          } else if (errno == ELAST) {
09170             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09171                struct analog_pvt *analog_p = p->sig_pvt;
09172                f = analog_exception(analog_p, ast);
09173             } else {
09174                f = __dahdi_exception(ast);
09175             }
09176          } else
09177             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09178       }
09179       ast_mutex_unlock(&p->lock);
09180       return f;
09181    }
09182    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09183       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09184       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09185          struct analog_pvt *analog_p = p->sig_pvt;
09186          f = analog_exception(analog_p, ast);
09187       } else {
09188          f = __dahdi_exception(ast);
09189       }
09190       ast_mutex_unlock(&p->lock);
09191       return f;
09192    }
09193    if (p->tdd) { /* if in TDD mode, see if we receive that */
09194       int c;
09195 
09196       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09197       if (c < 0) {
09198          ast_debug(1,"tdd_feed failed\n");
09199          ast_mutex_unlock(&p->lock);
09200          return NULL;
09201       }
09202       if (c) { /* if a char to return */
09203          p->subs[idx].f.subclass.integer = 0;
09204          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09205          p->subs[idx].f.mallocd = 0;
09206          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09207          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09208          p->subs[idx].f.datalen = 1;
09209          *((char *) p->subs[idx].f.data.ptr) = c;
09210          ast_mutex_unlock(&p->lock);
09211          return &p->subs[idx].f;
09212       }
09213    }
09214    if (idx == SUB_REAL) {
09215       /* Ensure the CW timers decrement only on a single subchannel */
09216       if (p->cidcwexpire) {
09217          if (!--p->cidcwexpire) {
09218             /* Expired CID/CW */
09219             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09220             restore_conference(p);
09221          }
09222       }
09223       if (p->cid_suppress_expire) {
09224          --p->cid_suppress_expire;
09225       }
09226       if (p->callwaitingrepeat) {
09227          if (!--p->callwaitingrepeat) {
09228             /* Expired, Repeat callwaiting tone */
09229             ++p->callwaitrings;
09230             dahdi_callwait(ast);
09231          }
09232       }
09233    }
09234    if (p->subs[idx].linear) {
09235       p->subs[idx].f.datalen = READ_SIZE * 2;
09236    } else
09237       p->subs[idx].f.datalen = READ_SIZE;
09238 
09239    /* Handle CallerID Transmission */
09240    if ((p->owner == ast) && p->cidspill) {
09241       send_callerid(p);
09242    }
09243 
09244    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09245    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09246    p->subs[idx].f.samples = READ_SIZE;
09247    p->subs[idx].f.mallocd = 0;
09248    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09249    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09250 #if 0
09251    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09252 #endif
09253    if (p->dialing ||  p->radio || /* Transmitting something */
09254       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09255       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09256       ) {
09257       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09258          don't send anything */
09259       p->subs[idx].f.frametype = AST_FRAME_NULL;
09260       p->subs[idx].f.subclass.integer = 0;
09261       p->subs[idx].f.samples = 0;
09262       p->subs[idx].f.mallocd = 0;
09263       p->subs[idx].f.offset = 0;
09264       p->subs[idx].f.data.ptr = NULL;
09265       p->subs[idx].f.datalen= 0;
09266    }
09267    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09268       /* Perform busy detection etc on the dahdi line */
09269       int mute;
09270 
09271       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09272 
09273       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09274       mute = ast_dsp_was_muted(p->dsp);
09275       if (p->muting != mute) {
09276          p->muting = mute;
09277          dahdi_confmute(p, mute);
09278       }
09279 
09280       if (f) {
09281          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09282             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09283                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09284                   a busy */
09285                ast_frfree(f);
09286                f = NULL;
09287             }
09288          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09289             || f->frametype == AST_FRAME_DTMF_END) {
09290 #ifdef HAVE_PRI
09291             if (dahdi_sig_pri_lib_handles(p->sig)
09292                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09293                && p->pri
09294                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09295                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09296                /* Don't accept in-band DTMF when in overlap dial mode */
09297                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09298                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09299                   f->subclass.integer, f->subclass.integer, ast->name);
09300 
09301                f->frametype = AST_FRAME_NULL;
09302                f->subclass.integer = 0;
09303             }
09304 #endif
09305             /* DSP clears us of being pulse */
09306             p->pulsedial = 0;
09307          } else if (p->waitingfordt.tv_sec) {
09308             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09309                p->waitingfordt.tv_sec = 0;
09310                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09311                ast_frfree(f);
09312                f = NULL;
09313             } else if (f->frametype == AST_FRAME_VOICE) {
09314                f->frametype = AST_FRAME_NULL;
09315                f->subclass.integer = 0;
09316                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) {
09317                   p->waitingfordt.tv_sec = 0;
09318                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09319                   ast_dsp_set_features(p->dsp, p->dsp_features);
09320                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09321                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09322                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09323                      if (res < 0) {
09324                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09325                         p->dop.dialstr[0] = '\0';
09326                         ast_mutex_unlock(&p->lock);
09327                         ast_frfree(f);
09328                         return NULL;
09329                      } else {
09330                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09331                         p->dialing = 1;
09332                         p->dop.dialstr[0] = '\0';
09333                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09334                         ast_setstate(ast, AST_STATE_DIALING);
09335                      }
09336                   }
09337                }
09338             }
09339          }
09340       }
09341    } else
09342       f = &p->subs[idx].f;
09343 
09344    if (f) {
09345       switch (f->frametype) {
09346       case AST_FRAME_DTMF_BEGIN:
09347       case AST_FRAME_DTMF_END:
09348          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09349             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09350          } else {
09351             dahdi_handle_dtmf(ast, idx, &f);
09352          }
09353          break;
09354       case AST_FRAME_VOICE:
09355          if (p->cidspill || p->cid_suppress_expire) {
09356             /* We are/were sending a caller id spill.  Suppress any echo. */
09357             p->subs[idx].f.frametype = AST_FRAME_NULL;
09358             p->subs[idx].f.subclass.integer = 0;
09359             p->subs[idx].f.samples = 0;
09360             p->subs[idx].f.mallocd = 0;
09361             p->subs[idx].f.offset = 0;
09362             p->subs[idx].f.data.ptr = NULL;
09363             p->subs[idx].f.datalen= 0;
09364          }
09365          break;
09366       default:
09367          break;
09368       }
09369    }
09370 
09371    ast_mutex_unlock(&p->lock);
09372    return f;
09373 }
09374 
09375 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09376 {
09377    int sent=0;
09378    int size;
09379    int res;
09380    int fd;
09381    fd = p->subs[idx].dfd;
09382    while (len) {
09383       size = len;
09384       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09385          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09386       res = write(fd, buf, size);
09387       if (res != size) {
09388          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09389          return sent;
09390       }
09391       len -= size;
09392       buf += size;
09393    }
09394    return sent;
09395 }
09396 
09397 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09398 {
09399    struct dahdi_pvt *p = ast->tech_pvt;
09400    int res;
09401    int idx;
09402    idx = dahdi_get_index(ast, p, 0);
09403    if (idx < 0) {
09404       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09405       return -1;
09406    }
09407 
09408    /* Write a frame of (presumably voice) data */
09409    if (frame->frametype != AST_FRAME_VOICE) {
09410       if (frame->frametype != AST_FRAME_IMAGE)
09411          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09412       return 0;
09413    }
09414    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09415       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09416       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09417       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09418       return -1;
09419    }
09420    if (p->dialing) {
09421       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09422       return 0;
09423    }
09424    if (!p->owner) {
09425       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09426       return 0;
09427    }
09428    if (p->cidspill) {
09429       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09430          ast->name);
09431       return 0;
09432    }
09433    /* Return if it's not valid data */
09434    if (!frame->data.ptr || !frame->datalen)
09435       return 0;
09436 
09437    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09438       if (!p->subs[idx].linear) {
09439          p->subs[idx].linear = 1;
09440          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09441          if (res)
09442             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09443       }
09444       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09445    } else {
09446       /* x-law already */
09447       if (p->subs[idx].linear) {
09448          p->subs[idx].linear = 0;
09449          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09450          if (res)
09451             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09452       }
09453       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09454    }
09455    if (res < 0) {
09456       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09457       return -1;
09458    }
09459    return 0;
09460 }
09461 
09462 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09463 {
09464    struct dahdi_pvt *p = chan->tech_pvt;
09465    int res=-1;
09466    int idx;
09467    int func = DAHDI_FLASH;
09468 
09469    ast_mutex_lock(&p->lock);
09470    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09471    switch (p->sig) {
09472 #if defined(HAVE_PRI)
09473    case SIG_PRI_LIB_HANDLE_CASES:
09474       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09475       ast_mutex_unlock(&p->lock);
09476       return res;
09477 #endif   /* defined(HAVE_PRI) */
09478 #if defined(HAVE_SS7)
09479    case SIG_SS7:
09480       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09481       ast_mutex_unlock(&p->lock);
09482       return res;
09483 #endif   /* defined(HAVE_SS7) */
09484    default:
09485       break;
09486    }
09487 #ifdef HAVE_OPENR2
09488    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09489       ast_mutex_unlock(&p->lock);
09490       /* if this is an R2 call and the call is not yet accepted, we don't want the
09491          tone indications to mess up with the MF tones */
09492       return 0;
09493    }
09494 #endif
09495    idx = dahdi_get_index(chan, p, 0);
09496    if (idx == SUB_REAL) {
09497       switch (condition) {
09498       case AST_CONTROL_BUSY:
09499          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09500          break;
09501       case AST_CONTROL_RINGING:
09502          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09503 
09504          if (chan->_state != AST_STATE_UP) {
09505             if ((chan->_state != AST_STATE_RING) ||
09506                ((p->sig != SIG_FXSKS) &&
09507              (p->sig != SIG_FXSLS) &&
09508              (p->sig != SIG_FXSGS)))
09509             ast_setstate(chan, AST_STATE_RINGING);
09510          }
09511          break;
09512       case AST_CONTROL_INCOMPLETE:
09513          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09514          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09515          res = 0;
09516          break;
09517       case AST_CONTROL_PROCEEDING:
09518          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09519          /* don't continue in ast_indicate */
09520          res = 0;
09521          break;
09522       case AST_CONTROL_PROGRESS:
09523          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09524          /* don't continue in ast_indicate */
09525          res = 0;
09526          break;
09527       case AST_CONTROL_CONGESTION:
09528          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09529          switch (chan->hangupcause) {
09530          case AST_CAUSE_USER_BUSY:
09531          case AST_CAUSE_NORMAL_CLEARING:
09532          case 0:/* Cause has not been set. */
09533             /* Supply a more appropriate cause. */
09534             chan->hangupcause = AST_CAUSE_CONGESTION;
09535             break;
09536          default:
09537             break;
09538          }
09539          break;
09540       case AST_CONTROL_HOLD:
09541          ast_moh_start(chan, data, p->mohinterpret);
09542          break;
09543       case AST_CONTROL_UNHOLD:
09544          ast_moh_stop(chan);
09545          break;
09546       case AST_CONTROL_RADIO_KEY:
09547          if (p->radio)
09548             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09549          res = 0;
09550          break;
09551       case AST_CONTROL_RADIO_UNKEY:
09552          if (p->radio)
09553             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09554          res = 0;
09555          break;
09556       case AST_CONTROL_FLASH:
09557          /* flash hookswitch */
09558          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09559             /* Clear out the dial buffer */
09560             p->dop.dialstr[0] = '\0';
09561             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09562                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09563                   chan->name, strerror(errno));
09564             } else
09565                res = 0;
09566          } else
09567             res = 0;
09568          break;
09569       case AST_CONTROL_SRCUPDATE:
09570          res = 0;
09571          break;
09572       case -1:
09573          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09574          break;
09575       }
09576    } else {
09577       res = 0;
09578    }
09579    ast_mutex_unlock(&p->lock);
09580    return res;
09581 }
09582 
09583 #if defined(HAVE_PRI)
09584 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09585 #else
09586 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09587 #endif   /* defined(HAVE_PRI) */
09588 {
09589    struct ast_str *chan_name;
09590    int x, y;
09591 
09592    /* Create the new channel name tail. */
09593    if (!(chan_name = ast_str_create(32))) {
09594       return NULL;
09595    }
09596    if (i->channel == CHAN_PSEUDO) {
09597       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09598 #if defined(HAVE_PRI)
09599    } else if (i->pri) {
09600       ast_mutex_lock(&i->pri->lock);
09601       y = ++i->pri->new_chan_seq;
09602       if (is_outgoing) {
09603          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09604          address[0] = '\0';
09605       } else if (ast_strlen_zero(i->cid_subaddr)) {
09606          /* Put in caller-id number only since there is no subaddress. */
09607          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09608       } else {
09609          /* Put in caller-id number and subaddress. */
09610          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09611             i->cid_subaddr, y);
09612       }
09613       ast_mutex_unlock(&i->pri->lock);
09614 #endif   /* defined(HAVE_PRI) */
09615    } else {
09616       y = 1;
09617       do {
09618          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09619          for (x = 0; x < 3; ++x) {
09620             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09621                i->subs[x].owner->name + 6)) {
09622                break;
09623             }
09624          }
09625          ++y;
09626       } while (x < 3);
09627    }
09628    return chan_name;
09629 }
09630 
09631 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09632 {
09633    struct ast_channel *tmp;
09634    format_t deflaw;
09635    int x;
09636    int features;
09637    struct ast_str *chan_name;
09638    struct ast_variable *v;
09639    char *dashptr;
09640    char device_name[AST_CHANNEL_NAME];
09641 
09642    if (i->subs[idx].owner) {
09643       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09644       return NULL;
09645    }
09646 
09647 #if defined(HAVE_PRI)
09648    /*
09649     * The dnid has been stuffed with the called-number[:subaddress]
09650     * by dahdi_request() for outgoing calls.
09651     */
09652    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09653 #else
09654    chan_name = create_channel_name(i);
09655 #endif   /* defined(HAVE_PRI) */
09656    if (!chan_name) {
09657       return NULL;
09658    }
09659 
09660    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));
09661    ast_free(chan_name);
09662    if (!tmp)
09663       return NULL;
09664    tmp->tech = &dahdi_tech;
09665 #if defined(HAVE_PRI)
09666    if (i->pri) {
09667       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09668    }
09669 #endif   /* defined(HAVE_PRI) */
09670    ast_channel_cc_params_init(tmp, i->cc_params);
09671    if (law) {
09672       i->law = law;
09673       if (law == DAHDI_LAW_ALAW) {
09674          deflaw = AST_FORMAT_ALAW;
09675       } else {
09676          deflaw = AST_FORMAT_ULAW;
09677       }
09678    } else {
09679       switch (i->sig) {
09680       case SIG_PRI_LIB_HANDLE_CASES:
09681          /* Make sure companding law is known. */
09682          i->law = (i->law_default == DAHDI_LAW_ALAW)
09683             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09684          break;
09685       default:
09686          i->law = i->law_default;
09687          break;
09688       }
09689       if (i->law_default == DAHDI_LAW_ALAW) {
09690          deflaw = AST_FORMAT_ALAW;
09691       } else {
09692          deflaw = AST_FORMAT_ULAW;
09693       }
09694    }
09695    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09696    tmp->nativeformats = deflaw;
09697    /* Start out assuming ulaw since it's smaller :) */
09698    tmp->rawreadformat = deflaw;
09699    tmp->readformat = deflaw;
09700    tmp->rawwriteformat = deflaw;
09701    tmp->writeformat = deflaw;
09702    i->subs[idx].linear = 0;
09703    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09704    features = 0;
09705    if (idx == SUB_REAL) {
09706       if (i->busydetect && CANBUSYDETECT(i))
09707          features |= DSP_FEATURE_BUSY_DETECT;
09708       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09709          features |= DSP_FEATURE_CALL_PROGRESS;
09710       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09711          features |= DSP_FEATURE_WAITDIALTONE;
09712       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09713          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09714          features |= DSP_FEATURE_FAX_DETECT;
09715       }
09716       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09717       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09718          i->hardwaredtmf = 0;
09719          features |= DSP_FEATURE_DIGIT_DETECT;
09720       } else if (NEED_MFDETECT(i)) {
09721          i->hardwaredtmf = 1;
09722          features |= DSP_FEATURE_DIGIT_DETECT;
09723       }
09724    }
09725    if (features) {
09726       if (i->dsp) {
09727          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09728       } else {
09729          if (i->channel != CHAN_PSEUDO)
09730             i->dsp = ast_dsp_new();
09731          else
09732             i->dsp = NULL;
09733          if (i->dsp) {
09734             i->dsp_features = features;
09735 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09736             /* We cannot do progress detection until receive PROGRESS message */
09737             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09738                /* Remember requested DSP features, don't treat
09739                   talking as ANSWER */
09740                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09741                features = 0;
09742             }
09743 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09744             ast_dsp_set_features(i->dsp, features);
09745             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09746             if (!ast_strlen_zero(progzone))
09747                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09748             if (i->busydetect && CANBUSYDETECT(i)) {
09749                if(i->silencethreshold > 0)
09750                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09751                ast_dsp_set_busy_count(i->dsp, i->busycount);
09752                if(i->busytonelength > 0)
09753                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09754                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09755                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09756             }
09757          }
09758       }
09759    }
09760 
09761    if (state == AST_STATE_RING)
09762       tmp->rings = 1;
09763    tmp->tech_pvt = i;
09764    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09765       /* Only FXO signalled stuff can be picked up */
09766       tmp->callgroup = i->callgroup;
09767       tmp->pickupgroup = i->pickupgroup;
09768    }
09769    if (!ast_strlen_zero(i->parkinglot))
09770       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09771    if (!ast_strlen_zero(i->language))
09772       ast_string_field_set(tmp, language, i->language);
09773    if (!i->owner)
09774       i->owner = tmp;
09775    if (!ast_strlen_zero(i->accountcode))
09776       ast_string_field_set(tmp, accountcode, i->accountcode);
09777    if (i->amaflags)
09778       tmp->amaflags = i->amaflags;
09779    i->subs[idx].owner = tmp;
09780    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09781    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09782       ast_string_field_set(tmp, call_forward, i->call_forward);
09783    }
09784    /* If we've been told "no ADSI" then enforce it */
09785    if (!i->adsi)
09786       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09787    if (!ast_strlen_zero(i->exten))
09788       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09789    if (!ast_strlen_zero(i->rdnis)) {
09790       tmp->redirecting.from.number.valid = 1;
09791       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09792    }
09793    if (!ast_strlen_zero(i->dnid)) {
09794       tmp->dialed.number.str = ast_strdup(i->dnid);
09795    }
09796 
09797    /* Don't use ast_set_callerid() here because it will
09798     * generate a needless NewCallerID event */
09799 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09800    if (!ast_strlen_zero(i->cid_ani)) {
09801       tmp->caller.ani.number.valid = 1;
09802       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09803    } else if (!ast_strlen_zero(i->cid_num)) {
09804       tmp->caller.ani.number.valid = 1;
09805       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09806    }
09807 #else
09808    if (!ast_strlen_zero(i->cid_num)) {
09809       tmp->caller.ani.number.valid = 1;
09810       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09811    }
09812 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09813    tmp->caller.id.name.presentation = i->callingpres;
09814    tmp->caller.id.number.presentation = i->callingpres;
09815    tmp->caller.id.number.plan = i->cid_ton;
09816    tmp->caller.ani2 = i->cid_ani2;
09817    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09818    /* clear the fake event in case we posted one before we had ast_channel */
09819    i->fake_event = 0;
09820    /* Assure there is no confmute on this channel */
09821    dahdi_confmute(i, 0);
09822    i->muting = 0;
09823    /* Configure the new channel jb */
09824    ast_jb_configure(tmp, &global_jbconf);
09825 
09826    /* Set initial device state */
09827    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09828    dashptr = strrchr(device_name, '-');
09829    if (dashptr) {
09830       *dashptr = '\0';
09831    }
09832    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09833    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09834 
09835    for (v = i->vars ; v ; v = v->next)
09836       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09837 
09838    ast_module_ref(ast_module_info->self);
09839 
09840    dahdi_ami_channel_event(i, tmp);
09841    if (startpbx) {
09842 #ifdef HAVE_OPENR2
09843       if (i->mfcr2call) {
09844          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09845       }
09846 #endif
09847       if (ast_pbx_start(tmp)) {
09848          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09849          ast_hangup(tmp);
09850          return NULL;
09851       }
09852    }
09853    return tmp;
09854 }
09855 
09856 
09857 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09858 {
09859    char c;
09860 
09861    *str = 0; /* start with empty output buffer */
09862    for (;;)
09863    {
09864       /* Wait for the first digit (up to specified ms). */
09865       c = ast_waitfordigit(chan, ms);
09866       /* if timeout, hangup or error, return as such */
09867       if (c < 1)
09868          return c;
09869       *str++ = c;
09870       *str = 0;
09871       if (strchr(term, c))
09872          return 1;
09873    }
09874 }
09875 
09876 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09877 {
09878    int j;
09879    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09880    for (;;)
09881    {
09882       /* set bits of interest */
09883       j = DAHDI_IOMUX_SIGEVENT;
09884       /* wait for some happening */
09885       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09886       /* exit loop if we have it */
09887       if (j & DAHDI_IOMUX_SIGEVENT) break;
09888    }
09889    /* get the event info */
09890    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09891    return 0;
09892 }
09893 
09894 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09895  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09896  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09897  *
09898  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09899  * DAHDI channel). Use this to enable or disable it.
09900  *
09901  * \bug the use of the word "channel" for those dahdichans is really confusing.
09902  */
09903 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09904 {
09905    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09906       return analog_dnd(dahdichan->sig_pvt, flag);
09907    }
09908 
09909    if (flag == -1) {
09910       return dahdichan->dnd;
09911    }
09912 
09913    /* Do not disturb */
09914    dahdichan->dnd = flag;
09915    ast_verb(3, "%s DND on channel %d\n",
09916          flag? "Enabled" : "Disabled",
09917          dahdichan->channel);
09918    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09919          "Channel: DAHDI/%d\r\n"
09920          "Status: %s\r\n", dahdichan->channel,
09921          flag? "enabled" : "disabled");
09922 
09923    return 0;
09924 }
09925 
09926 static int canmatch_featurecode(const char *exten)
09927 {
09928    int extlen = strlen(exten);
09929    const char *pickup_ext;
09930    if (!extlen) {
09931       return 1;
09932    }
09933    pickup_ext = ast_pickup_ext();
09934    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09935       return 1;
09936    }
09937    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09938    if (exten[0] == '*' && extlen < 3) {
09939       if (extlen == 1) {
09940          return 1;
09941       }
09942       /* "*0" should be processed before it gets here */
09943       switch (exten[1]) {
09944       case '6':
09945       case '7':
09946       case '8':
09947          return 1;
09948       }
09949    }
09950    return 0;
09951 }
09952 
09953 static void *analog_ss_thread(void *data)
09954 {
09955    struct ast_channel *chan = data;
09956    struct dahdi_pvt *p = chan->tech_pvt;
09957    char exten[AST_MAX_EXTENSION] = "";
09958    char exten2[AST_MAX_EXTENSION] = "";
09959    unsigned char buf[256];
09960    char dtmfcid[300];
09961    char dtmfbuf[300];
09962    struct callerid_state *cs = NULL;
09963    char *name = NULL, *number = NULL;
09964    int distMatches;
09965    int curRingData[3];
09966    int receivedRingT;
09967    int counter1;
09968    int counter;
09969    int samples = 0;
09970    struct ast_smdi_md_message *smdi_msg = NULL;
09971    int flags = 0;
09972    int i;
09973    int timeout;
09974    int getforward = 0;
09975    char *s1, *s2;
09976    int len = 0;
09977    int res;
09978    int idx;
09979 
09980    ast_mutex_lock(&ss_thread_lock);
09981    ss_thread_count++;
09982    ast_mutex_unlock(&ss_thread_lock);
09983    /* in the bizarre case where the channel has become a zombie before we
09984       even get started here, abort safely
09985    */
09986    if (!p) {
09987       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09988       ast_hangup(chan);
09989       goto quit;
09990    }
09991    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09992    idx = dahdi_get_index(chan, p, 1);
09993    if (idx < 0) {
09994       ast_log(LOG_WARNING, "Huh?\n");
09995       ast_hangup(chan);
09996       goto quit;
09997    }
09998    if (p->dsp)
09999       ast_dsp_digitreset(p->dsp);
10000    switch (p->sig) {
10001    case SIG_FEATD:
10002    case SIG_FEATDMF:
10003    case SIG_FEATDMF_TA:
10004    case SIG_E911:
10005    case SIG_FGC_CAMAMF:
10006    case SIG_FEATB:
10007    case SIG_EMWINK:
10008    case SIG_SF_FEATD:
10009    case SIG_SF_FEATDMF:
10010    case SIG_SF_FEATB:
10011    case SIG_SFWINK:
10012       if (dahdi_wink(p, idx))
10013          goto quit;
10014       /* Fall through */
10015    case SIG_EM:
10016    case SIG_EM_E1:
10017    case SIG_SF:
10018    case SIG_FGC_CAMA:
10019       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10020       if (p->dsp)
10021          ast_dsp_digitreset(p->dsp);
10022       /* set digit mode appropriately */
10023       if (p->dsp) {
10024          if (NEED_MFDETECT(p))
10025             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10026          else
10027             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10028       }
10029       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10030       /* Wait for the first digit only if immediate=no */
10031       if (!p->immediate)
10032          /* Wait for the first digit (up to 5 seconds). */
10033          res = ast_waitfordigit(chan, 5000);
10034       else
10035          res = 0;
10036       if (res > 0) {
10037          /* save first char */
10038          dtmfbuf[0] = res;
10039          switch (p->sig) {
10040          case SIG_FEATD:
10041          case SIG_SF_FEATD:
10042             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10043             if (res > 0)
10044                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10045             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10046             break;
10047          case SIG_FEATDMF_TA:
10048             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10049             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10050             if (dahdi_wink(p, idx)) goto quit;
10051             dtmfbuf[0] = 0;
10052             /* Wait for the first digit (up to 5 seconds). */
10053             res = ast_waitfordigit(chan, 5000);
10054             if (res <= 0) break;
10055             dtmfbuf[0] = res;
10056             /* fall through intentionally */
10057          case SIG_FEATDMF:
10058          case SIG_E911:
10059          case SIG_FGC_CAMAMF:
10060          case SIG_SF_FEATDMF:
10061             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10062             /* if international caca, do it again to get real ANO */
10063             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10064             {
10065                if (dahdi_wink(p, idx)) goto quit;
10066                dtmfbuf[0] = 0;
10067                /* Wait for the first digit (up to 5 seconds). */
10068                res = ast_waitfordigit(chan, 5000);
10069                if (res <= 0) break;
10070                dtmfbuf[0] = res;
10071                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10072             }
10073             if (res > 0) {
10074                /* if E911, take off hook */
10075                if (p->sig == SIG_E911)
10076                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10077                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10078             }
10079             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10080             break;
10081          case SIG_FEATB:
10082          case SIG_SF_FEATB:
10083             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10084             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10085             break;
10086          case SIG_EMWINK:
10087             /* if we received a '*', we are actually receiving Feature Group D
10088                dial syntax, so use that mode; otherwise, fall through to normal
10089                mode
10090             */
10091             if (res == '*') {
10092                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10093                if (res > 0)
10094                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10095                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10096                break;
10097             }
10098          default:
10099             /* If we got the first digit, get the rest */
10100             len = 1;
10101             dtmfbuf[len] = '\0';
10102             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10103                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10104                   timeout = matchdigittimeout;
10105                } else {
10106                   timeout = gendigittimeout;
10107                }
10108                res = ast_waitfordigit(chan, timeout);
10109                if (res < 0) {
10110                   ast_debug(1, "waitfordigit returned < 0...\n");
10111                   ast_hangup(chan);
10112                   goto quit;
10113                } else if (res) {
10114                   dtmfbuf[len++] = res;
10115                   dtmfbuf[len] = '\0';
10116                } else {
10117                   break;
10118                }
10119             }
10120             break;
10121          }
10122       }
10123       if (res == -1) {
10124          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10125          ast_hangup(chan);
10126          goto quit;
10127       } else if (res < 0) {
10128          ast_debug(1, "Got hung up before digits finished\n");
10129          ast_hangup(chan);
10130          goto quit;
10131       }
10132 
10133       if (p->sig == SIG_FGC_CAMA) {
10134          char anibuf[100];
10135 
10136          if (ast_safe_sleep(chan,1000) == -1) {
10137             ast_hangup(chan);
10138             goto quit;
10139          }
10140          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10141          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10142          res = my_getsigstr(chan, anibuf, "#", 10000);
10143          if ((res > 0) && (strlen(anibuf) > 2)) {
10144             if (anibuf[strlen(anibuf) - 1] == '#')
10145                anibuf[strlen(anibuf) - 1] = 0;
10146             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10147          }
10148          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10149       }
10150 
10151       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10152       if (ast_strlen_zero(exten))
10153          ast_copy_string(exten, "s", sizeof(exten));
10154       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10155          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10156          if (exten[0] == '*') {
10157             char *stringp=NULL;
10158             ast_copy_string(exten2, exten, sizeof(exten2));
10159             /* Parse out extension and callerid */
10160             stringp=exten2 +1;
10161             s1 = strsep(&stringp, "*");
10162             s2 = strsep(&stringp, "*");
10163             if (s2) {
10164                if (!ast_strlen_zero(p->cid_num))
10165                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10166                else
10167                   ast_set_callerid(chan, s1, NULL, s1);
10168                ast_copy_string(exten, s2, sizeof(exten));
10169             } else
10170                ast_copy_string(exten, s1, sizeof(exten));
10171          } else if (p->sig == SIG_FEATD)
10172             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10173       }
10174       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10175          if (exten[0] == '*') {
10176             char *stringp=NULL;
10177             ast_copy_string(exten2, exten, sizeof(exten2));
10178             /* Parse out extension and callerid */
10179             stringp=exten2 +1;
10180             s1 = strsep(&stringp, "#");
10181             s2 = strsep(&stringp, "#");
10182             if (s2) {
10183                if (!ast_strlen_zero(p->cid_num))
10184                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10185                else
10186                   if (*(s1 + 2))
10187                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10188                ast_copy_string(exten, s2 + 1, sizeof(exten));
10189             } else
10190                ast_copy_string(exten, s1 + 2, sizeof(exten));
10191          } else
10192             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10193       }
10194       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10195          if (exten[0] == '*') {
10196             char *stringp=NULL;
10197             ast_copy_string(exten2, exten, sizeof(exten2));
10198             /* Parse out extension and callerid */
10199             stringp=exten2 +1;
10200             s1 = strsep(&stringp, "#");
10201             s2 = strsep(&stringp, "#");
10202             if (s2 && (*(s2 + 1) == '0')) {
10203                if (*(s2 + 2))
10204                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10205             }
10206             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10207             else ast_copy_string(exten, "911", sizeof(exten));
10208          } else
10209             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10210       }
10211       if (p->sig == SIG_FEATB) {
10212          if (exten[0] == '*') {
10213             char *stringp=NULL;
10214             ast_copy_string(exten2, exten, sizeof(exten2));
10215             /* Parse out extension and callerid */
10216             stringp=exten2 +1;
10217             s1 = strsep(&stringp, "#");
10218             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10219          } else
10220             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10221       }
10222       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10223          dahdi_wink(p, idx);
10224          /* some switches require a minimum guard time between
10225             the last FGD wink and something that answers
10226             immediately. This ensures it */
10227          if (ast_safe_sleep(chan, 100)) {
10228             ast_hangup(chan);
10229             goto quit;
10230          }
10231       }
10232       dahdi_enable_ec(p);
10233       if (NEED_MFDETECT(p)) {
10234          if (p->dsp) {
10235             if (!p->hardwaredtmf)
10236                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10237             else {
10238                ast_dsp_free(p->dsp);
10239                p->dsp = NULL;
10240             }
10241          }
10242       }
10243 
10244       if (ast_exists_extension(chan, chan->context, exten, 1,
10245          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10246          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10247          if (p->dsp) ast_dsp_digitreset(p->dsp);
10248          res = ast_pbx_run(chan);
10249          if (res) {
10250             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10251             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10252          }
10253          goto quit;
10254       } else {
10255          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10256          sleep(2);
10257          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10258          if (res < 0)
10259             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10260          else
10261             sleep(1);
10262          res = ast_streamfile(chan, "ss-noservice", chan->language);
10263          if (res >= 0)
10264             ast_waitstream(chan, "");
10265          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10266          ast_hangup(chan);
10267          goto quit;
10268       }
10269       break;
10270    case SIG_FXOLS:
10271    case SIG_FXOGS:
10272    case SIG_FXOKS:
10273       /* Read the first digit */
10274       timeout = firstdigittimeout;
10275       /* If starting a threeway call, never timeout on the first digit so someone
10276          can use flash-hook as a "hold" feature */
10277       if (p->subs[SUB_THREEWAY].owner)
10278          timeout = 999999;
10279       while (len < AST_MAX_EXTENSION-1) {
10280          /* Read digit unless it's supposed to be immediate, in which case the
10281             only answer is 's' */
10282          if (p->immediate)
10283             res = 's';
10284          else
10285             res = ast_waitfordigit(chan, timeout);
10286          timeout = 0;
10287          if (res < 0) {
10288             ast_debug(1, "waitfordigit returned < 0...\n");
10289             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10290             ast_hangup(chan);
10291             goto quit;
10292          } else if (res) {
10293             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10294             exten[len++]=res;
10295             exten[len] = '\0';
10296          }
10297          if (!ast_ignore_pattern(chan->context, exten))
10298             tone_zone_play_tone(p->subs[idx].dfd, -1);
10299          else
10300             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10301          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10302             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10303                if (getforward) {
10304                   /* Record this as the forwarding extension */
10305                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10306                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10307                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10308                   if (res)
10309                      break;
10310                   usleep(500000);
10311                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10312                   sleep(1);
10313                   memset(exten, 0, sizeof(exten));
10314                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10315                   len = 0;
10316                   getforward = 0;
10317                } else {
10318                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10319                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10320                   if (!ast_strlen_zero(p->cid_num)) {
10321                      if (!p->hidecallerid)
10322                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10323                      else
10324                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10325                   }
10326                   if (!ast_strlen_zero(p->cid_name)) {
10327                      if (!p->hidecallerid)
10328                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10329                   }
10330                   ast_setstate(chan, AST_STATE_RING);
10331                   dahdi_enable_ec(p);
10332                   res = ast_pbx_run(chan);
10333                   if (res) {
10334                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10335                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10336                   }
10337                   goto quit;
10338                }
10339             } else {
10340                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10341                   so just set the timeout to matchdigittimeout and wait some more */
10342                timeout = matchdigittimeout;
10343             }
10344          } else if (res == 0) {
10345             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10346             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10347             dahdi_wait_event(p->subs[idx].dfd);
10348             ast_hangup(chan);
10349             goto quit;
10350          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10351             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10352             /* Disable call waiting if enabled */
10353             p->callwaiting = 0;
10354             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10355             if (res) {
10356                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10357                   chan->name, strerror(errno));
10358             }
10359             len = 0;
10360             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10361             memset(exten, 0, sizeof(exten));
10362             timeout = firstdigittimeout;
10363 
10364          } else if (!strcmp(exten,ast_pickup_ext())) {
10365             /* Scan all channels and see if there are any
10366              * ringing channels that have call groups
10367              * that equal this channels pickup group
10368              */
10369             if (idx == SUB_REAL) {
10370                /* Switch us from Third call to Call Wait */
10371                if (p->subs[SUB_THREEWAY].owner) {
10372                   /* If you make a threeway call and the *8# a call, it should actually
10373                      look like a callwait */
10374                   alloc_sub(p, SUB_CALLWAIT);
10375                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10376                   unalloc_sub(p, SUB_THREEWAY);
10377                }
10378                dahdi_enable_ec(p);
10379                if (ast_pickup_call(chan)) {
10380                   ast_debug(1, "No call pickup possible...\n");
10381                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10382                   dahdi_wait_event(p->subs[idx].dfd);
10383                }
10384                ast_hangup(chan);
10385                goto quit;
10386             } else {
10387                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10388                ast_hangup(chan);
10389                goto quit;
10390             }
10391 
10392          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10393             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10394             /* Disable Caller*ID if enabled */
10395             p->hidecallerid = 1;
10396             ast_party_number_free(&chan->caller.id.number);
10397             ast_party_number_init(&chan->caller.id.number);
10398             ast_party_name_free(&chan->caller.id.name);
10399             ast_party_name_init(&chan->caller.id.name);
10400             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401             if (res) {
10402                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10403                   chan->name, strerror(errno));
10404             }
10405             len = 0;
10406             memset(exten, 0, sizeof(exten));
10407             timeout = firstdigittimeout;
10408          } else if (p->callreturn && !strcmp(exten, "*69")) {
10409             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10410             break;
10411          } else if (!strcmp(exten, "*78")) {
10412             dahdi_dnd(p, 1);
10413             /* Do not disturb */
10414             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10415             getforward = 0;
10416             memset(exten, 0, sizeof(exten));
10417             len = 0;
10418          } else if (!strcmp(exten, "*79")) {
10419             dahdi_dnd(p, 0);
10420             /* Do not disturb */
10421             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10422             getforward = 0;
10423             memset(exten, 0, sizeof(exten));
10424             len = 0;
10425          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10426             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10427             getforward = 1;
10428             memset(exten, 0, sizeof(exten));
10429             len = 0;
10430          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10431             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10432             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10433             memset(p->call_forward, 0, sizeof(p->call_forward));
10434             getforward = 0;
10435             memset(exten, 0, sizeof(exten));
10436             len = 0;
10437          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10438                   p->subs[SUB_THREEWAY].owner &&
10439                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10440             /* This is a three way call, the main call being a real channel,
10441                and we're parking the first call. */
10442             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10443                chan, exten, chan->context, 0, NULL);
10444             ast_verb(3, "Parking call to '%s'\n", chan->name);
10445             break;
10446          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10447             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10448             /* Enable Caller*ID if enabled */
10449             p->hidecallerid = 0;
10450             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10451             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10452             if (res) {
10453                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10454                   chan->name, strerror(errno));
10455             }
10456             len = 0;
10457             memset(exten, 0, sizeof(exten));
10458             timeout = firstdigittimeout;
10459          } else if (!strcmp(exten, "*0")) {
10460             struct ast_channel *nbridge =
10461                p->subs[SUB_THREEWAY].owner;
10462             struct dahdi_pvt *pbridge = NULL;
10463             /* set up the private struct of the bridged one, if any */
10464             if (nbridge && ast_bridged_channel(nbridge))
10465                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10466             if (nbridge && pbridge &&
10467                (nbridge->tech == &dahdi_tech) &&
10468                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10469                ISTRUNK(pbridge)) {
10470                int func = DAHDI_FLASH;
10471                /* Clear out the dial buffer */
10472                p->dop.dialstr[0] = '\0';
10473                /* flash hookswitch */
10474                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10475                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10476                      nbridge->name, strerror(errno));
10477                }
10478                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10479                unalloc_sub(p, SUB_THREEWAY);
10480                p->owner = p->subs[SUB_REAL].owner;
10481                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10482                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10483                ast_hangup(chan);
10484                goto quit;
10485             } else {
10486                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10487                dahdi_wait_event(p->subs[idx].dfd);
10488                tone_zone_play_tone(p->subs[idx].dfd, -1);
10489                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10490                unalloc_sub(p, SUB_THREEWAY);
10491                p->owner = p->subs[SUB_REAL].owner;
10492                ast_hangup(chan);
10493                goto quit;
10494             }
10495          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10496             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10497             && !canmatch_featurecode(exten)) {
10498             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10499                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10500                chan->context);
10501             break;
10502          }
10503          if (!timeout)
10504             timeout = gendigittimeout;
10505          if (len && !ast_ignore_pattern(chan->context, exten))
10506             tone_zone_play_tone(p->subs[idx].dfd, -1);
10507       }
10508       break;
10509    case SIG_FXSLS:
10510    case SIG_FXSGS:
10511    case SIG_FXSKS:
10512       /* check for SMDI messages */
10513       if (p->use_smdi && p->smdi_iface) {
10514          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10515 
10516          if (smdi_msg != NULL) {
10517             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10518 
10519             if (smdi_msg->type == 'B')
10520                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10521             else if (smdi_msg->type == 'N')
10522                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10523 
10524             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10525          } else {
10526             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10527          }
10528       }
10529 
10530       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10531          number = smdi_msg->calling_st;
10532 
10533       /* If we want caller id, we're in a prering state due to a polarity reversal
10534        * and we're set to use a polarity reversal to trigger the start of caller id,
10535        * grab the caller id and wait for ringing to start... */
10536       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10537                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10538          /* If set to use DTMF CID signalling, listen for DTMF */
10539          if (p->cid_signalling == CID_SIG_DTMF) {
10540             int k = 0;
10541             int off_ms;
10542             struct timeval start = ast_tvnow();
10543             int ms;
10544             cs = NULL;
10545             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10546             dahdi_setlinear(p->subs[idx].dfd, 0);
10547             /*
10548              * We are the only party interested in the Rx stream since
10549              * we have not answered yet.  We don't need or even want DTMF
10550              * emulation.  The DTMF digits can come so fast that emulation
10551              * can drop some of them.
10552              */
10553             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10554             off_ms = 4000;/* This is a typical OFF time between rings. */
10555             for (;;) {
10556                struct ast_frame *f;
10557 
10558                ms = ast_remaining_ms(start, off_ms);
10559                res = ast_waitfor(chan, ms);
10560                if (res <= 0) {
10561                   /*
10562                    * We do not need to restore the dahdi_setlinear()
10563                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10564                    * are hanging up the channel.
10565                    */
10566                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10567                      "Exiting simple switch\n");
10568                   ast_hangup(chan);
10569                   goto quit;
10570                }
10571                f = ast_read(chan);
10572                if (!f)
10573                   break;
10574                if (f->frametype == AST_FRAME_DTMF) {
10575                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10576                      dtmfbuf[k++] = f->subclass.integer;
10577                   }
10578                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10579                   start = ast_tvnow();
10580                }
10581                ast_frfree(f);
10582                if (chan->_state == AST_STATE_RING ||
10583                   chan->_state == AST_STATE_RINGING)
10584                   break; /* Got ring */
10585             }
10586             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10587             dtmfbuf[k] = '\0';
10588             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10589             /* Got cid and ring. */
10590             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10591             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10592             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10593             /* If first byte is NULL, we have no cid */
10594             if (!ast_strlen_zero(dtmfcid))
10595                number = dtmfcid;
10596             else
10597                number = NULL;
10598          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10599          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10600             cs = callerid_new(p->cid_signalling);
10601             if (cs) {
10602                int off_ms;
10603                struct timeval start;
10604                int ms;
10605                samples = 0;
10606 #if 1
10607                bump_gains(p);
10608 #endif
10609                /* Take out of linear mode for Caller*ID processing */
10610                dahdi_setlinear(p->subs[idx].dfd, 0);
10611 
10612                /* First we wait and listen for the Caller*ID */
10613                for (;;) {
10614                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10615                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10616                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10617                      callerid_free(cs);
10618                      ast_hangup(chan);
10619                      goto quit;
10620                   }
10621                   if (i & DAHDI_IOMUX_SIGEVENT) {
10622                      res = dahdi_get_event(p->subs[idx].dfd);
10623                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10624                      if (res == DAHDI_EVENT_NOALARM) {
10625                         p->inalarm = 0;
10626                      }
10627 
10628                      if (p->cid_signalling == CID_SIG_V23_JP) {
10629                         if (res == DAHDI_EVENT_RINGBEGIN) {
10630                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10631                            usleep(1);
10632                         }
10633                      } else {
10634                         res = 0;
10635                         break;
10636                      }
10637                   } else if (i & DAHDI_IOMUX_READ) {
10638                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10639                      if (res < 0) {
10640                         if (errno != ELAST) {
10641                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10642                            callerid_free(cs);
10643                            ast_hangup(chan);
10644                            goto quit;
10645                         }
10646                         break;
10647                      }
10648                      samples += res;
10649 
10650                      if (p->cid_signalling == CID_SIG_V23_JP) {
10651                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10652                      } else {
10653                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10654                      }
10655                      if (res < 0) {
10656                         /*
10657                          * The previous diagnostic message output likely
10658                          * explains why it failed.
10659                          */
10660                         ast_log(LOG_WARNING,
10661                            "Failed to decode CallerID on channel '%s'\n",
10662                            chan->name);
10663                         break;
10664                      } else if (res)
10665                         break;
10666                      else if (samples > (8000 * 10))
10667                         break;
10668                   }
10669                }
10670                if (res == 1) {
10671                   callerid_get(cs, &name, &number, &flags);
10672                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10673                }
10674 
10675                if (p->cid_signalling == CID_SIG_V23_JP) {
10676                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10677                   usleep(1);
10678                }
10679 
10680                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10681                start = ast_tvnow();
10682                off_ms = 4000;/* This is a typical OFF time between rings. */
10683                for (;;) {
10684                   struct ast_frame *f;
10685 
10686                   ms = ast_remaining_ms(start, off_ms);
10687                   res = ast_waitfor(chan, ms);
10688                   if (res <= 0) {
10689                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10690                         "Exiting simple switch\n");
10691                      ast_hangup(chan);
10692                      goto quit;
10693                   }
10694                   if (!(f = ast_read(chan))) {
10695                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10696                      ast_hangup(chan);
10697                      goto quit;
10698                   }
10699                   ast_frfree(f);
10700                   if (chan->_state == AST_STATE_RING ||
10701                      chan->_state == AST_STATE_RINGING)
10702                      break; /* Got ring */
10703                }
10704 
10705                /* We must have a ring by now, so, if configured, lets try to listen for
10706                 * distinctive ringing */
10707                if (p->usedistinctiveringdetection) {
10708                   len = 0;
10709                   distMatches = 0;
10710                   /* Clear the current ring data array so we don't have old data in it. */
10711                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10712                      curRingData[receivedRingT] = 0;
10713                   receivedRingT = 0;
10714                   counter = 0;
10715                   counter1 = 0;
10716                   /* Check to see if context is what it should be, if not set to be. */
10717                   if (strcmp(p->context,p->defcontext) != 0) {
10718                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10719                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10720                   }
10721 
10722                   for (;;) {
10723                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10724                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10725                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10726                         callerid_free(cs);
10727                         ast_hangup(chan);
10728                         goto quit;
10729                      }
10730                      if (i & DAHDI_IOMUX_SIGEVENT) {
10731                         res = dahdi_get_event(p->subs[idx].dfd);
10732                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10733                         if (res == DAHDI_EVENT_NOALARM) {
10734                            p->inalarm = 0;
10735                         }
10736                         res = 0;
10737                         /* Let us detect distinctive ring */
10738 
10739                         curRingData[receivedRingT] = p->ringt;
10740 
10741                         if (p->ringt < p->ringt_base/2)
10742                            break;
10743                         /* Increment the ringT counter so we can match it against
10744                            values in chan_dahdi.conf for distinctive ring */
10745                         if (++receivedRingT == ARRAY_LEN(curRingData))
10746                            break;
10747                      } else if (i & DAHDI_IOMUX_READ) {
10748                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10749                         if (res < 0) {
10750                            if (errno != ELAST) {
10751                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10752                               callerid_free(cs);
10753                               ast_hangup(chan);
10754                               goto quit;
10755                            }
10756                            break;
10757                         }
10758                         if (p->ringt > 0) {
10759                            if (!(--p->ringt)) {
10760                               res = -1;
10761                               break;
10762                            }
10763                         }
10764                      }
10765                   }
10766                      /* this only shows up if you have n of the dring patterns filled in */
10767                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10768                   for (counter = 0; counter < 3; counter++) {
10769                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10770                      channel */
10771                      distMatches = 0;
10772                      for (counter1 = 0; counter1 < 3; counter1++) {
10773                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10774                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10775                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10776                            curRingData[counter1]);
10777                            distMatches++;
10778                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10779                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10780                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10781                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10782                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10783                            distMatches++;
10784                         }
10785                      }
10786 
10787                      if (distMatches == 3) {
10788                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10789                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10790                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10791                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10792                         break;
10793                      }
10794                   }
10795                }
10796                /* Restore linear mode (if appropriate) for Caller*ID processing */
10797                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10798 #if 1
10799                restore_gains(p);
10800 #endif
10801             } else
10802                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10803          } else {
10804             ast_log(LOG_WARNING, "Channel %s in prering "
10805                "state, but I have nothing to do. "
10806                "Terminating simple switch, should be "
10807                "restarted by the actual ring.\n",
10808                chan->name);
10809             ast_hangup(chan);
10810             goto quit;
10811          }
10812       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10813          if (p->cid_signalling == CID_SIG_DTMF) {
10814             int k = 0;
10815             int off_ms;
10816             struct timeval start;
10817             int ms;
10818             cs = NULL;
10819             dahdi_setlinear(p->subs[idx].dfd, 0);
10820             off_ms = 2000;
10821             start = ast_tvnow();
10822             for (;;) {
10823                struct ast_frame *f;
10824 
10825                ms = ast_remaining_ms(start, off_ms);
10826                res = ast_waitfor(chan, ms);
10827                if (res <= 0) {
10828                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10829                      "Exiting simple switch\n");
10830                   ast_hangup(chan);
10831                   goto quit;
10832                }
10833                f = ast_read(chan);
10834                if (!f) {
10835                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10836                   ast_hangup(chan);
10837                   goto quit;
10838                }
10839                if (f->frametype == AST_FRAME_DTMF) {
10840                   dtmfbuf[k++] = f->subclass.integer;
10841                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10842                   start = ast_tvnow();
10843                }
10844                ast_frfree(f);
10845 
10846                if (p->ringt_base == p->ringt)
10847                   break;
10848             }
10849             dtmfbuf[k] = '\0';
10850             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10851             /* Got cid and ring. */
10852             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10853             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10854                dtmfcid, flags);
10855             /* If first byte is NULL, we have no cid */
10856             if (!ast_strlen_zero(dtmfcid))
10857                number = dtmfcid;
10858             else
10859                number = NULL;
10860             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10861          } else {
10862             /* FSK Bell202 callerID */
10863             cs = callerid_new(p->cid_signalling);
10864             if (cs) {
10865 #if 1
10866                bump_gains(p);
10867 #endif
10868                samples = 0;
10869                len = 0;
10870                distMatches = 0;
10871                /* Clear the current ring data array so we don't have old data in it. */
10872                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10873                   curRingData[receivedRingT] = 0;
10874                receivedRingT = 0;
10875                counter = 0;
10876                counter1 = 0;
10877                /* Check to see if context is what it should be, if not set to be. */
10878                if (strcmp(p->context,p->defcontext) != 0) {
10879                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10880                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10881                }
10882 
10883                /* Take out of linear mode for Caller*ID processing */
10884                dahdi_setlinear(p->subs[idx].dfd, 0);
10885                for (;;) {
10886                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10887                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10888                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10889                      callerid_free(cs);
10890                      ast_hangup(chan);
10891                      goto quit;
10892                   }
10893                   if (i & DAHDI_IOMUX_SIGEVENT) {
10894                      res = dahdi_get_event(p->subs[idx].dfd);
10895                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10896                      if (res == DAHDI_EVENT_NOALARM) {
10897                         p->inalarm = 0;
10898                      }
10899                      /* If we get a PR event, they hung up while processing calerid */
10900                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10901                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10902                         p->polarity = POLARITY_IDLE;
10903                         callerid_free(cs);
10904                         ast_hangup(chan);
10905                         goto quit;
10906                      }
10907                      res = 0;
10908                      /* Let us detect callerid when the telco uses distinctive ring */
10909 
10910                      curRingData[receivedRingT] = p->ringt;
10911 
10912                      if (p->ringt < p->ringt_base/2)
10913                         break;
10914                      /* Increment the ringT counter so we can match it against
10915                         values in chan_dahdi.conf for distinctive ring */
10916                      if (++receivedRingT == ARRAY_LEN(curRingData))
10917                         break;
10918                   } else if (i & DAHDI_IOMUX_READ) {
10919                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10920                      if (res < 0) {
10921                         if (errno != ELAST) {
10922                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10923                            callerid_free(cs);
10924                            ast_hangup(chan);
10925                            goto quit;
10926                         }
10927                         break;
10928                      }
10929                      if (p->ringt > 0) {
10930                         if (!(--p->ringt)) {
10931                            res = -1;
10932                            break;
10933                         }
10934                      }
10935                      samples += res;
10936                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10937                      if (res < 0) {
10938                         /*
10939                          * The previous diagnostic message output likely
10940                          * explains why it failed.
10941                          */
10942                         ast_log(LOG_WARNING,
10943                            "Failed to decode CallerID on channel '%s'\n",
10944                            chan->name);
10945                         break;
10946                      } else if (res)
10947                         break;
10948                      else if (samples > (8000 * 10))
10949                         break;
10950                   }
10951                }
10952                if (res == 1) {
10953                   callerid_get(cs, &name, &number, &flags);
10954                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10955                }
10956                if (distinctiveringaftercid == 1) {
10957                   /* Clear the current ring data array so we don't have old data in it. */
10958                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10959                      curRingData[receivedRingT] = 0;
10960                   }
10961                   receivedRingT = 0;
10962                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10963                   for (;;) {
10964                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10965                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10966                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10967                         callerid_free(cs);
10968                         ast_hangup(chan);
10969                         goto quit;
10970                      }
10971                      if (i & DAHDI_IOMUX_SIGEVENT) {
10972                         res = dahdi_get_event(p->subs[idx].dfd);
10973                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10974                         if (res == DAHDI_EVENT_NOALARM) {
10975                            p->inalarm = 0;
10976                         }
10977                         res = 0;
10978                         /* Let us detect callerid when the telco uses distinctive ring */
10979 
10980                         curRingData[receivedRingT] = p->ringt;
10981 
10982                         if (p->ringt < p->ringt_base/2)
10983                            break;
10984                         /* Increment the ringT counter so we can match it against
10985                            values in chan_dahdi.conf for distinctive ring */
10986                         if (++receivedRingT == ARRAY_LEN(curRingData))
10987                            break;
10988                      } else if (i & DAHDI_IOMUX_READ) {
10989                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10990                         if (res < 0) {
10991                            if (errno != ELAST) {
10992                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10993                               callerid_free(cs);
10994                               ast_hangup(chan);
10995                               goto quit;
10996                            }
10997                            break;
10998                         }
10999                         if (p->ringt > 0) {
11000                            if (!(--p->ringt)) {
11001                               res = -1;
11002                               break;
11003                            }
11004                         }
11005                      }
11006                   }
11007                }
11008                if (p->usedistinctiveringdetection) {
11009                   /* this only shows up if you have n of the dring patterns filled in */
11010                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11011 
11012                   for (counter = 0; counter < 3; counter++) {
11013                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11014                      channel */
11015                      /* this only shows up if you have n of the dring patterns filled in */
11016                      ast_verb(3, "Checking %d,%d,%d\n",
11017                            p->drings.ringnum[counter].ring[0],
11018                            p->drings.ringnum[counter].ring[1],
11019                            p->drings.ringnum[counter].ring[2]);
11020                      distMatches = 0;
11021                      for (counter1 = 0; counter1 < 3; counter1++) {
11022                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11023                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11024                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11025                            curRingData[counter1]);
11026                            distMatches++;
11027                         }
11028                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11029                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11030                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11031                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11032                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11033                            distMatches++;
11034                         }
11035                      }
11036                      if (distMatches == 3) {
11037                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11038                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11039                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11040                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11041                         break;
11042                      }
11043                   }
11044                }
11045                /* Restore linear mode (if appropriate) for Caller*ID processing */
11046                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11047 #if 1
11048                restore_gains(p);
11049 #endif
11050                if (res < 0) {
11051                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11052                }
11053             } else
11054                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11055          }
11056       } else
11057          cs = NULL;
11058 
11059       if (number)
11060          ast_shrink_phone_number(number);
11061       ast_set_callerid(chan, number, name, number);
11062 
11063       if (smdi_msg)
11064          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11065 
11066       if (cs)
11067          callerid_free(cs);
11068 
11069       my_handle_notify_message(chan, p, flags, -1);
11070 
11071       ast_setstate(chan, AST_STATE_RING);
11072       chan->rings = 1;
11073       p->ringt = p->ringt_base;
11074       res = ast_pbx_run(chan);
11075       if (res) {
11076          ast_hangup(chan);
11077          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11078       }
11079       goto quit;
11080    default:
11081       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11082       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11083       if (res < 0)
11084             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11085    }
11086    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11087    if (res < 0)
11088          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11089    ast_hangup(chan);
11090 quit:
11091    ast_mutex_lock(&ss_thread_lock);
11092    ss_thread_count--;
11093    ast_cond_signal(&ss_thread_complete);
11094    ast_mutex_unlock(&ss_thread_lock);
11095    return NULL;
11096 }
11097 
11098 struct mwi_thread_data {
11099    struct dahdi_pvt *pvt;
11100    unsigned char buf[READ_SIZE];
11101    size_t len;
11102 };
11103 
11104 static int calc_energy(const unsigned char *buf, int len, format_t law)
11105 {
11106    int x;
11107    int sum = 0;
11108 
11109    if (!len)
11110       return 0;
11111 
11112    for (x = 0; x < len; x++)
11113       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11114 
11115    return sum / len;
11116 }
11117 
11118 static void *mwi_thread(void *data)
11119 {
11120    struct mwi_thread_data *mtd = data;
11121    struct callerid_state *cs;
11122    pthread_t threadid;
11123    int samples = 0;
11124    char *name, *number;
11125    int flags;
11126    int i, res;
11127    unsigned int spill_done = 0;
11128    int spill_result = -1;
11129 
11130    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11131       goto quit_no_clean;
11132    }
11133 
11134    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11135 
11136    bump_gains(mtd->pvt);
11137 
11138    for (;;) {
11139       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11140       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11141          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11142          goto quit;
11143       }
11144 
11145       if (i & DAHDI_IOMUX_SIGEVENT) {
11146          struct ast_channel *chan;
11147 
11148          /* If we get an event, screen out events that we do not act on.
11149           * Otherwise, cancel and go to the simple switch to let it deal with it.
11150           */
11151          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11152 
11153          switch (res) {
11154          case DAHDI_EVENT_NEONMWI_ACTIVE:
11155          case DAHDI_EVENT_NEONMWI_INACTIVE:
11156          case DAHDI_EVENT_NONE:
11157          case DAHDI_EVENT_BITSCHANGED:
11158             break;
11159          case DAHDI_EVENT_NOALARM:
11160             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11161                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11162 
11163                analog_p->inalarm = 0;
11164             }
11165             mtd->pvt->inalarm = 0;
11166             handle_clear_alarms(mtd->pvt);
11167             break;
11168          case DAHDI_EVENT_ALARM:
11169             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11170                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11171 
11172                analog_p->inalarm = 1;
11173             }
11174             mtd->pvt->inalarm = 1;
11175             res = get_alarms(mtd->pvt);
11176             handle_alarms(mtd->pvt, res);
11177             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11178          default:
11179             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11180             callerid_free(cs);
11181 
11182             restore_gains(mtd->pvt);
11183             mtd->pvt->ringt = mtd->pvt->ringt_base;
11184 
11185             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11186                int result;
11187 
11188                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11189                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11190                } else {
11191                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11192                }
11193                if (result) {
11194                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11195                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11196                   if (res < 0)
11197                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11198                   ast_hangup(chan);
11199                }
11200             } else {
11201                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11202             }
11203             goto quit_no_clean;
11204          }
11205       } else if (i & DAHDI_IOMUX_READ) {
11206          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11207             if (errno != ELAST) {
11208                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11209                goto quit;
11210             }
11211             break;
11212          }
11213          samples += res;
11214          if (!spill_done) {
11215             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11216                /*
11217                 * The previous diagnostic message output likely
11218                 * explains why it failed.
11219                 */
11220                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11221                break;
11222             } else if (spill_result) {
11223                spill_done = 1;
11224             }
11225          } else {
11226             /* keep reading data until the energy level drops below the threshold
11227                so we don't get another 'trigger' on the remaining carrier signal
11228             */
11229             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11230                break;
11231          }
11232          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11233             break;
11234       }
11235    }
11236 
11237    if (spill_result == 1) {
11238       callerid_get(cs, &name, &number, &flags);
11239       if (flags & CID_MSGWAITING) {
11240          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11241          notify_message(mtd->pvt->mailbox, 1);
11242       } else if (flags & CID_NOMSGWAITING) {
11243          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11244          notify_message(mtd->pvt->mailbox, 0);
11245       } else {
11246          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11247       }
11248    }
11249 
11250 
11251 quit:
11252    callerid_free(cs);
11253 
11254    restore_gains(mtd->pvt);
11255 
11256 quit_no_clean:
11257    mtd->pvt->mwimonitoractive = 0;
11258    ast_free(mtd);
11259 
11260    return NULL;
11261 }
11262 
11263 /*
11264 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11265 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11266 * that are sent out via FXS port on voicemail state change.  The execution of
11267 * the mwi send is state driven and can either generate a ring pulse prior to
11268 * sending the fsk spill or simply send an fsk spill.
11269 */
11270 static int mwi_send_init(struct dahdi_pvt * pvt)
11271 {
11272    int x;
11273 
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275    /* Determine how this spill is to be sent */
11276    if (pvt->mwisend_rpas) {
11277       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11278       pvt->mwisendactive = 1;
11279    } else if (pvt->mwisend_fsk) {
11280       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11281       pvt->mwisendactive = 1;
11282    } else {
11283       pvt->mwisendactive = 0;
11284       return 0;
11285    }
11286 #else
11287    if (mwisend_rpas) {
11288       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11289    } else {
11290       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11291    }
11292    pvt->mwisendactive = 1;
11293 #endif
11294 
11295    if (pvt->cidspill) {
11296       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11297       ast_free(pvt->cidspill);
11298       pvt->cidspill = NULL;
11299       pvt->cidpos = 0;
11300       pvt->cidlen = 0;
11301    }
11302    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11303    if (!pvt->cidspill) {
11304       pvt->mwisendactive = 0;
11305       return -1;
11306    }
11307    x = DAHDI_FLUSH_BOTH;
11308    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11309    x = 3000;
11310    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11311 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11312    if (pvt->mwisend_fsk) {
11313 #endif
11314       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11315                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11316       pvt->cidpos = 0;
11317 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11318    }
11319 #endif
11320    return 0;
11321 }
11322 
11323 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11324 {
11325    struct timeval    now;
11326    int         res;
11327 
11328    /* sanity check to catch if this had been interrupted previously
11329    *  i.e. state says there is more to do but there is no spill allocated
11330    */
11331    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11332       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11333    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11334       /* Normal processing -- Perform mwi send action */
11335       switch ( pvt->mwisend_data.mwisend_current) {
11336       case MWI_SEND_SA:
11337          /* Send the Ring Pulse Signal Alert */
11338          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11339          if (res) {
11340             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11341             goto quit;
11342          }
11343          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11344          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11345          break;
11346       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11347          break;
11348       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11349 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11350          if (pvt->mwisend_fsk) {
11351 #endif
11352             gettimeofday(&now, NULL);
11353             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11354                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11355             }
11356 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11357          } else { /* support for mwisendtype=nofsk */
11358             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11359          }
11360 #endif
11361          break;
11362       case MWI_SEND_SPILL:
11363          /* We read some number of bytes.  Write an equal amount of data */
11364          if(0 < num_read) {
11365             if (num_read > pvt->cidlen - pvt->cidpos)
11366                num_read = pvt->cidlen - pvt->cidpos;
11367             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11368             if (res > 0) {
11369                pvt->cidpos += res;
11370                if (pvt->cidpos >= pvt->cidlen) {
11371                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11372                }
11373             } else {
11374                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11375                goto quit;
11376             }
11377          }
11378          break;
11379       case MWI_SEND_CLEANUP:
11380          /* For now, do nothing */
11381          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11382          break;
11383       default:
11384          /* Should not get here, punt*/
11385          goto quit;
11386       }
11387    }
11388 
11389    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11390       if (pvt->cidspill) {
11391          ast_free(pvt->cidspill);
11392          pvt->cidspill = NULL;
11393          pvt->cidpos = 0;
11394          pvt->cidlen = 0;
11395       }
11396       pvt->mwisendactive = 0;
11397    }
11398    return 0;
11399 quit:
11400    if (pvt->cidspill) {
11401       ast_free(pvt->cidspill);
11402       pvt->cidspill = NULL;
11403       pvt->cidpos = 0;
11404       pvt->cidlen = 0;
11405    }
11406    pvt->mwisendactive = 0;
11407    return -1;
11408 }
11409 
11410 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11411 {
11412    int handled = 0;
11413 
11414    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11415       switch (event) {
11416       case DAHDI_EVENT_RINGEROFF:
11417          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11418             handled = 1;
11419 
11420             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11421                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11422                ast_free(pvt->cidspill);
11423                pvt->cidspill = NULL;
11424                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11425                pvt->mwisendactive = 0;
11426             } else {
11427                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11428                gettimeofday(&pvt->mwisend_data.pause, NULL);
11429             }
11430          }
11431          break;
11432       /* Going off hook, I need to punt this spill */
11433       case DAHDI_EVENT_RINGOFFHOOK:
11434          if (pvt->cidspill) {
11435             ast_free(pvt->cidspill);
11436             pvt->cidspill = NULL;
11437             pvt->cidpos = 0;
11438             pvt->cidlen = 0;
11439          }
11440          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11441          pvt->mwisendactive = 0;
11442          break;
11443       case DAHDI_EVENT_RINGERON:
11444       case DAHDI_EVENT_HOOKCOMPLETE:
11445          break;
11446       default:
11447          break;
11448       }
11449    }
11450    return handled;
11451 }
11452 
11453 /* destroy a DAHDI channel, identified by its number */
11454 static int dahdi_destroy_channel_bynum(int channel)
11455 {
11456    struct dahdi_pvt *cur;
11457 
11458    ast_mutex_lock(&iflock);
11459    for (cur = iflist; cur; cur = cur->next) {
11460       if (cur->channel == channel) {
11461          int x = DAHDI_FLASH;
11462 
11463          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11464          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11465 
11466          destroy_channel(cur, 1);
11467          ast_mutex_unlock(&iflock);
11468          ast_module_unref(ast_module_info->self);
11469          return RESULT_SUCCESS;
11470       }
11471    }
11472    ast_mutex_unlock(&iflock);
11473    return RESULT_FAILURE;
11474 }
11475 
11476 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11477 {
11478    int res;
11479    pthread_t threadid;
11480    struct ast_channel *chan;
11481 
11482    /* Handle an event on a given channel for the monitor thread. */
11483 
11484    switch (event) {
11485    case DAHDI_EVENT_NONE:
11486    case DAHDI_EVENT_BITSCHANGED:
11487       break;
11488    case DAHDI_EVENT_WINKFLASH:
11489    case DAHDI_EVENT_RINGOFFHOOK:
11490       if (i->inalarm) break;
11491       if (i->radio) break;
11492       /* Got a ring/answer.  What kind of channel are we? */
11493       switch (i->sig) {
11494       case SIG_FXOLS:
11495       case SIG_FXOGS:
11496       case SIG_FXOKS:
11497          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11498          if (res && (errno == EBUSY))
11499             break;
11500 
11501          /* Cancel VMWI spill */
11502          ast_free(i->cidspill);
11503          i->cidspill = NULL;
11504          restore_conference(i);
11505 
11506          if (i->immediate) {
11507             dahdi_enable_ec(i);
11508             /* The channel is immediately up.  Start right away */
11509             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11510             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11511             if (!chan) {
11512                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11513                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11514                if (res < 0)
11515                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11516             }
11517          } else {
11518             /* Check for callerid, digits, etc */
11519             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11520             if (chan) {
11521                if (has_voicemail(i))
11522                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11523                else
11524                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11525                if (res < 0)
11526                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11527                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11528                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11529                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11530                   if (res < 0)
11531                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11532                   ast_hangup(chan);
11533                }
11534             } else
11535                ast_log(LOG_WARNING, "Unable to create channel\n");
11536          }
11537          break;
11538       case SIG_FXSLS:
11539       case SIG_FXSGS:
11540       case SIG_FXSKS:
11541             i->ringt = i->ringt_base;
11542             /* Fall through */
11543       case SIG_EMWINK:
11544       case SIG_FEATD:
11545       case SIG_FEATDMF:
11546       case SIG_FEATDMF_TA:
11547       case SIG_E911:
11548       case SIG_FGC_CAMA:
11549       case SIG_FGC_CAMAMF:
11550       case SIG_FEATB:
11551       case SIG_EM:
11552       case SIG_EM_E1:
11553       case SIG_SFWINK:
11554       case SIG_SF_FEATD:
11555       case SIG_SF_FEATDMF:
11556       case SIG_SF_FEATB:
11557       case SIG_SF:
11558          /* Check for callerid, digits, etc */
11559          if (i->cid_start == CID_START_POLARITY_IN) {
11560             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11561          } else {
11562             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11563          }
11564 
11565          if (!chan) {
11566             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11567          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11568             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11569             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11570             if (res < 0) {
11571                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11572             }
11573             ast_hangup(chan);
11574          }
11575          break;
11576       default:
11577          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11578          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11579          if (res < 0)
11580             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11581          return NULL;
11582       }
11583       break;
11584    case DAHDI_EVENT_NOALARM:
11585       switch (i->sig) {
11586 #if defined(HAVE_PRI)
11587       case SIG_PRI_LIB_HANDLE_CASES:
11588          ast_mutex_lock(&i->lock);
11589          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11590          ast_mutex_unlock(&i->lock);
11591          break;
11592 #endif   /* defined(HAVE_PRI) */
11593 #if defined(HAVE_SS7)
11594       case SIG_SS7:
11595          sig_ss7_set_alarm(i->sig_pvt, 0);
11596          break;
11597 #endif   /* defined(HAVE_SS7) */
11598       default:
11599          i->inalarm = 0;
11600          break;
11601       }
11602       handle_clear_alarms(i);
11603       break;
11604    case DAHDI_EVENT_ALARM:
11605       switch (i->sig) {
11606 #if defined(HAVE_PRI)
11607       case SIG_PRI_LIB_HANDLE_CASES:
11608          ast_mutex_lock(&i->lock);
11609          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11610          ast_mutex_unlock(&i->lock);
11611          break;
11612 #endif   /* defined(HAVE_PRI) */
11613 #if defined(HAVE_SS7)
11614       case SIG_SS7:
11615          sig_ss7_set_alarm(i->sig_pvt, 1);
11616          break;
11617 #endif   /* defined(HAVE_SS7) */
11618       default:
11619          i->inalarm = 1;
11620          break;
11621       }
11622       res = get_alarms(i);
11623       handle_alarms(i, res);
11624       /* fall thru intentionally */
11625    case DAHDI_EVENT_ONHOOK:
11626       if (i->radio)
11627          break;
11628       /* Back on hook.  Hang up. */
11629       switch (i->sig) {
11630       case SIG_FXOLS:
11631       case SIG_FXOGS:
11632       case SIG_FEATD:
11633       case SIG_FEATDMF:
11634       case SIG_FEATDMF_TA:
11635       case SIG_E911:
11636       case SIG_FGC_CAMA:
11637       case SIG_FGC_CAMAMF:
11638       case SIG_FEATB:
11639       case SIG_EM:
11640       case SIG_EM_E1:
11641       case SIG_EMWINK:
11642       case SIG_SF_FEATD:
11643       case SIG_SF_FEATDMF:
11644       case SIG_SF_FEATB:
11645       case SIG_SF:
11646       case SIG_SFWINK:
11647       case SIG_FXSLS:
11648       case SIG_FXSGS:
11649       case SIG_FXSKS:
11650       case SIG_FXOKS:
11651          dahdi_disable_ec(i);
11652          /* Diddle the battery for the zhone */
11653 #ifdef ZHONE_HACK
11654          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11655          usleep(1);
11656 #endif
11657          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11658          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11659          break;
11660       case SIG_SS7:
11661       case SIG_PRI_LIB_HANDLE_CASES:
11662          dahdi_disable_ec(i);
11663          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11664          break;
11665       default:
11666          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11667          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11668          return NULL;
11669       }
11670       break;
11671    case DAHDI_EVENT_POLARITY:
11672       switch (i->sig) {
11673       case SIG_FXSLS:
11674       case SIG_FXSKS:
11675       case SIG_FXSGS:
11676          /* We have already got a PR before the channel was
11677             created, but it wasn't handled. We need polarity
11678             to be REV for remote hangup detection to work.
11679             At least in Spain */
11680          if (i->hanguponpolarityswitch)
11681             i->polarity = POLARITY_REV;
11682          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11683             i->polarity = POLARITY_REV;
11684             ast_verb(2, "Starting post polarity "
11685                "CID detection on channel %d\n",
11686                i->channel);
11687             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11688             if (!chan) {
11689                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11690             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11691                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11692                ast_hangup(chan);
11693             }
11694          }
11695          break;
11696       default:
11697          ast_log(LOG_WARNING, "handle_init_event detected "
11698             "polarity reversal on non-FXO (SIG_FXS) "
11699             "interface %d\n", i->channel);
11700       }
11701       break;
11702    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11703       ast_log(LOG_NOTICE,
11704             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11705             i->channel);
11706       return i;
11707    case DAHDI_EVENT_NEONMWI_ACTIVE:
11708       if (i->mwimonitor_neon) {
11709          notify_message(i->mailbox, 1);
11710          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11711       }
11712       break;
11713    case DAHDI_EVENT_NEONMWI_INACTIVE:
11714       if (i->mwimonitor_neon) {
11715          notify_message(i->mailbox, 0);
11716          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11717       }
11718       break;
11719    }
11720    return NULL;
11721 }
11722 
11723 static void *do_monitor(void *data)
11724 {
11725    int count, res, res2, spoint, pollres=0;
11726    struct dahdi_pvt *i;
11727    struct dahdi_pvt *last = NULL;
11728    struct dahdi_pvt *doomed;
11729    time_t thispass = 0, lastpass = 0;
11730    int found;
11731    char buf[1024];
11732    struct pollfd *pfds=NULL;
11733    int lastalloc = -1;
11734    /* This thread monitors all the frame relay interfaces which are not yet in use
11735       (and thus do not have a separate thread) indefinitely */
11736    /* From here on out, we die whenever asked */
11737 #if 0
11738    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11739       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11740       return NULL;
11741    }
11742    ast_debug(1, "Monitor starting...\n");
11743 #endif
11744    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11745 
11746    for (;;) {
11747       /* Lock the interface list */
11748       ast_mutex_lock(&iflock);
11749       if (!pfds || (lastalloc != ifcount)) {
11750          if (pfds) {
11751             ast_free(pfds);
11752             pfds = NULL;
11753          }
11754          if (ifcount) {
11755             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11756                ast_mutex_unlock(&iflock);
11757                return NULL;
11758             }
11759          }
11760          lastalloc = ifcount;
11761       }
11762       /* Build the stuff we're going to poll on, that is the socket of every
11763          dahdi_pvt that does not have an associated owner channel */
11764       count = 0;
11765       for (i = iflist; i; i = i->next) {
11766          ast_mutex_lock(&i->lock);
11767          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11768             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11769                struct analog_pvt *p = i->sig_pvt;
11770 
11771                if (!p) {
11772                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11773                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11774                   /* This needs to be watched, as it lacks an owner */
11775                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11776                   pfds[count].events = POLLPRI;
11777                   pfds[count].revents = 0;
11778                   /* Message waiting or r2 channels also get watched for reading */
11779                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11780                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11781                      pfds[count].events |= POLLIN;
11782                   }
11783                   count++;
11784                }
11785             } else {
11786                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11787                   /* This needs to be watched, as it lacks an owner */
11788                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11789                   pfds[count].events = POLLPRI;
11790                   pfds[count].revents = 0;
11791                   /* If we are monitoring for VMWI or sending CID, we need to
11792                      read from the channel as well */
11793                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11794                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11795                      pfds[count].events |= POLLIN;
11796                   }
11797                   count++;
11798                }
11799             }
11800          }
11801          ast_mutex_unlock(&i->lock);
11802       }
11803       /* Okay, now that we know what to do, release the interface lock */
11804       ast_mutex_unlock(&iflock);
11805 
11806       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11807       pthread_testcancel();
11808       /* Wait at least a second for something to happen */
11809       res = poll(pfds, count, 1000);
11810       pthread_testcancel();
11811       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11812 
11813       /* Okay, poll has finished.  Let's see what happened.  */
11814       if (res < 0) {
11815          if ((errno != EAGAIN) && (errno != EINTR))
11816             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11817          continue;
11818       }
11819       /* Alright, lock the interface list again, and let's look and see what has
11820          happened */
11821       ast_mutex_lock(&iflock);
11822       found = 0;
11823       spoint = 0;
11824       lastpass = thispass;
11825       thispass = time(NULL);
11826       doomed = NULL;
11827       for (i = iflist;; i = i->next) {
11828          if (doomed) {
11829             int res;
11830             res = dahdi_destroy_channel_bynum(doomed->channel);
11831             if (res != RESULT_SUCCESS) {
11832                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11833             }
11834             doomed = NULL;
11835          }
11836          if (!i) {
11837             break;
11838          }
11839 
11840          if (thispass != lastpass) {
11841             if (!found && ((i == last) || ((i == iflist) && !last))) {
11842                last = i;
11843                if (last) {
11844                   struct analog_pvt *analog_p = last->sig_pvt;
11845                   /* Only allow MWI to be initiated on a quiescent fxs port */
11846                   if (analog_p
11847                      && !last->mwisendactive
11848                      && (last->sig & __DAHDI_SIG_FXO)
11849                      && !analog_p->fxsoffhookstate
11850                      && !last->owner
11851                      && !ast_strlen_zero(last->mailbox)
11852                      && (thispass - analog_p->onhooktime > 3)) {
11853                      res = has_voicemail(last);
11854                      if (analog_p->msgstate != res) {
11855                         /* Set driver resources for signalling VMWI */
11856                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11857                         if (res2) {
11858                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11859                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11860                         }
11861                         /* If enabled for FSK spill then initiate it */
11862                         if (mwi_send_init(last)) {
11863                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11864                         }
11865                         analog_p->msgstate = res;
11866                         found ++;
11867                      }
11868                   }
11869                   last = last->next;
11870                }
11871             }
11872          }
11873          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11874             if (i->radio && !i->owner)
11875             {
11876                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11877                if (res)
11878                {
11879                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11880                   /* Don't hold iflock while handling init events */
11881                   ast_mutex_unlock(&iflock);
11882                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11883                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11884                   else
11885                      doomed = handle_init_event(i, res);
11886                   ast_mutex_lock(&iflock);
11887                }
11888                continue;
11889             }
11890             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11891             if (pollres & POLLIN) {
11892                if (i->owner || i->subs[SUB_REAL].owner) {
11893 #ifdef HAVE_PRI
11894                   if (!i->pri)
11895 #endif
11896                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11897                   continue;
11898                }
11899                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11900                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11901                   continue;
11902                }
11903                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11904                if (res > 0) {
11905                   if (i->mwimonitor_fsk) {
11906                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11907                         pthread_attr_t attr;
11908                         pthread_t threadid;
11909                         struct mwi_thread_data *mtd;
11910 
11911                         pthread_attr_init(&attr);
11912                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11913 
11914                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11915                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11916                            mtd->pvt = i;
11917                            memcpy(mtd->buf, buf, res);
11918                            mtd->len = res;
11919                            i->mwimonitoractive = 1;
11920                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11921                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11922                               i->mwimonitoractive = 0;
11923                               ast_free(mtd);
11924                            }
11925                         }
11926                      }
11927                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11928                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11929                      int energy;
11930                      struct timeval now;
11931                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11932                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11933                      */
11934                      if (1 == i->dtmfcid_holdoff_state) {
11935                         gettimeofday(&i->dtmfcid_delay, NULL);
11936                         i->dtmfcid_holdoff_state = 2;
11937                      } else if (2 == i->dtmfcid_holdoff_state) {
11938                         gettimeofday(&now, NULL);
11939                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11940                            i->dtmfcid_holdoff_state = 0;
11941                         }
11942                      } else {
11943                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11944                         if (!i->mwisendactive && energy > dtmfcid_level) {
11945                            pthread_t threadid;
11946                            struct ast_channel *chan;
11947                            ast_mutex_unlock(&iflock);
11948                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11949                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11950                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11951                               i->dtmfcid_holdoff_state = 1;
11952                            } else {
11953                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11954                               if (!chan) {
11955                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11956                               } else {
11957                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11958                                  if (res) {
11959                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11960                                     ast_hangup(chan);
11961                                  } else {
11962                                     i->dtmfcid_holdoff_state = 1;
11963                                  }
11964                               }
11965                            }
11966                            ast_mutex_lock(&iflock);
11967                         }
11968                      }
11969                   }
11970                   if (i->mwisendactive) {
11971                      mwi_send_process_buffer(i, res);
11972                   }
11973                } else {
11974                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11975                }
11976             }
11977             if (pollres & POLLPRI) {
11978                if (i->owner || i->subs[SUB_REAL].owner) {
11979 #ifdef HAVE_PRI
11980                   if (!i->pri)
11981 #endif
11982                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11983                   continue;
11984                }
11985                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11986                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11987                /* Don't hold iflock while handling init events */
11988                ast_mutex_unlock(&iflock);
11989                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11990                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11991                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11992                   else
11993                      doomed = handle_init_event(i, res);
11994                }
11995                ast_mutex_lock(&iflock);
11996             }
11997          }
11998       }
11999       ast_mutex_unlock(&iflock);
12000    }
12001    /* Never reached */
12002    return NULL;
12003 
12004 }
12005 
12006 static int restart_monitor(void)
12007 {
12008    /* If we're supposed to be stopped -- stay stopped */
12009    if (monitor_thread == AST_PTHREADT_STOP)
12010       return 0;
12011    ast_mutex_lock(&monlock);
12012    if (monitor_thread == pthread_self()) {
12013       ast_mutex_unlock(&monlock);
12014       ast_log(LOG_WARNING, "Cannot kill myself\n");
12015       return -1;
12016    }
12017    if (monitor_thread != AST_PTHREADT_NULL) {
12018       /* Wake up the thread */
12019       pthread_kill(monitor_thread, SIGURG);
12020    } else {
12021       /* Start a new monitor */
12022       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12023          ast_mutex_unlock(&monlock);
12024          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12025          return -1;
12026       }
12027    }
12028    ast_mutex_unlock(&monlock);
12029    return 0;
12030 }
12031 
12032 #if defined(HAVE_PRI)
12033 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12034 {
12035    int x;
12036    int trunkgroup;
12037    /* Get appropriate trunk group if there is one */
12038    trunkgroup = pris[*span].mastertrunkgroup;
12039    if (trunkgroup) {
12040       /* Select a specific trunk group */
12041       for (x = 0; x < NUM_SPANS; x++) {
12042          if (pris[x].pri.trunkgroup == trunkgroup) {
12043             *span = x;
12044             return 0;
12045          }
12046       }
12047       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12048       *span = -1;
12049    } else {
12050       if (pris[*span].pri.trunkgroup) {
12051          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);
12052          *span = -1;
12053       } else if (pris[*span].mastertrunkgroup) {
12054          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12055          *span = -1;
12056       } else {
12057          if (si->totalchans == 31) {
12058             /* E1 */
12059             pris[*span].dchannels[0] = 16 + offset;
12060          } else if (si->totalchans == 24) {
12061             /* T1 or J1 */
12062             pris[*span].dchannels[0] = 24 + offset;
12063          } else if (si->totalchans == 3) {
12064             /* BRI */
12065             pris[*span].dchannels[0] = 3 + offset;
12066          } else {
12067             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);
12068             *span = -1;
12069             return 0;
12070          }
12071          pris[*span].pri.span = *span + 1;
12072       }
12073    }
12074    return 0;
12075 }
12076 #endif   /* defined(HAVE_PRI) */
12077 
12078 #if defined(HAVE_PRI)
12079 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12080 {
12081    struct dahdi_spaninfo si;
12082    struct dahdi_params p;
12083    int fd;
12084    int span;
12085    int ospan=0;
12086    int x,y;
12087    for (x = 0; x < NUM_SPANS; x++) {
12088       if (pris[x].pri.trunkgroup == trunkgroup) {
12089          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12090          return -1;
12091       }
12092    }
12093    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12094       if (!channels[y])
12095          break;
12096       memset(&si, 0, sizeof(si));
12097       memset(&p, 0, sizeof(p));
12098       fd = open("/dev/dahdi/channel", O_RDWR);
12099       if (fd < 0) {
12100          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12101          return -1;
12102       }
12103       x = channels[y];
12104       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12105          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12106          close(fd);
12107          return -1;
12108       }
12109       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12110          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12111          return -1;
12112       }
12113       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12114          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12115          close(fd);
12116          return -1;
12117       }
12118       span = p.spanno - 1;
12119       if (pris[span].pri.trunkgroup) {
12120          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12121          close(fd);
12122          return -1;
12123       }
12124       if (pris[span].pri.pvts[0]) {
12125          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12126          close(fd);
12127          return -1;
12128       }
12129       if (!y) {
12130          pris[span].pri.trunkgroup = trunkgroup;
12131          ospan = span;
12132       }
12133       pris[ospan].dchannels[y] = channels[y];
12134       pris[span].pri.span = span + 1;
12135       close(fd);
12136    }
12137    return 0;
12138 }
12139 #endif   /* defined(HAVE_PRI) */
12140 
12141 #if defined(HAVE_PRI)
12142 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12143 {
12144    if (pris[span].mastertrunkgroup) {
12145       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);
12146       return -1;
12147    }
12148    pris[span].mastertrunkgroup = trunkgroup;
12149    pris[span].prilogicalspan = logicalspan;
12150    return 0;
12151 }
12152 #endif   /* defined(HAVE_PRI) */
12153 
12154 #if defined(HAVE_SS7)
12155 static unsigned int parse_pointcode(const char *pcstring)
12156 {
12157    unsigned int code1, code2, code3;
12158    int numvals;
12159 
12160    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12161    if (numvals == 1)
12162       return code1;
12163    if (numvals == 3)
12164       return (code1 << 16) | (code2 << 8) | code3;
12165 
12166    return 0;
12167 }
12168 #endif   /* defined(HAVE_SS7) */
12169 
12170 #if defined(HAVE_SS7)
12171 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12172 {
12173    if ((linkset < 0) || (linkset >= NUM_SPANS))
12174       return NULL;
12175    else
12176       return &linksets[linkset - 1];
12177 }
12178 #endif   /* defined(HAVE_SS7) */
12179 
12180 #ifdef HAVE_OPENR2
12181 static void dahdi_r2_destroy_links(void)
12182 {
12183    int i = 0;
12184    if (!r2links) {
12185       return;
12186    }
12187    for (; i < r2links_count; i++) {
12188       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12189          pthread_cancel(r2links[i]->r2master);
12190          pthread_join(r2links[i]->r2master, NULL);
12191          openr2_context_delete(r2links[i]->protocol_context);
12192       }
12193       ast_free(r2links[i]);
12194    }
12195    ast_free(r2links);
12196    r2links = NULL;
12197    r2links_count = 0;
12198 }
12199 
12200 #define R2_LINK_CAPACITY 10
12201 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12202 {
12203    struct dahdi_mfcr2 *new_r2link = NULL;
12204    struct dahdi_mfcr2 **new_r2links = NULL;
12205    /* this function is called just when starting up and no monitor threads have been launched,
12206       no need to lock monitored_count member */
12207    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12208       new_r2link = ast_calloc(1, sizeof(**r2links));
12209       if (!new_r2link) {
12210          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12211          return NULL;
12212       }
12213       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12214       if (!new_r2links) {
12215          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12216          ast_free(new_r2link);
12217          return NULL;
12218       }
12219       r2links = new_r2links;
12220       new_r2link->r2master = AST_PTHREADT_NULL;
12221       r2links[r2links_count] = new_r2link;
12222       r2links_count++;
12223       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12224    }
12225    return r2links[r2links_count - 1];
12226 }
12227 
12228 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12229 {
12230    char tmplogdir[] = "/tmp";
12231    char logdir[OR2_MAX_PATH];
12232    int threshold = 0;
12233    int snres = 0;
12234    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12235          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12236          conf->mfcr2.max_dnis);
12237    if (!r2_link->protocol_context) {
12238       return -1;
12239    }
12240    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12241    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12243    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12244 #endif
12245    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12246    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12247    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12248    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12249    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12250    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12251       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12252          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12253       }
12254    } else {
12255       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12256       if (snres >= sizeof(logdir)) {
12257          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12258          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12259             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12260          }
12261       } else {
12262          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12263             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12264          }
12265       }
12266    }
12267    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12268       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12269          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12270       }
12271    }
12272    r2_link->monitored_count = 0;
12273    return 0;
12274 }
12275 #endif
12276 
12277 /* converts a DAHDI sigtype to signalling as can be configured from
12278  * chan_dahdi.conf.
12279  * While both have basically the same values, this will later be the
12280  * place to add filters and sanity checks
12281  */
12282 static int sigtype_to_signalling(int sigtype)
12283 {
12284    return sigtype;
12285 }
12286 
12287 /*!
12288  * \internal
12289  * \brief Get file name and channel number from (subdir,number)
12290  *
12291  * \param subdir name of the subdirectory under /dev/dahdi/
12292  * \param channel name of device file under /dev/dahdi/<subdir>/
12293  * \param path buffer to put file name in
12294  * \param pathlen maximal length of path
12295  *
12296  * \retval minor number of dahdi channel.
12297  * \retval -errno on error.
12298  */
12299 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12300 {
12301    struct stat stbuf;
12302    int      num;
12303 
12304    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12305    if (stat(path, &stbuf) < 0) {
12306       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12307       return -errno;
12308    }
12309    if (!S_ISCHR(stbuf.st_mode)) {
12310       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12311       return -EINVAL;
12312    }
12313    num = minor(stbuf.st_rdev);
12314    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12315    return num;
12316 
12317 }
12318 
12319 /*!
12320  * \internal
12321  * \brief Initialize/create a channel interface.
12322  *
12323  * \param channel Channel interface number to initialize/create.
12324  * \param conf Configuration parameters to initialize interface with.
12325  * \param reloading What we are doing now:
12326  * 0 - initial module load,
12327  * 1 - module reload,
12328  * 2 - module restart
12329  *
12330  * \retval Interface-pointer initialized/created
12331  * \retval NULL if error
12332  */
12333 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12334 {
12335    /* Make a dahdi_pvt structure for this interface */
12336    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12337    char fn[80];
12338    struct dahdi_bufferinfo bi;
12339 
12340    int res;
12341 #if defined(HAVE_PRI)
12342    int span = 0;
12343 #endif   /* defined(HAVE_PRI) */
12344    int here = 0;/*!< TRUE if the channel interface already exists. */
12345    int x;
12346    struct analog_pvt *analog_p = NULL;
12347    struct dahdi_params p;
12348 #if defined(HAVE_PRI)
12349    struct dahdi_spaninfo si;
12350    struct sig_pri_chan *pri_chan = NULL;
12351 #endif   /* defined(HAVE_PRI) */
12352 #if defined(HAVE_SS7)
12353    struct sig_ss7_chan *ss7_chan = NULL;
12354 #endif   /* defined(HAVE_SS7) */
12355 
12356    /* Search channel interface list to see if it already exists. */
12357    for (tmp = iflist; tmp; tmp = tmp->next) {
12358       if (!tmp->destroy) {
12359          if (tmp->channel == channel) {
12360             /* The channel interface already exists. */
12361             here = 1;
12362             break;
12363          }
12364          if (tmp->channel > channel) {
12365             /* No way it can be in the sorted list. */
12366             tmp = NULL;
12367             break;
12368          }
12369       }
12370    }
12371 
12372    if (!here && reloading != 1) {
12373       tmp = ast_calloc(1, sizeof(*tmp));
12374       if (!tmp) {
12375          return NULL;
12376       }
12377       tmp->cc_params = ast_cc_config_params_init();
12378       if (!tmp->cc_params) {
12379          ast_free(tmp);
12380          return NULL;
12381       }
12382       ast_mutex_init(&tmp->lock);
12383       ifcount++;
12384       for (x = 0; x < 3; x++)
12385          tmp->subs[x].dfd = -1;
12386       tmp->channel = channel;
12387       tmp->priindication_oob = conf->chan.priindication_oob;
12388    }
12389 
12390    if (tmp) {
12391       int chan_sig = conf->chan.sig;
12392 
12393       /* If there are variables in tmp before it is updated to match the new config, clear them */
12394       if (reloading && tmp->vars) {
12395          ast_variables_destroy(tmp->vars);
12396          tmp->vars = NULL;
12397       }
12398 
12399 
12400       if (!here) {
12401          /* Can only get here if this is a new channel interface being created. */
12402          if ((channel != CHAN_PSEUDO)) {
12403             int count = 0;
12404 
12405             snprintf(fn, sizeof(fn), "%d", channel);
12406             /* Open non-blocking */
12407             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12408             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 */
12409                usleep(1);
12410                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12411                count++;
12412             }
12413             /* Allocate a DAHDI structure */
12414             if (tmp->subs[SUB_REAL].dfd < 0) {
12415                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);
12416                destroy_dahdi_pvt(tmp);
12417                return NULL;
12418             }
12419             memset(&p, 0, sizeof(p));
12420             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12421             if (res < 0) {
12422                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12423                destroy_dahdi_pvt(tmp);
12424                return NULL;
12425             }
12426             if (conf->is_sig_auto)
12427                chan_sig = sigtype_to_signalling(p.sigtype);
12428             if (p.sigtype != (chan_sig & 0x3ffff)) {
12429                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));
12430                destroy_dahdi_pvt(tmp);
12431                return NULL;
12432             }
12433             tmp->law_default = p.curlaw;
12434             tmp->law = p.curlaw;
12435             tmp->span = p.spanno;
12436 #if defined(HAVE_PRI)
12437             span = p.spanno - 1;
12438 #endif   /* defined(HAVE_PRI) */
12439          } else {
12440             chan_sig = 0;
12441          }
12442          tmp->sig = chan_sig;
12443          tmp->outsigmod = conf->chan.outsigmod;
12444 
12445          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12446             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12447             if (!analog_p) {
12448                destroy_dahdi_pvt(tmp);
12449                return NULL;
12450             }
12451             tmp->sig_pvt = analog_p;
12452          }
12453 #if defined(HAVE_SS7)
12454          if (chan_sig == SIG_SS7) {
12455             struct dahdi_ss7 *ss7;
12456             int clear = 0;
12457 
12458             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12459                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12460                destroy_dahdi_pvt(tmp);
12461                return NULL;
12462             }
12463 
12464             ss7 = ss7_resolve_linkset(cur_linkset);
12465             if (!ss7) {
12466                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12467                destroy_dahdi_pvt(tmp);
12468                return NULL;
12469             }
12470             ss7->ss7.span = cur_linkset;
12471             if (cur_cicbeginswith < 0) {
12472                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12473                destroy_dahdi_pvt(tmp);
12474                return NULL;
12475             }
12476             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12477             if (!ss7_chan) {
12478                destroy_dahdi_pvt(tmp);
12479                return NULL;
12480             }
12481             tmp->sig_pvt = ss7_chan;
12482             tmp->ss7 = &ss7->ss7;
12483 
12484             ss7_chan->channel = tmp->channel;
12485             ss7_chan->cic = cur_cicbeginswith++;
12486 
12487             /* DB: Add CIC's DPC information */
12488             ss7_chan->dpc = cur_defaultdpc;
12489 
12490             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12491 
12492             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12493             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12494             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12495             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12496 
12497             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12498             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12499          }
12500 #endif   /* defined(HAVE_SS7) */
12501 #ifdef HAVE_OPENR2
12502          if (chan_sig == SIG_MFCR2) {
12503             struct dahdi_mfcr2 *r2_link;
12504             r2_link = dahdi_r2_get_link();
12505             if (!r2_link) {
12506                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12507                destroy_dahdi_pvt(tmp);
12508                return NULL;
12509             }
12510             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12511                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12512                destroy_dahdi_pvt(tmp);
12513                return NULL;
12514             }
12515             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12516                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12517                destroy_dahdi_pvt(tmp);
12518                return NULL;
12519             }
12520             r2_link->pvts[r2_link->numchans++] = tmp;
12521             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12522                                         tmp->subs[SUB_REAL].dfd,
12523                                         NULL, NULL);
12524             if (!tmp->r2chan) {
12525                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12526                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12527                destroy_dahdi_pvt(tmp);
12528                return NULL;
12529             }
12530             tmp->mfcr2 = r2_link;
12531             if (conf->mfcr2.call_files) {
12532                openr2_chan_enable_call_files(tmp->r2chan);
12533             }
12534             openr2_chan_set_client_data(tmp->r2chan, tmp);
12535             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12536             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12537             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12538             tmp->mfcr2_category = conf->mfcr2.category;
12539             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12540             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12541             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12542             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12543             tmp->mfcr2call = 0;
12544             tmp->mfcr2_dnis_index = 0;
12545             tmp->mfcr2_ani_index = 0;
12546             r2_link->monitored_count++;
12547          }
12548 #endif
12549 #ifdef HAVE_PRI
12550          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12551             int offset;
12552             int matchesdchan;
12553             int x,y;
12554             int myswitchtype = 0;
12555 
12556             offset = 0;
12557             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12558                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12559                destroy_dahdi_pvt(tmp);
12560                return NULL;
12561             }
12562             if (span >= NUM_SPANS) {
12563                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12564                destroy_dahdi_pvt(tmp);
12565                return NULL;
12566             } else {
12567                si.spanno = 0;
12568                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12569                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12570                   destroy_dahdi_pvt(tmp);
12571                   return NULL;
12572                }
12573                /* Store the logical span first based upon the real span */
12574                tmp->logicalspan = pris[span].prilogicalspan;
12575                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12576                if (span < 0) {
12577                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12578                   destroy_dahdi_pvt(tmp);
12579                   return NULL;
12580                }
12581                myswitchtype = conf->pri.pri.switchtype;
12582                /* Make sure this isn't a d-channel */
12583                matchesdchan=0;
12584                for (x = 0; x < NUM_SPANS; x++) {
12585                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12586                      if (pris[x].dchannels[y] == tmp->channel) {
12587                         matchesdchan = 1;
12588                         break;
12589                      }
12590                   }
12591                }
12592                if (!matchesdchan) {
12593                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12594                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12595                      destroy_dahdi_pvt(tmp);
12596                      return NULL;
12597                   }
12598                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12599                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12600                      destroy_dahdi_pvt(tmp);
12601                      return NULL;
12602                   }
12603                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12604                      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));
12605                      destroy_dahdi_pvt(tmp);
12606                      return NULL;
12607                   }
12608                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12609                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12610                      destroy_dahdi_pvt(tmp);
12611                      return NULL;
12612                   }
12613                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12614                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12615                      destroy_dahdi_pvt(tmp);
12616                      return NULL;
12617                   }
12618                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12619                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12620                      destroy_dahdi_pvt(tmp);
12621                      return NULL;
12622                   }
12623                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12624                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12625                      destroy_dahdi_pvt(tmp);
12626                      return NULL;
12627                   }
12628                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12629                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12630                         pris[span].pri.trunkgroup);
12631                      destroy_dahdi_pvt(tmp);
12632                      return NULL;
12633                   }
12634 
12635                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12636                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12637                   if (!pri_chan) {
12638                      destroy_dahdi_pvt(tmp);
12639                      return NULL;
12640                   }
12641                   tmp->sig_pvt = pri_chan;
12642                   tmp->pri = &pris[span].pri;
12643 
12644                   tmp->priexclusive = conf->chan.priexclusive;
12645 
12646                   if (!tmp->pri->cc_params) {
12647                      tmp->pri->cc_params = ast_cc_config_params_init();
12648                      if (!tmp->pri->cc_params) {
12649                         destroy_dahdi_pvt(tmp);
12650                         return NULL;
12651                      }
12652                   }
12653                   ast_cc_copy_config_params(tmp->pri->cc_params,
12654                      conf->chan.cc_params);
12655 
12656                   pris[span].pri.sig = chan_sig;
12657                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12658                   pris[span].pri.switchtype = myswitchtype;
12659                   pris[span].pri.nsf = conf->pri.pri.nsf;
12660                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12661                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12662                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12663                   pris[span].pri.minunused = conf->pri.pri.minunused;
12664                   pris[span].pri.minidle = conf->pri.pri.minidle;
12665                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12666                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12667                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12668 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12669                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12670 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12671 #ifdef HAVE_PRI_INBANDDISCONNECT
12672                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12673 #endif
12674 #if defined(HAVE_PRI_CALL_HOLD)
12675                   pris[span].pri.hold_disconnect_transfer =
12676                      conf->pri.pri.hold_disconnect_transfer;
12677 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12678 #if defined(HAVE_PRI_CCSS)
12679                   pris[span].pri.cc_ptmp_recall_mode =
12680                      conf->pri.pri.cc_ptmp_recall_mode;
12681                   pris[span].pri.cc_qsig_signaling_link_req =
12682                      conf->pri.pri.cc_qsig_signaling_link_req;
12683                   pris[span].pri.cc_qsig_signaling_link_rsp =
12684                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12685 #endif   /* defined(HAVE_PRI_CCSS) */
12686 #if defined(HAVE_PRI_CALL_WAITING)
12687                   pris[span].pri.max_call_waiting_calls =
12688                      conf->pri.pri.max_call_waiting_calls;
12689                   pris[span].pri.allow_call_waiting_calls =
12690                      conf->pri.pri.allow_call_waiting_calls;
12691 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12692                   pris[span].pri.transfer = conf->chan.transfer;
12693                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12694 #if defined(HAVE_PRI_L2_PERSISTENCE)
12695                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12696 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12697 #if defined(HAVE_PRI_AOC_EVENTS)
12698                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12699                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12700 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12701                   if (chan_sig == SIG_BRI_PTMP) {
12702                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12703                   } else {
12704                      /* Option does not apply to this line type. */
12705                      pris[span].pri.layer1_ignored = 0;
12706                   }
12707                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12708                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12709                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12710 #if defined(HAVE_PRI_MWI)
12711                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12712                      conf->pri.pri.mwi_mailboxes,
12713                      sizeof(pris[span].pri.mwi_mailboxes));
12714 #endif   /* defined(HAVE_PRI_MWI) */
12715                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12716                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12717                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12718                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12719                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12720                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12721                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12722                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12723 
12724                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12725                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12726                   }
12727 
12728 #if defined(HAVE_PRI_CALL_WAITING)
12729                   /* Channel initial config parameters. */
12730                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12731                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12732                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12733                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12734                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12735                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12736                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12737                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12738                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12739                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12740 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12741                } else {
12742                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12743                   destroy_dahdi_pvt(tmp);
12744                   return NULL;
12745                }
12746             }
12747          }
12748 #endif
12749       } else {
12750          /* already exists in interface list */
12751          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));
12752          chan_sig = tmp->sig;
12753          if (tmp->subs[SUB_REAL].dfd > -1) {
12754             memset(&p, 0, sizeof(p));
12755             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12756          }
12757       }
12758       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12759       switch (chan_sig) {
12760       case SIG_FXSKS:
12761       case SIG_FXSLS:
12762       case SIG_EM:
12763       case SIG_EM_E1:
12764       case SIG_EMWINK:
12765       case SIG_FEATD:
12766       case SIG_FEATDMF:
12767       case SIG_FEATDMF_TA:
12768       case SIG_FEATB:
12769       case SIG_E911:
12770       case SIG_SF:
12771       case SIG_SFWINK:
12772       case SIG_FGC_CAMA:
12773       case SIG_FGC_CAMAMF:
12774       case SIG_SF_FEATD:
12775       case SIG_SF_FEATDMF:
12776       case SIG_SF_FEATB:
12777          p.starttime = 250;
12778          break;
12779       }
12780 
12781       if (tmp->radio) {
12782          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12783          p.channo = channel;
12784          p.rxwinktime = 1;
12785          p.rxflashtime = 1;
12786          p.starttime = 1;
12787          p.debouncetime = 5;
12788       } else {
12789          p.channo = channel;
12790          /* Override timing settings based on config file */
12791          if (conf->timing.prewinktime >= 0)
12792             p.prewinktime = conf->timing.prewinktime;
12793          if (conf->timing.preflashtime >= 0)
12794             p.preflashtime = conf->timing.preflashtime;
12795          if (conf->timing.winktime >= 0)
12796             p.winktime = conf->timing.winktime;
12797          if (conf->timing.flashtime >= 0)
12798             p.flashtime = conf->timing.flashtime;
12799          if (conf->timing.starttime >= 0)
12800             p.starttime = conf->timing.starttime;
12801          if (conf->timing.rxwinktime >= 0)
12802             p.rxwinktime = conf->timing.rxwinktime;
12803          if (conf->timing.rxflashtime >= 0)
12804             p.rxflashtime = conf->timing.rxflashtime;
12805          if (conf->timing.debouncetime >= 0)
12806             p.debouncetime = conf->timing.debouncetime;
12807       }
12808 
12809       /* don't set parms on a pseudo-channel */
12810       if (tmp->subs[SUB_REAL].dfd >= 0)
12811       {
12812          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12813          if (res < 0) {
12814             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12815             destroy_dahdi_pvt(tmp);
12816             return NULL;
12817          }
12818       }
12819 #if 1
12820       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12821          memset(&bi, 0, sizeof(bi));
12822          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12823          if (!res) {
12824             bi.txbufpolicy = conf->chan.buf_policy;
12825             bi.rxbufpolicy = conf->chan.buf_policy;
12826             bi.numbufs = conf->chan.buf_no;
12827             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12828             if (res < 0) {
12829                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12830             }
12831          } else {
12832             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12833          }
12834          tmp->buf_policy = conf->chan.buf_policy;
12835          tmp->buf_no = conf->chan.buf_no;
12836          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12837          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12838          tmp->faxbuf_no = conf->chan.faxbuf_no;
12839          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12840           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12841           * The reason the ioctl call above failed should to be determined before worrying about the
12842           * faxbuffer-related ioctl calls */
12843          tmp->bufsize = bi.bufsize;
12844       }
12845 #endif
12846       tmp->immediate = conf->chan.immediate;
12847       tmp->transfertobusy = conf->chan.transfertobusy;
12848       if (chan_sig & __DAHDI_SIG_FXS) {
12849          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12850          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12851          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12852       }
12853       tmp->ringt_base = ringt_base;
12854       tmp->firstradio = 0;
12855       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12856          tmp->permcallwaiting = conf->chan.callwaiting;
12857       else
12858          tmp->permcallwaiting = 0;
12859       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12860       tmp->destroy = 0;
12861       tmp->drings = conf->chan.drings;
12862 
12863       /* 10 is a nice default. */
12864       if (tmp->drings.ringnum[0].range == 0)
12865          tmp->drings.ringnum[0].range = 10;
12866       if (tmp->drings.ringnum[1].range == 0)
12867          tmp->drings.ringnum[1].range = 10;
12868       if (tmp->drings.ringnum[2].range == 0)
12869          tmp->drings.ringnum[2].range = 10;
12870 
12871       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12872       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12873       tmp->threewaycalling = conf->chan.threewaycalling;
12874       tmp->adsi = conf->chan.adsi;
12875       tmp->use_smdi = conf->chan.use_smdi;
12876       tmp->permhidecallerid = conf->chan.hidecallerid;
12877       tmp->hidecalleridname = conf->chan.hidecalleridname;
12878       tmp->callreturn = conf->chan.callreturn;
12879       tmp->echocancel = conf->chan.echocancel;
12880       tmp->echotraining = conf->chan.echotraining;
12881       tmp->pulse = conf->chan.pulse;
12882       if (tmp->echocancel.head.tap_length) {
12883          tmp->echocanbridged = conf->chan.echocanbridged;
12884       } else {
12885          if (conf->chan.echocanbridged)
12886             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12887          tmp->echocanbridged = 0;
12888       }
12889       tmp->busydetect = conf->chan.busydetect;
12890       tmp->busycount = conf->chan.busycount;
12891       tmp->busycompare = conf->chan.busycompare;
12892       tmp->busytonelength = conf->chan.busytonelength;
12893       tmp->busyquietlength = conf->chan.busyquietlength;
12894       tmp->busyfuzziness = conf->chan.busyfuzziness;
12895       tmp->silencethreshold = conf->chan.silencethreshold;
12896       tmp->callprogress = conf->chan.callprogress;
12897       tmp->waitfordialtone = conf->chan.waitfordialtone;
12898       tmp->cancallforward = conf->chan.cancallforward;
12899       tmp->dtmfrelax = conf->chan.dtmfrelax;
12900       tmp->callwaiting = tmp->permcallwaiting;
12901       tmp->hidecallerid = tmp->permhidecallerid;
12902       tmp->channel = channel;
12903       tmp->stripmsd = conf->chan.stripmsd;
12904       tmp->use_callerid = conf->chan.use_callerid;
12905       tmp->cid_signalling = conf->chan.cid_signalling;
12906       tmp->cid_start = conf->chan.cid_start;
12907       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12908       tmp->restrictcid = conf->chan.restrictcid;
12909       tmp->use_callingpres = conf->chan.use_callingpres;
12910       if (tmp->usedistinctiveringdetection) {
12911          if (!tmp->use_callerid) {
12912             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12913             tmp->use_callerid = 1;
12914          }
12915       }
12916 
12917       if (tmp->cid_signalling == CID_SIG_SMDI) {
12918          if (!tmp->use_smdi) {
12919             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12920             tmp->use_smdi = 1;
12921          }
12922       }
12923       if (tmp->use_smdi) {
12924          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12925          if (!(tmp->smdi_iface)) {
12926             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12927             tmp->use_smdi = 0;
12928          }
12929       }
12930 
12931       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12932       tmp->amaflags = conf->chan.amaflags;
12933       if (!here) {
12934          tmp->confno = -1;
12935          tmp->propconfno = -1;
12936       }
12937       tmp->canpark = conf->chan.canpark;
12938       tmp->transfer = conf->chan.transfer;
12939       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12940       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12941       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12942       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12943       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12944       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12945       tmp->cid_ton = 0;
12946       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12947          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12948          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12949       } else {
12950          tmp->cid_num[0] = '\0';
12951          tmp->cid_name[0] = '\0';
12952       }
12953 #if defined(HAVE_PRI)
12954       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12955          tmp->cid_tag[0] = '\0';
12956       } else
12957 #endif   /* defined(HAVE_PRI) */
12958       {
12959          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12960       }
12961       tmp->cid_subaddr[0] = '\0';
12962       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12963       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12964          char *mailbox, *context;
12965          mailbox = context = ast_strdupa(tmp->mailbox);
12966          strsep(&context, "@");
12967          if (ast_strlen_zero(context))
12968             context = "default";
12969          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12970             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12971             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12972             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12973             AST_EVENT_IE_END);
12974       }
12975 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12976       tmp->mwisend_setting = conf->chan.mwisend_setting;
12977       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12978       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12979 #endif
12980 
12981       tmp->group = conf->chan.group;
12982       tmp->callgroup = conf->chan.callgroup;
12983       tmp->pickupgroup= conf->chan.pickupgroup;
12984       if (conf->chan.vars) {
12985          struct ast_variable *v, *tmpvar;
12986                    for (v = conf->chan.vars ; v ; v = v->next) {
12987                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12988                                   tmpvar->next = tmp->vars;
12989                                    tmp->vars = tmpvar;
12990                            }
12991                   }
12992       }
12993       tmp->cid_rxgain = conf->chan.cid_rxgain;
12994       tmp->rxgain = conf->chan.rxgain;
12995       tmp->txgain = conf->chan.txgain;
12996       tmp->txdrc = conf->chan.txdrc;
12997       tmp->rxdrc = conf->chan.rxdrc;
12998       tmp->tonezone = conf->chan.tonezone;
12999       if (tmp->subs[SUB_REAL].dfd > -1) {
13000          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13001          if (tmp->dsp)
13002             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13003          update_conf(tmp);
13004          if (!here) {
13005             switch (chan_sig) {
13006             case SIG_PRI_LIB_HANDLE_CASES:
13007             case SIG_SS7:
13008             case SIG_MFCR2:
13009                break;
13010             default:
13011                /* Hang it up to be sure it's good */
13012                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13013                break;
13014             }
13015          }
13016          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13017          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13018             /* the dchannel is down so put the channel in alarm */
13019             switch (tmp->sig) {
13020 #ifdef HAVE_PRI
13021             case SIG_PRI_LIB_HANDLE_CASES:
13022                sig_pri_set_alarm(tmp->sig_pvt, 1);
13023                break;
13024 #endif
13025 #if defined(HAVE_SS7)
13026             case SIG_SS7:
13027                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13028                break;
13029 #endif   /* defined(HAVE_SS7) */
13030             default:
13031                /* The only sig submodule left should be sig_analog. */
13032                analog_p = tmp->sig_pvt;
13033                if (analog_p) {
13034                   analog_p->inalarm = 1;
13035                }
13036                tmp->inalarm = 1;
13037                break;
13038             }
13039             handle_alarms(tmp, res);
13040          }
13041       }
13042 
13043       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13044       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13045       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13046       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13047       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13048 
13049       if (!here) {
13050          tmp->locallyblocked = 0;
13051          tmp->remotelyblocked = 0;
13052          switch (tmp->sig) {
13053 #if defined(HAVE_PRI)
13054          case SIG_PRI_LIB_HANDLE_CASES:
13055             tmp->inservice = 1;/* Inservice until actually implemented. */
13056 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13057             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13058             if (chan_sig == SIG_PRI) {
13059                char db_chan_name[20];
13060                char db_answer[5];
13061 
13062                /*
13063                 * Initialize the active out-of-service status
13064                 * and delete any record if the feature is not enabled.
13065                 */
13066                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13067                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13068                   unsigned *why;
13069 
13070                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13071                   if (tmp->pri->enable_service_message_support) {
13072                      char state;
13073 
13074                      sscanf(db_answer, "%1c:%30u", &state, why);
13075 
13076                      /* Ensure that only the implemented bits could be set.*/
13077                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13078                   }
13079                   if (!*why) {
13080                      ast_db_del(db_chan_name, SRVST_DBKEY);
13081                   }
13082                }
13083             }
13084 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13085             break;
13086 #endif   /* defined(HAVE_PRI) */
13087 #if defined(HAVE_SS7)
13088          case SIG_SS7:
13089             tmp->inservice = 0;
13090             break;
13091 #endif   /* defined(HAVE_SS7) */
13092          default:
13093              /* We default to in service on protocols that don't have a reset */
13094             tmp->inservice = 1;
13095             break;
13096          }
13097       }
13098 
13099       switch (tmp->sig) {
13100 #if defined(HAVE_PRI)
13101       case SIG_PRI_LIB_HANDLE_CASES:
13102          if (pri_chan) {
13103             pri_chan->channel = tmp->channel;
13104             pri_chan->hidecallerid = tmp->hidecallerid;
13105             pri_chan->hidecalleridname = tmp->hidecalleridname;
13106             pri_chan->immediate = tmp->immediate;
13107             pri_chan->inalarm = tmp->inalarm;
13108             pri_chan->priexclusive = tmp->priexclusive;
13109             pri_chan->priindication_oob = tmp->priindication_oob;
13110             pri_chan->use_callerid = tmp->use_callerid;
13111             pri_chan->use_callingpres = tmp->use_callingpres;
13112             ast_copy_string(pri_chan->context, tmp->context,
13113                sizeof(pri_chan->context));
13114             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13115                sizeof(pri_chan->mohinterpret));
13116             pri_chan->stripmsd = tmp->stripmsd;
13117          }
13118          break;
13119 #endif   /* defined(HAVE_PRI) */
13120 #if defined(HAVE_SS7)
13121       case SIG_SS7:
13122          if (ss7_chan) {
13123             ss7_chan->inalarm = tmp->inalarm;
13124 
13125             ss7_chan->stripmsd = tmp->stripmsd;
13126             ss7_chan->hidecallerid = tmp->hidecallerid;
13127             ss7_chan->use_callerid = tmp->use_callerid;
13128             ss7_chan->use_callingpres = tmp->use_callingpres;
13129             ss7_chan->immediate = tmp->immediate;
13130             ss7_chan->locallyblocked = tmp->locallyblocked;
13131             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13132             ast_copy_string(ss7_chan->context, tmp->context,
13133                sizeof(ss7_chan->context));
13134             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13135                sizeof(ss7_chan->mohinterpret));
13136          }
13137          break;
13138 #endif   /* defined(HAVE_SS7) */
13139       default:
13140          /* The only sig submodule left should be sig_analog. */
13141          analog_p = tmp->sig_pvt;
13142          if (analog_p) {
13143             analog_p->channel = tmp->channel;
13144             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13145             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13146             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13147             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13148             analog_p->callreturn = conf->chan.callreturn;
13149             analog_p->cancallforward = conf->chan.cancallforward;
13150             analog_p->canpark = conf->chan.canpark;
13151             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13152             analog_p->immediate = conf->chan.immediate;
13153             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13154             analog_p->pulse = conf->chan.pulse;
13155             analog_p->threewaycalling = conf->chan.threewaycalling;
13156             analog_p->transfer = conf->chan.transfer;
13157             analog_p->transfertobusy = conf->chan.transfertobusy;
13158             analog_p->use_callerid = tmp->use_callerid;
13159             analog_p->use_smdi = tmp->use_smdi;
13160             analog_p->smdi_iface = tmp->smdi_iface;
13161             analog_p->outsigmod = ANALOG_SIG_NONE;
13162             analog_p->echotraining = conf->chan.echotraining;
13163             analog_p->cid_signalling = conf->chan.cid_signalling;
13164             analog_p->stripmsd = conf->chan.stripmsd;
13165             switch (conf->chan.cid_start) {
13166             case CID_START_POLARITY:
13167                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13168                break;
13169             case CID_START_POLARITY_IN:
13170                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13171                break;
13172             case CID_START_DTMF_NOALERT:
13173                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13174                break;
13175             default:
13176                analog_p->cid_start = ANALOG_CID_START_RING;
13177                break;
13178             }
13179             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13180             analog_p->ringt = conf->chan.ringt;
13181             analog_p->ringt_base = ringt_base;
13182             analog_p->onhooktime = time(NULL);
13183             if (chan_sig & __DAHDI_SIG_FXO) {
13184                memset(&p, 0, sizeof(p));
13185                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13186                if (!res) {
13187                   analog_p->fxsoffhookstate = p.rxisoffhook;
13188                }
13189 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13190                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13191 #endif
13192             }
13193             analog_p->msgstate = -1;
13194 
13195             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13196             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13197             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13198 
13199             analog_config_complete(analog_p);
13200          }
13201          break;
13202       }
13203 #if defined(HAVE_PRI)
13204       if (tmp->channel == CHAN_PSEUDO) {
13205          /*
13206           * Save off pseudo channel buffer policy values for dynamic creation of
13207           * no B channel interfaces.
13208           */
13209          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13210          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13211          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13212          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13213       }
13214 #endif   /* defined(HAVE_PRI) */
13215    }
13216    if (tmp && !here) {
13217       /* Add the new channel interface to the sorted channel interface list. */
13218       dahdi_iflist_insert(tmp);
13219    }
13220    return tmp;
13221 }
13222 
13223 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13224 {
13225 #if defined(HAVE_PRI)
13226    if (0 < span) {
13227       /* The channel must be on the specified PRI span. */
13228       if (!p->pri || p->pri->span != span) {
13229          return 0;
13230       }
13231       if (!groupmatch && channelmatch == -1) {
13232          /* Match any group since it only needs to be on the PRI span. */
13233          *groupmatched = 1;
13234          return 1;
13235       }
13236    }
13237 #endif   /* defined(HAVE_PRI) */
13238    /* check group matching */
13239    if (groupmatch) {
13240       if ((p->group & groupmatch) != groupmatch)
13241          /* Doesn't match the specified group, try the next one */
13242          return 0;
13243       *groupmatched = 1;
13244    }
13245    /* Check to see if we have a channel match */
13246    if (channelmatch != -1) {
13247       if (p->channel != channelmatch)
13248          /* Doesn't match the specified channel, try the next one */
13249          return 0;
13250       *channelmatched = 1;
13251    }
13252 
13253    return 1;
13254 }
13255 
13256 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13257 {
13258    struct dahdi_pvt *p = *pvt;
13259 
13260    if (p->inalarm)
13261       return 0;
13262 
13263    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13264       return analog_available(p->sig_pvt);
13265 
13266    switch (p->sig) {
13267 #if defined(HAVE_PRI)
13268    case SIG_PRI_LIB_HANDLE_CASES:
13269       {
13270          struct sig_pri_chan *pvt_chan;
13271          int res;
13272 
13273          pvt_chan = p->sig_pvt;
13274          res = sig_pri_available(&pvt_chan, is_specific_channel);
13275          *pvt = pvt_chan->chan_pvt;
13276          return res;
13277       }
13278 #endif   /* defined(HAVE_PRI) */
13279 #if defined(HAVE_SS7)
13280    case SIG_SS7:
13281       return sig_ss7_available(p->sig_pvt);
13282 #endif   /* defined(HAVE_SS7) */
13283    default:
13284       break;
13285    }
13286 
13287    if (p->locallyblocked || p->remotelyblocked) {
13288       return 0;
13289    }
13290 
13291    /* If no owner definitely available */
13292    if (!p->owner) {
13293 #ifdef HAVE_OPENR2
13294       /* Trust MFC/R2 */
13295       if (p->mfcr2) {
13296          if (p->mfcr2call) {
13297             return 0;
13298          } else {
13299             return 1;
13300          }
13301       }
13302 #endif
13303       return 1;
13304    }
13305 
13306    return 0;
13307 }
13308 
13309 #if defined(HAVE_PRI)
13310 #if defined(HAVE_PRI_CALL_WAITING)
13311 /*!
13312  * \internal
13313  * \brief Init the private channel configuration using the span controller.
13314  * \since 1.8
13315  *
13316  * \param priv Channel to init the configuration.
13317  * \param pri sig_pri PRI control structure.
13318  *
13319  * \note Assumes the pri->lock is already obtained.
13320  *
13321  * \return Nothing
13322  */
13323 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13324 {
13325    struct dahdi_pvt *pvt = priv;
13326 
13327    pvt->stripmsd = pri->ch_cfg.stripmsd;
13328    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13329    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13330    pvt->immediate = pri->ch_cfg.immediate;
13331    pvt->priexclusive = pri->ch_cfg.priexclusive;
13332    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13333    pvt->use_callerid = pri->ch_cfg.use_callerid;
13334    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13335    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13336    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13337 }
13338 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13339 #endif   /* defined(HAVE_PRI) */
13340 
13341 #if defined(HAVE_PRI)
13342 /*!
13343  * \internal
13344  * \brief Create a no B channel interface.
13345  * \since 1.8
13346  *
13347  * \param pri sig_pri span controller to add interface.
13348  *
13349  * \note Assumes the pri->lock is already obtained.
13350  *
13351  * \retval array-index into private pointer array on success.
13352  * \retval -1 on error.
13353  */
13354 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13355 {
13356    int pvt_idx;
13357    int res;
13358    unsigned idx;
13359    struct dahdi_pvt *pvt;
13360    struct sig_pri_chan *chan;
13361    struct dahdi_bufferinfo bi;
13362 
13363    static int nobch_channel = CHAN_PSEUDO;
13364 
13365    /* Find spot in the private pointer array for new interface. */
13366    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13367       if (!pri->pvts[pvt_idx]) {
13368          break;
13369       }
13370    }
13371    if (pri->numchans == pvt_idx) {
13372       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13373          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13374          return -1;
13375       }
13376 
13377       /* Add new spot to the private pointer array. */
13378       pri->pvts[pvt_idx] = NULL;
13379       ++pri->numchans;
13380    }
13381 
13382    pvt = ast_calloc(1, sizeof(*pvt));
13383    if (!pvt) {
13384       return -1;
13385    }
13386    pvt->cc_params = ast_cc_config_params_init();
13387    if (!pvt->cc_params) {
13388       ast_free(pvt);
13389       return -1;
13390    }
13391    ast_mutex_init(&pvt->lock);
13392    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13393       pvt->subs[idx].dfd = -1;
13394    }
13395    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13396    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13397    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13398    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13399 
13400    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13401    if (!chan) {
13402       destroy_dahdi_pvt(pvt);
13403       return -1;
13404    }
13405    chan->no_b_channel = 1;
13406 
13407    /*
13408     * Pseudo channel companding law.
13409     * Needed for outgoing call waiting calls.
13410     * XXX May need to make this determined by switchtype or user option.
13411     */
13412    pvt->law_default = DAHDI_LAW_ALAW;
13413 
13414    pvt->sig = pri->sig;
13415    pvt->outsigmod = -1;
13416    pvt->pri = pri;
13417    pvt->sig_pvt = chan;
13418    pri->pvts[pvt_idx] = chan;
13419 
13420    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13421    if (pvt->subs[SUB_REAL].dfd < 0) {
13422       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13423          strerror(errno));
13424       destroy_dahdi_pvt(pvt);
13425       return -1;
13426    }
13427    memset(&bi, 0, sizeof(bi));
13428    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13429    if (!res) {
13430       pvt->bufsize = bi.bufsize;
13431       bi.txbufpolicy = pvt->buf_policy;
13432       bi.rxbufpolicy = pvt->buf_policy;
13433       bi.numbufs = pvt->buf_no;
13434       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13435       if (res < 0) {
13436          ast_log(LOG_WARNING,
13437             "Unable to set buffer policy on no B channel interface: %s\n",
13438             strerror(errno));
13439       }
13440    } else
13441       ast_log(LOG_WARNING,
13442          "Unable to check buffer policy on no B channel interface: %s\n",
13443          strerror(errno));
13444 
13445    --nobch_channel;
13446    if (CHAN_PSEUDO < nobch_channel) {
13447       nobch_channel = CHAN_PSEUDO - 1;
13448    }
13449    pvt->channel = nobch_channel;
13450    pvt->span = pri->span;
13451    chan->channel = pvt->channel;
13452 
13453    dahdi_nobch_insert(pri, pvt);
13454 
13455    return pvt_idx;
13456 }
13457 #endif   /* defined(HAVE_PRI) */
13458 
13459 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13460    structures; it makes no attempt to safely copy regular channel private
13461    structures that might contain reference-counted object pointers and other
13462    scary bits
13463 */
13464 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13465 {
13466    struct dahdi_pvt *p;
13467    struct dahdi_bufferinfo bi;
13468    int res;
13469 
13470    p = ast_malloc(sizeof(*p));
13471    if (!p) {
13472       return NULL;
13473    }
13474    *p = *src;
13475 
13476    /* Must deep copy the cc_params. */
13477    p->cc_params = ast_cc_config_params_init();
13478    if (!p->cc_params) {
13479       ast_free(p);
13480       return NULL;
13481    }
13482    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13483 
13484    p->which_iflist = DAHDI_IFLIST_NONE;
13485    p->next = NULL;
13486    p->prev = NULL;
13487    ast_mutex_init(&p->lock);
13488    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13489    if (p->subs[SUB_REAL].dfd < 0) {
13490       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13491       destroy_dahdi_pvt(p);
13492       return NULL;
13493    }
13494    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13495    if (!res) {
13496       bi.txbufpolicy = src->buf_policy;
13497       bi.rxbufpolicy = src->buf_policy;
13498       bi.numbufs = src->buf_no;
13499       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13500       if (res < 0) {
13501          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13502       }
13503    } else
13504       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13505    p->destroy = 1;
13506    dahdi_iflist_insert(p);
13507    return p;
13508 }
13509 
13510 struct dahdi_starting_point {
13511    /*! Group matching mask.  Zero if not specified. */
13512    ast_group_t groupmatch;
13513    /*! DAHDI channel to match with.  -1 if not specified. */
13514    int channelmatch;
13515    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13516    int rr_starting_point;
13517    /*! ISDN span where channels can be picked (Zero if not specified) */
13518    int span;
13519    /*! Analog channel distinctive ring cadance index. */
13520    int cadance;
13521    /*! Dialing option. c/r/d if present and valid. */
13522    char opt;
13523    /*! TRUE if to search the channel list backwards. */
13524    char backwards;
13525    /*! TRUE if search is done with round robin sequence. */
13526    char roundrobin;
13527 };
13528 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13529 {
13530    char *dest;
13531    char *s;
13532    int x;
13533    int res = 0;
13534    struct dahdi_pvt *p;
13535    char *subdir = NULL;
13536    AST_DECLARE_APP_ARGS(args,
13537       AST_APP_ARG(group);  /* channel/group token */
13538       //AST_APP_ARG(ext);  /* extension token */
13539       //AST_APP_ARG(opts); /* options token */
13540       AST_APP_ARG(other);  /* Any remining unused arguments */
13541    );
13542 
13543    /*
13544     * data is ---v
13545     * Dial(DAHDI/pseudo[/extension[/options]])
13546     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13547     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13548     * Dial(DAHDI/i<span>[/extension[/options]])
13549     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13550     *
13551     * i - ISDN span channel restriction.
13552     *     Used by CC to ensure that the CC recall goes out the same span.
13553     *     Also to make ISDN channel names dialable when the sequence number
13554     *     is stripped off.  (Used by DTMF attended transfer feature.)
13555     *
13556     * g - channel group allocation search forward
13557     * G - channel group allocation search backward
13558     * r - channel group allocation round robin search forward
13559     * R - channel group allocation round robin search backward
13560     *
13561     * c - Wait for DTMF digit to confirm answer
13562     * r<cadance#> - Set distintive ring cadance number
13563     * d - Force bearer capability for ISDN/SS7 call to digital.
13564     */
13565 
13566    if (data) {
13567       dest = ast_strdupa(data);
13568    } else {
13569       ast_log(LOG_WARNING, "Channel requested with no data\n");
13570       return NULL;
13571    }
13572    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13573    if (!args.argc || ast_strlen_zero(args.group)) {
13574       ast_log(LOG_WARNING, "No channel/group specified\n");
13575       return NULL;
13576    }
13577 
13578    /* Initialize the output parameters */
13579    memset(param, 0, sizeof(*param));
13580    param->channelmatch = -1;
13581 
13582    if (strchr(args.group, '!') != NULL) {
13583       char *prev = args.group;
13584       while ((s = strchr(prev, '!')) != NULL) {
13585          *s++ = '/';
13586          prev = s;
13587       }
13588       *(prev - 1) = '\0';
13589       subdir = args.group;
13590       args.group = prev;
13591    } else if (args.group[0] == 'i') {
13592       /* Extract the ISDN span channel restriction specifier. */
13593       res = sscanf(args.group + 1, "%30d", &x);
13594       if (res < 1) {
13595          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13596          return NULL;
13597       }
13598       param->span = x;
13599 
13600       /* Remove the ISDN span channel restriction specifier. */
13601       s = strchr(args.group, '-');
13602       if (!s) {
13603          /* Search all groups since we are ISDN span restricted. */
13604          return iflist;
13605       }
13606       args.group = s + 1;
13607       res = 0;
13608    }
13609    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13610       /* Retrieve the group number */
13611       s = args.group + 1;
13612       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13613       if (res < 1) {
13614          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13615          return NULL;
13616       }
13617       param->groupmatch = ((ast_group_t) 1 << x);
13618 
13619       if (toupper(args.group[0]) == 'G') {
13620          if (args.group[0] == 'G') {
13621             param->backwards = 1;
13622             p = ifend;
13623          } else
13624             p = iflist;
13625       } else {
13626          if (ARRAY_LEN(round_robin) <= x) {
13627             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13628                x, data);
13629             return NULL;
13630          }
13631          if (args.group[0] == 'R') {
13632             param->backwards = 1;
13633             p = round_robin[x] ? round_robin[x]->prev : ifend;
13634             if (!p)
13635                p = ifend;
13636          } else {
13637             p = round_robin[x] ? round_robin[x]->next : iflist;
13638             if (!p)
13639                p = iflist;
13640          }
13641          param->roundrobin = 1;
13642          param->rr_starting_point = x;
13643       }
13644    } else {
13645       s = args.group;
13646       if (!strcasecmp(s, "pseudo")) {
13647          /* Special case for pseudo */
13648          x = CHAN_PSEUDO;
13649          param->channelmatch = x;
13650       } else {
13651          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13652          if (res < 1) {
13653             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13654             return NULL;
13655          } else {
13656             param->channelmatch = x;
13657          }
13658       }
13659       if (subdir) {
13660          char path[PATH_MAX];
13661          struct stat stbuf;
13662 
13663          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13664                subdir, param->channelmatch);
13665          if (stat(path, &stbuf) < 0) {
13666             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13667                   path, strerror(errno));
13668             return NULL;
13669          }
13670          if (!S_ISCHR(stbuf.st_mode)) {
13671             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13672                   path);
13673             return NULL;
13674          }
13675          param->channelmatch = minor(stbuf.st_rdev);
13676       }
13677 
13678       p = iflist;
13679    }
13680 
13681    if (param->opt == 'r' && res < 3) {
13682       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13683       param->opt = '\0';
13684    }
13685 
13686    return p;
13687 }
13688 
13689 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13690 {
13691    int callwait = 0;
13692    struct dahdi_pvt *p;
13693    struct ast_channel *tmp = NULL;
13694    struct dahdi_pvt *exitpvt;
13695    int channelmatched = 0;
13696    int groupmatched = 0;
13697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13698    int transcapdigital = 0;
13699 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13700    struct dahdi_starting_point start;
13701 
13702    ast_mutex_lock(&iflock);
13703    p = determine_starting_point(data, &start);
13704    if (!p) {
13705       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13706       ast_mutex_unlock(&iflock);
13707       return NULL;
13708    }
13709 
13710    /* Search for an unowned channel */
13711    exitpvt = p;
13712    while (p && !tmp) {
13713       if (start.roundrobin)
13714          round_robin[start.rr_starting_point] = p;
13715 
13716       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13717          && available(&p, channelmatched)) {
13718          ast_debug(1, "Using channel %d\n", p->channel);
13719 
13720          callwait = (p->owner != NULL);
13721 #ifdef HAVE_OPENR2
13722          if (p->mfcr2) {
13723             ast_mutex_lock(&p->lock);
13724             if (p->mfcr2call) {
13725                ast_mutex_unlock(&p->lock);
13726                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13727                goto next;
13728             }
13729             p->mfcr2call = 1;
13730             ast_mutex_unlock(&p->lock);
13731          }
13732 #endif
13733          if (p->channel == CHAN_PSEUDO) {
13734             p = duplicate_pseudo(p);
13735             if (!p) {
13736                break;
13737             }
13738          }
13739 
13740          p->distinctivering = 0;
13741          /* Make special notes */
13742          switch (start.opt) {
13743          case '\0':
13744             /* No option present. */
13745             break;
13746          case 'c':
13747             /* Confirm answer */
13748             p->confirmanswer = 1;
13749             break;
13750          case 'r':
13751             /* Distinctive ring */
13752             p->distinctivering = start.cadance;
13753             break;
13754          case 'd':
13755 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13756             /* If this is an ISDN call, make it digital */
13757             transcapdigital = AST_TRANS_CAP_DIGITAL;
13758 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13759             break;
13760          default:
13761             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13762             break;
13763          }
13764 
13765          p->outgoing = 1;
13766          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13767             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13768 #ifdef HAVE_PRI
13769          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13770             /*
13771              * We already have the B channel reserved for this call.  We
13772              * just need to make sure that dahdi_hangup() has completed
13773              * cleaning up before continuing.
13774              */
13775             ast_mutex_lock(&p->lock);
13776             ast_mutex_unlock(&p->lock);
13777 
13778             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13779                sizeof(p->dnid));
13780             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13781 #endif
13782 #if defined(HAVE_SS7)
13783          } else if (p->sig == SIG_SS7) {
13784             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13785 #endif   /* defined(HAVE_SS7) */
13786          } else {
13787             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13788          }
13789          if (!tmp) {
13790             p->outgoing = 0;
13791 #if defined(HAVE_PRI)
13792             switch (p->sig) {
13793             case SIG_PRI_LIB_HANDLE_CASES:
13794 #if defined(HAVE_PRI_CALL_WAITING)
13795                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13796                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13797                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13798                }
13799 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13800                /*
13801                 * This should be the last thing to clear when we are done with
13802                 * the channel.
13803                 */
13804                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13805                break;
13806             default:
13807                break;
13808             }
13809 #endif   /* defined(HAVE_PRI) */
13810          } else {
13811             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13812          }
13813          break;
13814       }
13815 #ifdef HAVE_OPENR2
13816 next:
13817 #endif
13818       if (start.backwards) {
13819          p = p->prev;
13820          if (!p)
13821             p = ifend;
13822       } else {
13823          p = p->next;
13824          if (!p)
13825             p = iflist;
13826       }
13827       /* stop when you roll to the one that we started from */
13828       if (p == exitpvt)
13829          break;
13830    }
13831    ast_mutex_unlock(&iflock);
13832    restart_monitor();
13833    if (cause && !tmp) {
13834       if (callwait || channelmatched) {
13835          *cause = AST_CAUSE_BUSY;
13836       } else if (groupmatched) {
13837          *cause = AST_CAUSE_CONGESTION;
13838       } else {
13839          /*
13840           * We did not match any channel requested.
13841           * Dialplan error requesting non-existant channel?
13842           */
13843       }
13844    }
13845 
13846    return tmp;
13847 }
13848 
13849 /*!
13850  * \internal
13851  * \brief Determine the device state for a given DAHDI device if we can.
13852  * \since 1.8
13853  *
13854  * \param data DAHDI device name after "DAHDI/".
13855  *
13856  * \retval device_state enum ast_device_state value.
13857  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13858  */
13859 static int dahdi_devicestate(void *data)
13860 {
13861 #if defined(HAVE_PRI)
13862    char *device;
13863    unsigned span;
13864    int res;
13865 
13866    device = data;
13867 
13868    if (*device != 'I') {
13869       /* The request is not for an ISDN span device. */
13870       return AST_DEVICE_UNKNOWN;
13871    }
13872    res = sscanf(device, "I%30u", &span);
13873    if (res != 1 || !span || NUM_SPANS < span) {
13874       /* Bad format for ISDN span device name. */
13875       return AST_DEVICE_UNKNOWN;
13876    }
13877    device = strchr(device, '/');
13878    if (!device) {
13879       /* Bad format for ISDN span device name. */
13880       return AST_DEVICE_UNKNOWN;
13881    }
13882 
13883    /*
13884     * Since there are currently no other span devstate's defined,
13885     * it must be congestion.
13886     */
13887 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13888    ++device;
13889    if (!strcmp(device, "congestion"))
13890 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13891    {
13892       return pris[span - 1].pri.congestion_devstate;
13893    }
13894 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13895    else if (!strcmp(device, "threshold")) {
13896       return pris[span - 1].pri.threshold_devstate;
13897    }
13898    return AST_DEVICE_UNKNOWN;
13899 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13900 #else
13901    return AST_DEVICE_UNKNOWN;
13902 #endif   /* defined(HAVE_PRI) */
13903 }
13904 
13905 /*!
13906  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13907  * \since 1.8
13908  *
13909  * \param inbound Incoming asterisk channel.
13910  * \param dest Same dial string passed to dahdi_request().
13911  * \param callback Callback into CC core to announce a busy channel available for CC.
13912  *
13913  * \details
13914  * This callback acts like a forked dial with all prongs of the fork busy.
13915  * Essentially, for each channel that could have taken the call, indicate that
13916  * it is busy.
13917  *
13918  * \retval 0 on success.
13919  * \retval -1 on error.
13920  */
13921 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13922 {
13923    struct dahdi_pvt *p;
13924    struct dahdi_pvt *exitpvt;
13925    struct dahdi_starting_point start;
13926    int groupmatched = 0;
13927    int channelmatched = 0;
13928 
13929    ast_mutex_lock(&iflock);
13930    p = determine_starting_point(dest, &start);
13931    if (!p) {
13932       ast_mutex_unlock(&iflock);
13933       return -1;
13934    }
13935    exitpvt = p;
13936    for (;;) {
13937       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13938          /* We found a potential match. call the callback */
13939          struct ast_str *device_name;
13940          char *dash;
13941          const char *monitor_type;
13942          char dialstring[AST_CHANNEL_NAME];
13943          char full_device_name[AST_CHANNEL_NAME];
13944 
13945          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13946          case AST_CC_MONITOR_NEVER:
13947             break;
13948          case AST_CC_MONITOR_NATIVE:
13949          case AST_CC_MONITOR_ALWAYS:
13950          case AST_CC_MONITOR_GENERIC:
13951 #if defined(HAVE_PRI)
13952             if (dahdi_sig_pri_lib_handles(p->sig)) {
13953                /*
13954                 * ISDN is in a trunk busy condition so we need to monitor
13955                 * the span congestion device state.
13956                 */
13957                snprintf(full_device_name, sizeof(full_device_name),
13958                   "DAHDI/I%d/congestion", p->pri->span);
13959             } else
13960 #endif   /* defined(HAVE_PRI) */
13961             {
13962 #if defined(HAVE_PRI)
13963                device_name = create_channel_name(p, 1, "");
13964 #else
13965                device_name = create_channel_name(p);
13966 #endif   /* defined(HAVE_PRI) */
13967                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13968                   device_name ? ast_str_buffer(device_name) : "");
13969                ast_free(device_name);
13970                /*
13971                 * The portion after the '-' in the channel name is either a random
13972                 * number, a sequence number, or a subchannel number. None are
13973                 * necessary so strip them off.
13974                 */
13975                dash = strrchr(full_device_name, '-');
13976                if (dash) {
13977                   *dash = '\0';
13978                }
13979             }
13980             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13981 
13982             /*
13983              * Analog can only do generic monitoring.
13984              * ISDN is in a trunk busy condition and any "device" is going
13985              * to be busy until a B channel becomes available.  The generic
13986              * monitor can do this task.
13987              */
13988             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13989             callback(inbound,
13990 #if defined(HAVE_PRI)
13991                p->pri ? p->pri->cc_params : p->cc_params,
13992 #else
13993                p->cc_params,
13994 #endif   /* defined(HAVE_PRI) */
13995                monitor_type, full_device_name, dialstring, NULL);
13996             break;
13997          }
13998       }
13999       p = start.backwards ? p->prev : p->next;
14000       if (!p) {
14001          p = start.backwards ? ifend : iflist;
14002       }
14003       if (p == exitpvt) {
14004          break;
14005       }
14006    }
14007    ast_mutex_unlock(&iflock);
14008    return 0;
14009 }
14010 
14011 #if defined(HAVE_SS7)
14012 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14013 {
14014    int i;
14015 
14016    if (ss7) {
14017       for (i = 0; i < NUM_SPANS; i++) {
14018          if (linksets[i].ss7.ss7 == ss7) {
14019             ast_verbose("[%d] %s", i + 1, s);
14020             return;
14021          }
14022       }
14023    }
14024    ast_verbose("%s", s);
14025 }
14026 #endif   /* defined(HAVE_SS7) */
14027 
14028 #if defined(HAVE_SS7)
14029 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14030 {
14031    int i;
14032 
14033    if (ss7) {
14034       for (i = 0; i < NUM_SPANS; i++) {
14035          if (linksets[i].ss7.ss7 == ss7) {
14036             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14037             return;
14038          }
14039       }
14040    }
14041    ast_log(LOG_ERROR, "%s", s);
14042 }
14043 #endif   /* defined(HAVE_SS7) */
14044 
14045 #if defined(HAVE_OPENR2)
14046 static void *mfcr2_monitor(void *data)
14047 {
14048    struct dahdi_mfcr2 *mfcr2 = data;
14049    /* we should be using pthread_key_create
14050       and allocate pollers dynamically.
14051       I think do_monitor() could be leaking, since it
14052       could be cancelled at any time and is not
14053       using thread keys, why?, */
14054    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14055    int res = 0;
14056    int i = 0;
14057    int oldstate = 0;
14058    int quit_loop = 0;
14059    int maxsleep = 20;
14060    int was_idle = 0;
14061    int pollsize = 0;
14062    /* now that we're ready to get calls, unblock our side and
14063       get current line state */
14064    for (i = 0; i < mfcr2->numchans; i++) {
14065       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14066       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14067    }
14068    while (1) {
14069       /* we trust here that the mfcr2 channel list will not ever change once
14070          the module is loaded */
14071       pollsize = 0;
14072       for (i = 0; i < mfcr2->numchans; i++) {
14073          pollers[i].revents = 0;
14074          pollers[i].events = 0;
14075          if (mfcr2->pvts[i]->owner) {
14076             continue;
14077          }
14078          if (!mfcr2->pvts[i]->r2chan) {
14079             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14080             quit_loop = 1;
14081             break;
14082          }
14083          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14084          pollers[i].events = POLLIN | POLLPRI;
14085          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14086          pollsize++;
14087       }
14088       if (quit_loop) {
14089          break;
14090       }
14091       if (pollsize == 0) {
14092          if (!was_idle) {
14093             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14094             was_idle = 1;
14095          }
14096          poll(NULL, 0, maxsleep);
14097          continue;
14098       }
14099       was_idle = 0;
14100       /* probably poll() is a valid cancel point, lets just be on the safe side
14101          by calling pthread_testcancel */
14102       pthread_testcancel();
14103       res = poll(pollers, mfcr2->numchans, maxsleep);
14104       pthread_testcancel();
14105       if ((res < 0) && (errno != EINTR)) {
14106          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14107          break;
14108       }
14109       /* do we want to allow to cancel while processing events? */
14110       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14111       for (i = 0; i < mfcr2->numchans; i++) {
14112          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14113             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14114          }
14115       }
14116       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14117    }
14118    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14119    return 0;
14120 }
14121 #endif /* HAVE_OPENR2 */
14122 
14123 #if defined(HAVE_PRI)
14124 static void dahdi_pri_message(struct pri *pri, char *s)
14125 {
14126    int x;
14127    int y;
14128    int dchan = -1;
14129    int span = -1;
14130    int dchancount = 0;
14131 
14132    if (pri) {
14133       for (x = 0; x < NUM_SPANS; x++) {
14134          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14135             if (pris[x].pri.dchans[y]) {
14136                dchancount++;
14137             }
14138 
14139             if (pris[x].pri.dchans[y] == pri) {
14140                dchan = y;
14141             }
14142          }
14143          if (dchan >= 0) {
14144             span = x;
14145             break;
14146          }
14147          dchancount = 0;
14148       }
14149       if (-1 < span) {
14150          if (1 < dchancount) {
14151             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14152          } else {
14153             ast_verbose("PRI Span: %d %s", span + 1, s);
14154          }
14155       } else {
14156          ast_verbose("PRI Span: ? %s", s);
14157       }
14158    } else {
14159       ast_verbose("PRI Span: ? %s", s);
14160    }
14161 
14162    ast_mutex_lock(&pridebugfdlock);
14163 
14164    if (pridebugfd >= 0) {
14165       if (write(pridebugfd, s, strlen(s)) < 0) {
14166          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14167       }
14168    }
14169 
14170    ast_mutex_unlock(&pridebugfdlock);
14171 }
14172 #endif   /* defined(HAVE_PRI) */
14173 
14174 #if defined(HAVE_PRI)
14175 static void dahdi_pri_error(struct pri *pri, char *s)
14176 {
14177    int x;
14178    int y;
14179    int dchan = -1;
14180    int span = -1;
14181    int dchancount = 0;
14182 
14183    if (pri) {
14184       for (x = 0; x < NUM_SPANS; x++) {
14185          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14186             if (pris[x].pri.dchans[y]) {
14187                dchancount++;
14188             }
14189 
14190             if (pris[x].pri.dchans[y] == pri) {
14191                dchan = y;
14192             }
14193          }
14194          if (dchan >= 0) {
14195             span = x;
14196             break;
14197          }
14198          dchancount = 0;
14199       }
14200       if (-1 < span) {
14201          if (1 < dchancount) {
14202             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14203          } else {
14204             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14205          }
14206       } else {
14207          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14208       }
14209    } else {
14210       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14211    }
14212 
14213    ast_mutex_lock(&pridebugfdlock);
14214 
14215    if (pridebugfd >= 0) {
14216       if (write(pridebugfd, s, strlen(s)) < 0) {
14217          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14218       }
14219    }
14220 
14221    ast_mutex_unlock(&pridebugfdlock);
14222 }
14223 #endif   /* defined(HAVE_PRI) */
14224 
14225 #if defined(HAVE_PRI)
14226 static int prepare_pri(struct dahdi_pri *pri)
14227 {
14228    int i, res, x;
14229    struct dahdi_params p;
14230    struct dahdi_bufferinfo bi;
14231    struct dahdi_spaninfo si;
14232 
14233    pri->pri.calls = &dahdi_pri_callbacks;
14234 
14235    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14236       if (!pri->dchannels[i])
14237          break;
14238       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14239       x = pri->dchannels[i];
14240       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14241          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14242          return -1;
14243       }
14244       memset(&p, 0, sizeof(p));
14245       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14246       if (res) {
14247          dahdi_close_pri_fd(pri, i);
14248          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14249          return -1;
14250       }
14251       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14252          dahdi_close_pri_fd(pri, i);
14253          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14254          return -1;
14255       }
14256       memset(&si, 0, sizeof(si));
14257       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14258       if (res) {
14259          dahdi_close_pri_fd(pri, i);
14260          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14261       }
14262       if (!si.alarms) {
14263          pri_event_noalarm(&pri->pri, i, 1);
14264       } else {
14265          pri_event_alarm(&pri->pri, i, 1);
14266       }
14267       memset(&bi, 0, sizeof(bi));
14268       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14269       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14270       bi.numbufs = 32;
14271       bi.bufsize = 1024;
14272       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14273          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14274          dahdi_close_pri_fd(pri, i);
14275          return -1;
14276       }
14277       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14278    }
14279    return 0;
14280 }
14281 #endif   /* defined(HAVE_PRI) */
14282 
14283 #if defined(HAVE_PRI)
14284 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14285 {
14286    int which, span;
14287    char *ret = NULL;
14288 
14289    if (pos != rpos)
14290       return ret;
14291 
14292    for (which = span = 0; span < NUM_SPANS; span++) {
14293       if (pris[span].pri.pri && ++which > state) {
14294          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14295             ret = NULL;
14296          }
14297          break;
14298       }
14299    }
14300    return ret;
14301 }
14302 #endif   /* defined(HAVE_PRI) */
14303 
14304 #if defined(HAVE_PRI)
14305 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14306 {
14307    return complete_span_helper(line,word,pos,state,3);
14308 }
14309 #endif   /* defined(HAVE_PRI) */
14310 
14311 #if defined(HAVE_PRI)
14312 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14313 {
14314    int myfd;
14315    switch (cmd) {
14316    case CLI_INIT:
14317       e->command = "pri set debug file";
14318       e->usage = "Usage: pri set debug file [output-file]\n"
14319          "       Sends PRI debug output to the specified output file\n";
14320       return NULL;
14321    case CLI_GENERATE:
14322       return NULL;
14323    }
14324    if (a->argc < 5)
14325       return CLI_SHOWUSAGE;
14326 
14327    if (ast_strlen_zero(a->argv[4]))
14328       return CLI_SHOWUSAGE;
14329 
14330    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14331    if (myfd < 0) {
14332       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14333       return CLI_SUCCESS;
14334    }
14335 
14336    ast_mutex_lock(&pridebugfdlock);
14337 
14338    if (pridebugfd >= 0)
14339       close(pridebugfd);
14340 
14341    pridebugfd = myfd;
14342    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14343    ast_mutex_unlock(&pridebugfdlock);
14344    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14345    return CLI_SUCCESS;
14346 }
14347 #endif   /* defined(HAVE_PRI) */
14348 
14349 #if defined(HAVE_PRI)
14350 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14351 {
14352    int span;
14353    int x;
14354    int level = 0;
14355    switch (cmd) {
14356    case CLI_INIT:
14357       e->command = "pri set debug {on|off|0|1|2} span";
14358       e->usage =
14359          "Usage: pri set debug {<level>|on|off} span <span>\n"
14360          "       Enables debugging on a given PRI span\n";
14361       return NULL;
14362    case CLI_GENERATE:
14363       return complete_span_4(a->line, a->word, a->pos, a->n);
14364    }
14365    if (a->argc < 6) {
14366       return CLI_SHOWUSAGE;
14367    }
14368 
14369    if (!strcasecmp(a->argv[3], "on")) {
14370       level = 1;
14371    } else if (!strcasecmp(a->argv[3], "off")) {
14372       level = 0;
14373    } else {
14374       level = atoi(a->argv[3]);
14375    }
14376    span = atoi(a->argv[5]);
14377    if ((span < 1) || (span > NUM_SPANS)) {
14378       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14379       return CLI_SUCCESS;
14380    }
14381    if (!pris[span-1].pri.pri) {
14382       ast_cli(a->fd, "No PRI running on span %d\n", span);
14383       return CLI_SUCCESS;
14384    }
14385 
14386    /* Set debug level in libpri */
14387    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14388       if (pris[span - 1].pri.dchans[x]) {
14389          switch (level) {
14390          case 0:
14391             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14392             break;
14393          case 1:
14394             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14395             break;
14396          default:
14397             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14398             break;
14399          }
14400       }
14401    }
14402    if (level == 0) {
14403       /* Close the debugging file if it's set */
14404       ast_mutex_lock(&pridebugfdlock);
14405       if (0 <= pridebugfd) {
14406          close(pridebugfd);
14407          pridebugfd = -1;
14408          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14409             pridebugfilename);
14410       }
14411       ast_mutex_unlock(&pridebugfdlock);
14412    }
14413    pris[span - 1].pri.debug = (level) ? 1 : 0;
14414    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14415    return CLI_SUCCESS;
14416 }
14417 #endif   /* defined(HAVE_PRI) */
14418 
14419 #if defined(HAVE_PRI)
14420 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14421 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14422 {
14423    unsigned *why;
14424    int channel;
14425    int trunkgroup;
14426    int x, y, fd = a->fd;
14427    int interfaceid = 0;
14428    char db_chan_name[20], db_answer[5];
14429    struct dahdi_pvt *tmp;
14430    struct dahdi_pri *pri;
14431 
14432    if (a->argc < 5 || a->argc > 6)
14433       return CLI_SHOWUSAGE;
14434    if (strchr(a->argv[4], ':')) {
14435       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14436          return CLI_SHOWUSAGE;
14437       if ((trunkgroup < 1) || (channel < 1))
14438          return CLI_SHOWUSAGE;
14439       pri = NULL;
14440       for (x=0;x<NUM_SPANS;x++) {
14441          if (pris[x].pri.trunkgroup == trunkgroup) {
14442             pri = pris + x;
14443             break;
14444          }
14445       }
14446       if (!pri) {
14447          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14448          return CLI_FAILURE;
14449       }
14450    } else
14451       channel = atoi(a->argv[4]);
14452 
14453    if (a->argc == 6)
14454       interfaceid = atoi(a->argv[5]);
14455 
14456    /* either servicing a D-Channel */
14457    for (x = 0; x < NUM_SPANS; x++) {
14458       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14459          if (pris[x].dchannels[y] == channel) {
14460             pri = pris + x;
14461             if (pri->pri.enable_service_message_support) {
14462                ast_mutex_lock(&pri->pri.lock);
14463                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14464                ast_mutex_unlock(&pri->pri.lock);
14465             } else {
14466                ast_cli(fd,
14467                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14468                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14469             }
14470             return CLI_SUCCESS;
14471          }
14472       }
14473    }
14474 
14475    /* or servicing a B-Channel */
14476    ast_mutex_lock(&iflock);
14477    for (tmp = iflist; tmp; tmp = tmp->next) {
14478       if (tmp->pri && tmp->channel == channel) {
14479          ast_mutex_unlock(&iflock);
14480          ast_mutex_lock(&tmp->pri->lock);
14481          if (!tmp->pri->enable_service_message_support) {
14482             ast_mutex_unlock(&tmp->pri->lock);
14483             ast_cli(fd,
14484                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14485                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14486             return CLI_SUCCESS;
14487          }
14488          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14489          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14490          switch(changestatus) {
14491          case 0: /* enable */
14492             /* Near end wants to be in service now. */
14493             ast_db_del(db_chan_name, SRVST_DBKEY);
14494             *why &= ~SRVST_NEAREND;
14495             if (*why) {
14496                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14497                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14498             } else {
14499                dahdi_pri_update_span_devstate(tmp->pri);
14500             }
14501             break;
14502          /* case 1:  -- loop */
14503          case 2: /* disable */
14504             /* Near end wants to be out-of-service now. */
14505             ast_db_del(db_chan_name, SRVST_DBKEY);
14506             *why |= SRVST_NEAREND;
14507             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14508             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14509             dahdi_pri_update_span_devstate(tmp->pri);
14510             break;
14511          /* case 3:  -- continuity */
14512          /* case 4:  -- shutdown */
14513          default:
14514             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14515             break;
14516          }
14517          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14518          ast_mutex_unlock(&tmp->pri->lock);
14519          return CLI_SUCCESS;
14520       }
14521    }
14522    ast_mutex_unlock(&iflock);
14523 
14524    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14525    return CLI_FAILURE;
14526 }
14527 
14528 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14529 {
14530    switch (cmd) {
14531    case CLI_INIT:
14532       e->command = "pri service enable channel";
14533       e->usage =
14534          "Usage: pri service enable channel <channel> [<interface id>]\n"
14535          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14536          "  to restore a channel to service, with optional interface id\n"
14537          "  as agreed upon with remote switch operator\n";
14538       return NULL;
14539    case CLI_GENERATE:
14540       return NULL;
14541    }
14542    return handle_pri_service_generic(e, cmd, a, 0);
14543 }
14544 
14545 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14546 {
14547    switch (cmd) {
14548    case CLI_INIT:
14549       e->command = "pri service disable channel";
14550       e->usage =
14551          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14552          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14553          "  to remove a channel from service, with optional interface id\n"
14554          "  as agreed upon with remote switch operator\n";
14555       return NULL;
14556    case CLI_GENERATE:
14557       return NULL;
14558    }
14559    return handle_pri_service_generic(e, cmd, a, 2);
14560 }
14561 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14562 #endif   /* defined(HAVE_PRI) */
14563 
14564 #if defined(HAVE_PRI)
14565 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14566 {
14567    int span;
14568 
14569    switch (cmd) {
14570    case CLI_INIT:
14571       e->command = "pri show channels";
14572       e->usage =
14573          "Usage: pri show channels\n"
14574          "       Displays PRI channel information such as the current mapping\n"
14575          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14576          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14577          "       are not associated with any B channel.\n";
14578       return NULL;
14579    case CLI_GENERATE:
14580       return NULL;
14581    }
14582 
14583    if (a->argc != 3)
14584       return CLI_SHOWUSAGE;
14585 
14586    sig_pri_cli_show_channels_header(a->fd);
14587    for (span = 0; span < NUM_SPANS; ++span) {
14588       if (pris[span].pri.pri) {
14589          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14590       }
14591    }
14592    return CLI_SUCCESS;
14593 }
14594 #endif   /* defined(HAVE_PRI) */
14595 
14596 #if defined(HAVE_PRI)
14597 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14598 {
14599    int span;
14600 
14601    switch (cmd) {
14602    case CLI_INIT:
14603       e->command = "pri show spans";
14604       e->usage =
14605          "Usage: pri show spans\n"
14606          "       Displays PRI span information\n";
14607       return NULL;
14608    case CLI_GENERATE:
14609       return NULL;
14610    }
14611 
14612    if (a->argc != 3)
14613       return CLI_SHOWUSAGE;
14614 
14615    for (span = 0; span < NUM_SPANS; span++) {
14616       if (pris[span].pri.pri) {
14617          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14618       }
14619    }
14620    return CLI_SUCCESS;
14621 }
14622 #endif   /* defined(HAVE_PRI) */
14623 
14624 #if defined(HAVE_PRI)
14625 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14626 {
14627    int span;
14628 
14629    switch (cmd) {
14630    case CLI_INIT:
14631       e->command = "pri show span";
14632       e->usage =
14633          "Usage: pri show span <span>\n"
14634          "       Displays PRI Information on a given PRI span\n";
14635       return NULL;
14636    case CLI_GENERATE:
14637       return complete_span_4(a->line, a->word, a->pos, a->n);
14638    }
14639 
14640    if (a->argc < 4)
14641       return CLI_SHOWUSAGE;
14642    span = atoi(a->argv[3]);
14643    if ((span < 1) || (span > NUM_SPANS)) {
14644       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14645       return CLI_SUCCESS;
14646    }
14647    if (!pris[span-1].pri.pri) {
14648       ast_cli(a->fd, "No PRI running on span %d\n", span);
14649       return CLI_SUCCESS;
14650    }
14651 
14652    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14653 
14654    return CLI_SUCCESS;
14655 }
14656 #endif   /* defined(HAVE_PRI) */
14657 
14658 #if defined(HAVE_PRI)
14659 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14660 {
14661    int x;
14662    int span;
14663    int count=0;
14664    int debug;
14665 
14666    switch (cmd) {
14667    case CLI_INIT:
14668       e->command = "pri show debug";
14669       e->usage =
14670          "Usage: pri show debug\n"
14671          "  Show the debug state of pri spans\n";
14672       return NULL;
14673    case CLI_GENERATE:
14674       return NULL;
14675    }
14676 
14677    for (span = 0; span < NUM_SPANS; span++) {
14678       if (pris[span].pri.pri) {
14679          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14680             if (pris[span].pri.dchans[x]) {
14681                debug = pri_get_debug(pris[span].pri.dchans[x]);
14682                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" );
14683                count++;
14684             }
14685          }
14686       }
14687 
14688    }
14689    ast_mutex_lock(&pridebugfdlock);
14690    if (pridebugfd >= 0)
14691       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14692    ast_mutex_unlock(&pridebugfdlock);
14693 
14694    if (!count)
14695       ast_cli(a->fd, "No PRI running\n");
14696    return CLI_SUCCESS;
14697 }
14698 #endif   /* defined(HAVE_PRI) */
14699 
14700 #if defined(HAVE_PRI)
14701 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14702 {
14703    switch (cmd) {
14704    case CLI_INIT:
14705       e->command = "pri show version";
14706       e->usage =
14707          "Usage: pri show version\n"
14708          "Show libpri version information\n";
14709       return NULL;
14710    case CLI_GENERATE:
14711       return NULL;
14712    }
14713 
14714    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14715 
14716    return CLI_SUCCESS;
14717 }
14718 #endif   /* defined(HAVE_PRI) */
14719 
14720 #if defined(HAVE_PRI)
14721 static struct ast_cli_entry dahdi_pri_cli[] = {
14722    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14723 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14724    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14725    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14726 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14727    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14728    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14729    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14730    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14731    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14732    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14733 };
14734 #endif   /* defined(HAVE_PRI) */
14735 
14736 #ifdef HAVE_OPENR2
14737 
14738 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14739 {
14740    switch (cmd) {
14741    case CLI_INIT:
14742       e->command = "mfcr2 show version";
14743       e->usage =
14744          "Usage: mfcr2 show version\n"
14745          "       Shows the version of the OpenR2 library being used.\n";
14746       return NULL;
14747    case CLI_GENERATE:
14748       return NULL;
14749    }
14750    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14751    return CLI_SUCCESS;
14752 }
14753 
14754 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756 #define FORMAT "%4s %40s\n"
14757    int i = 0;
14758    int numvariants = 0;
14759    const openr2_variant_entry_t *variants;
14760    switch (cmd) {
14761    case CLI_INIT:
14762       e->command = "mfcr2 show variants";
14763       e->usage =
14764          "Usage: mfcr2 show variants\n"
14765          "       Shows the list of MFC/R2 variants supported.\n";
14766       return NULL;
14767    case CLI_GENERATE:
14768       return NULL;
14769    }
14770    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14771       ast_cli(a->fd, "Failed to get list of variants.\n");
14772       return CLI_FAILURE;
14773    }
14774    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14775    for (i = 0; i < numvariants; i++) {
14776       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14777    }
14778    return CLI_SUCCESS;
14779 #undef FORMAT
14780 }
14781 
14782 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14783 {
14784 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14785    int filtertype = 0;
14786    int targetnum = 0;
14787    char channo[5];
14788    char anino[5];
14789    char dnisno[5];
14790    struct dahdi_pvt *p;
14791    openr2_context_t *r2context;
14792    openr2_variant_t r2variant;
14793    switch (cmd) {
14794    case CLI_INIT:
14795       e->command = "mfcr2 show channels [group|context]";
14796       e->usage =
14797          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14798          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14799       return NULL;
14800    case CLI_GENERATE:
14801       return NULL;
14802    }
14803    if (!((a->argc == 3) || (a->argc == 5))) {
14804       return CLI_SHOWUSAGE;
14805    }
14806    if (a->argc == 5) {
14807       if (!strcasecmp(a->argv[3], "group")) {
14808          targetnum = atoi(a->argv[4]);
14809          if ((targetnum < 0) || (targetnum > 63))
14810             return CLI_SHOWUSAGE;
14811          targetnum = 1 << targetnum;
14812          filtertype = 1;
14813       } else if (!strcasecmp(a->argv[3], "context")) {
14814          filtertype = 2;
14815       } else {
14816          return CLI_SHOWUSAGE;
14817       }
14818    }
14819    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14820    ast_mutex_lock(&iflock);
14821    for (p = iflist; p; p = p->next) {
14822       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14823          continue;
14824       }
14825       if (filtertype) {
14826          switch(filtertype) {
14827          case 1: /* mfcr2 show channels group <group> */
14828             if (p->group != targetnum) {
14829                continue;
14830             }
14831             break;
14832          case 2: /* mfcr2 show channels context <context> */
14833             if (strcasecmp(p->context, a->argv[4])) {
14834                continue;
14835             }
14836             break;
14837          default:
14838             ;
14839          }
14840       }
14841       r2context = openr2_chan_get_context(p->r2chan);
14842       r2variant = openr2_context_get_variant(r2context);
14843       snprintf(channo, sizeof(channo), "%d", p->channel);
14844       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14845       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14846       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14847             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14848             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14849             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14850    }
14851    ast_mutex_unlock(&iflock);
14852    return CLI_SUCCESS;
14853 #undef FORMAT
14854 }
14855 
14856 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14857 {
14858    struct dahdi_pvt *p = NULL;
14859    int channo = 0;
14860    char *toklevel = NULL;
14861    char *saveptr = NULL;
14862    char *logval = NULL;
14863    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14864    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14865    switch (cmd) {
14866    case CLI_INIT:
14867       e->command = "mfcr2 set debug";
14868       e->usage =
14869          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14870          "       Set a new logging level for the specified channel.\n"
14871          "       If no channel is specified the logging level will be applied to all channels.\n";
14872       return NULL;
14873    case CLI_GENERATE:
14874       return NULL;
14875    }
14876    if (a->argc < 4) {
14877       return CLI_SHOWUSAGE;
14878    }
14879    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14880    logval = ast_strdupa(a->argv[3]);
14881    toklevel = strtok_r(logval, ",", &saveptr);
14882    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14883       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14884       return CLI_FAILURE;
14885    } else if (OR2_LOG_NOTHING == tmplevel) {
14886       loglevel = tmplevel;
14887    } else {
14888       loglevel |= tmplevel;
14889       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14890          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14891             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14892             continue;
14893          }
14894          loglevel |= tmplevel;
14895       }
14896    }
14897    ast_mutex_lock(&iflock);
14898    for (p = iflist; p; p = p->next) {
14899       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14900          continue;
14901       }
14902       if ((channo != -1) && (p->channel != channo )) {
14903          continue;
14904       }
14905       openr2_chan_set_log_level(p->r2chan, loglevel);
14906       if (channo != -1) {
14907          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14908          break;
14909       }
14910    }
14911    if ((channo != -1) && !p) {
14912       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14913    }
14914    if (channo == -1) {
14915       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14916    }
14917    ast_mutex_unlock(&iflock);
14918    return CLI_SUCCESS;
14919 }
14920 
14921 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14922 {
14923    struct dahdi_pvt *p = NULL;
14924    int channo = 0;
14925    switch (cmd) {
14926    case CLI_INIT:
14927       e->command = "mfcr2 call files [on|off]";
14928       e->usage =
14929          "Usage: mfcr2 call files [on|off] <channel>\n"
14930          "       Enable call files creation on the specified channel.\n"
14931          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14932       return NULL;
14933    case CLI_GENERATE:
14934       return NULL;
14935    }
14936    if (a->argc < 4) {
14937       return CLI_SHOWUSAGE;
14938    }
14939    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14940    ast_mutex_lock(&iflock);
14941    for (p = iflist; p; p = p->next) {
14942       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14943          continue;
14944       }
14945       if ((channo != -1) && (p->channel != channo )) {
14946          continue;
14947       }
14948       if (ast_true(a->argv[3])) {
14949          openr2_chan_enable_call_files(p->r2chan);
14950       } else {
14951          openr2_chan_disable_call_files(p->r2chan);
14952       }
14953       if (channo != -1) {
14954          if (ast_true(a->argv[3])) {
14955             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14956          } else {
14957             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14958          }
14959          break;
14960       }
14961    }
14962    if ((channo != -1) && !p) {
14963       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14964    }
14965    if (channo == -1) {
14966       if (ast_true(a->argv[3])) {
14967          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14968       } else {
14969          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14970       }
14971    }
14972    ast_mutex_unlock(&iflock);
14973    return CLI_SUCCESS;
14974 }
14975 
14976 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14977 {
14978    struct dahdi_pvt *p = NULL;
14979    int channo = 0;
14980    switch (cmd) {
14981    case CLI_INIT:
14982       e->command = "mfcr2 set idle";
14983       e->usage =
14984          "Usage: mfcr2 set idle <channel>\n"
14985          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14986          "       Force the given channel into IDLE state.\n"
14987          "       If no channel is specified, all channels will be set to IDLE.\n";
14988       return NULL;
14989    case CLI_GENERATE:
14990       return NULL;
14991    }
14992    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14993    ast_mutex_lock(&iflock);
14994    for (p = iflist; p; p = p->next) {
14995       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14996          continue;
14997       }
14998       if ((channo != -1) && (p->channel != channo )) {
14999          continue;
15000       }
15001       openr2_chan_set_idle(p->r2chan);
15002       ast_mutex_lock(&p->lock);
15003       p->locallyblocked = 0;
15004       p->mfcr2call = 0;
15005       ast_mutex_unlock(&p->lock);
15006       if (channo != -1) {
15007          break;
15008       }
15009    }
15010    if ((channo != -1) && !p) {
15011       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15012    }
15013    ast_mutex_unlock(&iflock);
15014    return CLI_SUCCESS;
15015 }
15016 
15017 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15018 {
15019    struct dahdi_pvt *p = NULL;
15020    int channo = 0;
15021    switch (cmd) {
15022    case CLI_INIT:
15023       e->command = "mfcr2 set blocked";
15024       e->usage =
15025          "Usage: mfcr2 set blocked <channel>\n"
15026          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15027          "       Force the given channel into BLOCKED state.\n"
15028          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15029       return NULL;
15030    case CLI_GENERATE:
15031       return NULL;
15032    }
15033    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15034    ast_mutex_lock(&iflock);
15035    for (p = iflist; p; p = p->next) {
15036       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15037          continue;
15038       }
15039       if ((channo != -1) && (p->channel != channo )) {
15040          continue;
15041       }
15042       openr2_chan_set_blocked(p->r2chan);
15043       ast_mutex_lock(&p->lock);
15044       p->locallyblocked = 1;
15045       ast_mutex_unlock(&p->lock);
15046       if (channo != -1) {
15047          break;
15048       }
15049    }
15050    if ((channo != -1) && !p) {
15051       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15052    }
15053    ast_mutex_unlock(&iflock);
15054    return CLI_SUCCESS;
15055 }
15056 
15057 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15058    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15059    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15060    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15061    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15062    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15063    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15064    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15065 };
15066 
15067 #endif /* HAVE_OPENR2 */
15068 
15069 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15070 {
15071    int channel;
15072    int ret;
15073    switch (cmd) {
15074    case CLI_INIT:
15075       e->command = "dahdi destroy channel";
15076       e->usage =
15077          "Usage: dahdi destroy channel <chan num>\n"
15078          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15079       return NULL;
15080    case CLI_GENERATE:
15081       return NULL;
15082    }
15083    if (a->argc != 4)
15084       return CLI_SHOWUSAGE;
15085 
15086    channel = atoi(a->argv[3]);
15087    ret = dahdi_destroy_channel_bynum(channel);
15088    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15089 }
15090 
15091 static void dahdi_softhangup_all(void)
15092 {
15093    struct dahdi_pvt *p;
15094 retry:
15095    ast_mutex_lock(&iflock);
15096    for (p = iflist; p; p = p->next) {
15097       ast_mutex_lock(&p->lock);
15098       if (p->owner && !p->restartpending) {
15099          if (ast_channel_trylock(p->owner)) {
15100             if (option_debug > 2)
15101                ast_verbose("Avoiding deadlock\n");
15102             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15103             ast_mutex_unlock(&p->lock);
15104             ast_mutex_unlock(&iflock);
15105             goto retry;
15106          }
15107          if (option_debug > 2)
15108             ast_verbose("Softhanging up on %s\n", p->owner->name);
15109          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15110          p->restartpending = 1;
15111          num_restart_pending++;
15112          ast_channel_unlock(p->owner);
15113       }
15114       ast_mutex_unlock(&p->lock);
15115    }
15116    ast_mutex_unlock(&iflock);
15117 }
15118 
15119 static int setup_dahdi(int reload);
15120 static int dahdi_restart(void)
15121 {
15122 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15123    int i, j;
15124 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15125    int cancel_code;
15126    struct dahdi_pvt *p;
15127 
15128    ast_mutex_lock(&restart_lock);
15129    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15130    dahdi_softhangup_all();
15131    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15132 #ifdef HAVE_OPENR2
15133    dahdi_r2_destroy_links();
15134 #endif
15135 
15136 #if defined(HAVE_PRI)
15137    for (i = 0; i < NUM_SPANS; i++) {
15138       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15139          cancel_code = pthread_cancel(pris[i].pri.master);
15140          pthread_kill(pris[i].pri.master, SIGURG);
15141          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);
15142          pthread_join(pris[i].pri.master, NULL);
15143          ast_debug(4, "Joined thread of span %d\n", i);
15144       }
15145    }
15146 #endif
15147 
15148 #if defined(HAVE_SS7)
15149    for (i = 0; i < NUM_SPANS; i++) {
15150       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15151          cancel_code = pthread_cancel(linksets[i].ss7.master);
15152          pthread_kill(linksets[i].ss7.master, SIGURG);
15153          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);
15154          pthread_join(linksets[i].ss7.master, NULL);
15155          ast_debug(4, "Joined thread of span %d\n", i);
15156       }
15157    }
15158 #endif   /* defined(HAVE_SS7) */
15159 
15160    ast_mutex_lock(&monlock);
15161    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15162       cancel_code = pthread_cancel(monitor_thread);
15163       pthread_kill(monitor_thread, SIGURG);
15164       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15165       pthread_join(monitor_thread, NULL);
15166       ast_debug(4, "Joined monitor thread\n");
15167    }
15168    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15169 
15170    ast_mutex_lock(&ss_thread_lock);
15171    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15172       int x = DAHDI_FLASH;
15173       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15174 
15175       ast_mutex_lock(&iflock);
15176       for (p = iflist; p; p = p->next) {
15177          if (p->owner) {
15178             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15179             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15180          }
15181       }
15182       ast_mutex_unlock(&iflock);
15183       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15184    }
15185 
15186    /* ensure any created channels before monitor threads were stopped are hungup */
15187    dahdi_softhangup_all();
15188    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15189    destroy_all_channels();
15190    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15191 
15192    ast_mutex_unlock(&monlock);
15193 
15194 #ifdef HAVE_PRI
15195    for (i = 0; i < NUM_SPANS; i++) {
15196       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15197          dahdi_close_pri_fd(&(pris[i]), j);
15198    }
15199 
15200    memset(pris, 0, sizeof(pris));
15201    for (i = 0; i < NUM_SPANS; i++) {
15202       sig_pri_init_pri(&pris[i].pri);
15203    }
15204    pri_set_error(dahdi_pri_error);
15205    pri_set_message(dahdi_pri_message);
15206 #endif
15207 #if defined(HAVE_SS7)
15208    for (i = 0; i < NUM_SPANS; i++) {
15209       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15210          dahdi_close_ss7_fd(&(linksets[i]), j);
15211    }
15212 
15213    memset(linksets, 0, sizeof(linksets));
15214    for (i = 0; i < NUM_SPANS; i++) {
15215       sig_ss7_init_linkset(&linksets[i].ss7);
15216    }
15217    ss7_set_error(dahdi_ss7_error);
15218    ss7_set_message(dahdi_ss7_message);
15219 #endif   /* defined(HAVE_SS7) */
15220 
15221    if (setup_dahdi(2) != 0) {
15222       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15223       ast_mutex_unlock(&ss_thread_lock);
15224       return 1;
15225    }
15226    ast_mutex_unlock(&ss_thread_lock);
15227    ast_mutex_unlock(&restart_lock);
15228    return 0;
15229 }
15230 
15231 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15232 {
15233    switch (cmd) {
15234    case CLI_INIT:
15235       e->command = "dahdi restart";
15236       e->usage =
15237          "Usage: dahdi restart\n"
15238          "  Restarts the DAHDI channels: destroys them all and then\n"
15239          "  re-reads them from chan_dahdi.conf.\n"
15240          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15241          "";
15242       return NULL;
15243    case CLI_GENERATE:
15244       return NULL;
15245    }
15246    if (a->argc != 2)
15247       return CLI_SHOWUSAGE;
15248 
15249    if (dahdi_restart() != 0)
15250       return CLI_FAILURE;
15251    return CLI_SUCCESS;
15252 }
15253 
15254 static int action_dahdirestart(struct mansession *s, const struct message *m)
15255 {
15256    if (dahdi_restart() != 0) {
15257       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15258       return 1;
15259    }
15260    astman_send_ack(s, m, "DAHDIRestart: Success");
15261    return 0;
15262 }
15263 
15264 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15265 {
15266 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15267 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15268    ast_group_t targetnum = 0;
15269    int filtertype = 0;
15270    struct dahdi_pvt *tmp = NULL;
15271    char tmps[20] = "";
15272    char statestr[20] = "";
15273    char blockstr[20] = "";
15274 
15275    switch (cmd) {
15276    case CLI_INIT:
15277       e->command = "dahdi show channels [group|context]";
15278       e->usage =
15279          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15280          "  Shows a list of available channels with optional filtering\n"
15281          "  <group> must be a number between 0 and 63\n";
15282       return NULL;
15283    case CLI_GENERATE:
15284       return NULL;
15285    }
15286 
15287    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15288 
15289    if (!((a->argc == 3) || (a->argc == 5)))
15290       return CLI_SHOWUSAGE;
15291 
15292    if (a->argc == 5) {
15293       if (!strcasecmp(a->argv[3], "group")) {
15294          targetnum = atoi(a->argv[4]);
15295          if (63 < targetnum) {
15296             return CLI_SHOWUSAGE;
15297          }
15298          targetnum = ((ast_group_t) 1) << targetnum;
15299          filtertype = 1;
15300       } else if (!strcasecmp(a->argv[3], "context")) {
15301          filtertype = 2;
15302       }
15303    }
15304 
15305    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15306    ast_mutex_lock(&iflock);
15307    for (tmp = iflist; tmp; tmp = tmp->next) {
15308       if (filtertype) {
15309          switch(filtertype) {
15310          case 1: /* dahdi show channels group <group> */
15311             if (!(tmp->group & targetnum)) {
15312                continue;
15313             }
15314             break;
15315          case 2: /* dahdi show channels context <context> */
15316             if (strcasecmp(tmp->context, a->argv[4])) {
15317                continue;
15318             }
15319             break;
15320          default:
15321             break;
15322          }
15323       }
15324       if (tmp->channel > 0) {
15325          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15326       } else
15327          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15328 
15329       if (tmp->locallyblocked)
15330          blockstr[0] = 'L';
15331       else
15332          blockstr[0] = ' ';
15333 
15334       if (tmp->remotelyblocked)
15335          blockstr[1] = 'R';
15336       else
15337          blockstr[1] = ' ';
15338 
15339       blockstr[2] = '\0';
15340 
15341       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15342 
15343       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15344    }
15345    ast_mutex_unlock(&iflock);
15346    return CLI_SUCCESS;
15347 #undef FORMAT
15348 #undef FORMAT2
15349 }
15350 
15351 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15352 {
15353    int channel;
15354    struct dahdi_pvt *tmp = NULL;
15355    struct dahdi_confinfo ci;
15356    struct dahdi_params ps;
15357    int x;
15358 
15359    switch (cmd) {
15360    case CLI_INIT:
15361       e->command = "dahdi show channel";
15362       e->usage =
15363          "Usage: dahdi show channel <chan num>\n"
15364          "  Detailed information about a given channel\n";
15365       return NULL;
15366    case CLI_GENERATE:
15367       return NULL;
15368    }
15369 
15370    if (a->argc != 4)
15371       return CLI_SHOWUSAGE;
15372 
15373    channel = atoi(a->argv[3]);
15374 
15375    ast_mutex_lock(&iflock);
15376    for (tmp = iflist; tmp; tmp = tmp->next) {
15377       if (tmp->channel == channel) {
15378          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15379          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15380          ast_cli(a->fd, "Span: %d\n", tmp->span);
15381          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15382          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15383          ast_cli(a->fd, "Context: %s\n", tmp->context);
15384          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15385          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15386 #if defined(HAVE_PRI)
15387 #if defined(HAVE_PRI_SUBADDR)
15388          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15389 #endif   /* defined(HAVE_PRI_SUBADDR) */
15390 #endif   /* defined(HAVE_PRI) */
15391          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15392          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15393          if (tmp->vars) {
15394             struct ast_variable *v;
15395             ast_cli(a->fd, "Variables:\n");
15396             for (v = tmp->vars ; v ; v = v->next)
15397                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15398          }
15399          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15400          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15401          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15402          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15403          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15404          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)" : "");
15405          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)" : "");
15406          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)" : "");
15407          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15408          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15409          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15410          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15411          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15412          if (tmp->busydetect) {
15413 #if defined(BUSYDETECT_TONEONLY)
15414             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15415 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15416             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15417 #endif
15418 #ifdef BUSYDETECT_DEBUG
15419             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15420 #endif
15421             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15422             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15423          }
15424          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15425          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15426          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15427          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15428          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15429          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15430          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15431          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15432          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15433          ast_cli(a->fd, "Echo Cancellation:\n");
15434 
15435          if (tmp->echocancel.head.tap_length) {
15436             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15437             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15438                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15439             }
15440             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15441          } else {
15442             ast_cli(a->fd, "\tnone\n");
15443          }
15444          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15445          if (tmp->master)
15446             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15447          for (x = 0; x < MAX_SLAVES; x++) {
15448             if (tmp->slaves[x])
15449                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15450          }
15451 #ifdef HAVE_OPENR2
15452          if (tmp->mfcr2) {
15453             char calldir[OR2_MAX_PATH];
15454             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15455             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15456             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15457             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15458             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15459             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15460             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15461             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15462             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15463             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15464             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15465 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15466             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15467 #endif
15468             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15469             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15470             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15471             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15472             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15473             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15474             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15475             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15476             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15477             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15478             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15479             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15480          }
15481 #endif
15482 #if defined(HAVE_SS7)
15483          if (tmp->ss7) {
15484             struct sig_ss7_chan *chan = tmp->sig_pvt;
15485 
15486             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15487          }
15488 #endif   /* defined(HAVE_SS7) */
15489 #ifdef HAVE_PRI
15490          if (tmp->pri) {
15491             struct sig_pri_chan *chan = tmp->sig_pvt;
15492 
15493             ast_cli(a->fd, "PRI Flags: ");
15494             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15495                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15496             }
15497             if (chan->call)
15498                ast_cli(a->fd, "Call ");
15499             if (chan->allocated) {
15500                ast_cli(a->fd, "Allocated ");
15501             }
15502             ast_cli(a->fd, "\n");
15503             if (tmp->logicalspan)
15504                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15505             else
15506                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15507          }
15508 #endif
15509          memset(&ci, 0, sizeof(ci));
15510          ps.channo = tmp->channel;
15511          if (tmp->subs[SUB_REAL].dfd > -1) {
15512             memset(&ci, 0, sizeof(ci));
15513             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15514                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15515             }
15516             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15517                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15518             }
15519             memset(&ps, 0, sizeof(ps));
15520             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15521                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15522             } else {
15523                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15524             }
15525          }
15526          if (ISTRUNK(tmp)) {
15527             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15528             if (!ast_strlen_zero(progzone))
15529                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15530             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15531             if(tmp->busydetect) {
15532                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15533                if(tmp->busytonelength > 0) {
15534                   ast_cli(a->fd, "Busy Pattern:\n");
15535                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15536                   if (tmp->busyquietlength > 0) 
15537                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15538                   else 
15539                      ast_cli(a->fd, " -- Detect Tone Only\n");
15540                   if(tmp->busyfuzziness > 0)
15541                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15542                }
15543             }
15544          }
15545          ast_mutex_unlock(&iflock);
15546          return CLI_SUCCESS;
15547       }
15548    }
15549    ast_mutex_unlock(&iflock);
15550 
15551    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15552    return CLI_FAILURE;
15553 }
15554 
15555 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15556 {
15557    int i, j;
15558    switch (cmd) {
15559    case CLI_INIT:
15560       e->command = "dahdi show cadences";
15561       e->usage =
15562          "Usage: dahdi show cadences\n"
15563          "       Shows all cadences currently defined\n";
15564       return NULL;
15565    case CLI_GENERATE:
15566       return NULL;
15567    }
15568    for (i = 0; i < num_cadence; i++) {
15569       char output[1024];
15570       char tmp[16], tmp2[64];
15571       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15572       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15573 
15574       for (j = 0; j < 16; j++) {
15575          if (cadences[i].ringcadence[j] == 0)
15576             break;
15577          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15578          if (cidrings[i] * 2 - 1 == j)
15579             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15580          else
15581             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15582          if (j != 0)
15583             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15584          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15585       }
15586       ast_cli(a->fd,"%s\n",output);
15587    }
15588    return CLI_SUCCESS;
15589 }
15590 
15591 /* Based on irqmiss.c */
15592 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15593 {
15594    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15595    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15596    int span;
15597    int res;
15598    char alarmstr[50];
15599 
15600    int ctl;
15601    struct dahdi_spaninfo s;
15602 
15603    switch (cmd) {
15604    case CLI_INIT:
15605       e->command = "dahdi show status";
15606       e->usage =
15607          "Usage: dahdi show status\n"
15608          "       Shows a list of DAHDI cards with status\n";
15609       return NULL;
15610    case CLI_GENERATE:
15611       return NULL;
15612    }
15613    ctl = open("/dev/dahdi/ctl", O_RDWR);
15614    if (ctl < 0) {
15615       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15616       return CLI_FAILURE;
15617    }
15618    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15619 
15620    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15621       s.spanno = span;
15622       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15623       if (res) {
15624          continue;
15625       }
15626       alarmstr[0] = '\0';
15627       if (s.alarms > 0) {
15628          if (s.alarms & DAHDI_ALARM_BLUE)
15629             strcat(alarmstr, "BLU/");
15630          if (s.alarms & DAHDI_ALARM_YELLOW)
15631             strcat(alarmstr, "YEL/");
15632          if (s.alarms & DAHDI_ALARM_RED)
15633             strcat(alarmstr, "RED/");
15634          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15635             strcat(alarmstr, "LB/");
15636          if (s.alarms & DAHDI_ALARM_RECOVER)
15637             strcat(alarmstr, "REC/");
15638          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15639             strcat(alarmstr, "NOP/");
15640          if (!strlen(alarmstr))
15641             strcat(alarmstr, "UUU/");
15642          if (strlen(alarmstr)) {
15643             /* Strip trailing / */
15644             alarmstr[strlen(alarmstr) - 1] = '\0';
15645          }
15646       } else {
15647          if (s.numchans)
15648             strcpy(alarmstr, "OK");
15649          else
15650             strcpy(alarmstr, "UNCONFIGURED");
15651       }
15652 
15653       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15654          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15655          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15656          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15657          "CAS",
15658          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15659          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15660          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15661          "Unk",
15662          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15663             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15664             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15665          lbostr[s.lbo]
15666          );
15667    }
15668    close(ctl);
15669 
15670    return CLI_SUCCESS;
15671 #undef FORMAT
15672 #undef FORMAT2
15673 }
15674 
15675 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15676 {
15677    int pseudo_fd = -1;
15678    struct dahdi_versioninfo vi;
15679 
15680    switch (cmd) {
15681    case CLI_INIT:
15682       e->command = "dahdi show version";
15683       e->usage =
15684          "Usage: dahdi show version\n"
15685          "       Shows the DAHDI version in use\n";
15686       return NULL;
15687    case CLI_GENERATE:
15688       return NULL;
15689    }
15690    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15691       ast_cli(a->fd, "Failed to open control file to get version.\n");
15692       return CLI_SUCCESS;
15693    }
15694 
15695    strcpy(vi.version, "Unknown");
15696    strcpy(vi.echo_canceller, "Unknown");
15697 
15698    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15699       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15700    else
15701       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15702 
15703    close(pseudo_fd);
15704 
15705    return CLI_SUCCESS;
15706 }
15707 
15708 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15709 {
15710    int channel;
15711    int gain;
15712    int tx;
15713    struct dahdi_hwgain hwgain;
15714    struct dahdi_pvt *tmp = NULL;
15715 
15716    switch (cmd) {
15717    case CLI_INIT:
15718       e->command = "dahdi set hwgain";
15719       e->usage =
15720          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15721          "  Sets the hardware gain on a a given channel, overriding the\n"
15722          "   value provided at module loadtime, whether the channel is in\n"
15723          "   use or not.  Changes take effect immediately.\n"
15724          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15725          "   <chan num> is the channel number relative to the device\n"
15726          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15727       return NULL;
15728    case CLI_GENERATE:
15729       return NULL;
15730    }
15731 
15732    if (a->argc != 6)
15733       return CLI_SHOWUSAGE;
15734 
15735    if (!strcasecmp("rx", a->argv[3]))
15736       tx = 0; /* rx */
15737    else if (!strcasecmp("tx", a->argv[3]))
15738       tx = 1; /* tx */
15739    else
15740       return CLI_SHOWUSAGE;
15741 
15742    channel = atoi(a->argv[4]);
15743    gain = atof(a->argv[5])*10.0;
15744 
15745    ast_mutex_lock(&iflock);
15746 
15747    for (tmp = iflist; tmp; tmp = tmp->next) {
15748 
15749       if (tmp->channel != channel)
15750          continue;
15751 
15752       if (tmp->subs[SUB_REAL].dfd == -1)
15753          break;
15754 
15755       hwgain.newgain = gain;
15756       hwgain.tx = tx;
15757       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15758          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15759          ast_mutex_unlock(&iflock);
15760          return CLI_FAILURE;
15761       }
15762       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15763          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15764       break;
15765    }
15766 
15767    ast_mutex_unlock(&iflock);
15768 
15769    if (tmp)
15770       return CLI_SUCCESS;
15771 
15772    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15773    return CLI_FAILURE;
15774 
15775 }
15776 
15777 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15778 {
15779    int channel;
15780    float gain;
15781    int tx;
15782    int res;
15783    struct dahdi_pvt *tmp = NULL;
15784 
15785    switch (cmd) {
15786    case CLI_INIT:
15787       e->command = "dahdi set swgain";
15788       e->usage =
15789          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15790          "  Sets the software gain on a a given channel, overriding the\n"
15791          "   value provided at module loadtime, whether the channel is in\n"
15792          "   use or not.  Changes take effect immediately.\n"
15793          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15794          "   <chan num> is the channel number relative to the device\n"
15795          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15796       return NULL;
15797    case CLI_GENERATE:
15798       return NULL;
15799    }
15800 
15801    if (a->argc != 6)
15802       return CLI_SHOWUSAGE;
15803 
15804    if (!strcasecmp("rx", a->argv[3]))
15805       tx = 0; /* rx */
15806    else if (!strcasecmp("tx", a->argv[3]))
15807       tx = 1; /* tx */
15808    else
15809       return CLI_SHOWUSAGE;
15810 
15811    channel = atoi(a->argv[4]);
15812    gain = atof(a->argv[5]);
15813 
15814    ast_mutex_lock(&iflock);
15815    for (tmp = iflist; tmp; tmp = tmp->next) {
15816 
15817       if (tmp->channel != channel)
15818          continue;
15819 
15820       if (tmp->subs[SUB_REAL].dfd == -1)
15821          break;
15822 
15823       if (tx)
15824          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15825       else
15826          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15827 
15828       if (res) {
15829          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15830          ast_mutex_unlock(&iflock);
15831          return CLI_FAILURE;
15832       }
15833 
15834       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15835          tx ? "tx" : "rx", gain, channel);
15836       break;
15837    }
15838    ast_mutex_unlock(&iflock);
15839 
15840    if (tmp)
15841       return CLI_SUCCESS;
15842 
15843    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15844    return CLI_FAILURE;
15845 
15846 }
15847 
15848 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15849 {
15850    int channel;
15851    int on;
15852    struct dahdi_pvt *dahdi_chan = NULL;
15853 
15854    switch (cmd) {
15855    case CLI_INIT:
15856       e->command = "dahdi set dnd";
15857       e->usage =
15858          "Usage: dahdi set dnd <chan#> <on|off>\n"
15859          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15860          "  Changes take effect immediately.\n"
15861          "  <chan num> is the channel number\n"
15862          "  <on|off> Enable or disable DND mode?\n"
15863          ;
15864       return NULL;
15865    case CLI_GENERATE:
15866       return NULL;
15867    }
15868 
15869    if (a->argc != 5)
15870       return CLI_SHOWUSAGE;
15871 
15872    if ((channel = atoi(a->argv[3])) <= 0) {
15873       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15874       return CLI_SHOWUSAGE;
15875    }
15876 
15877    if (ast_true(a->argv[4]))
15878       on = 1;
15879    else if (ast_false(a->argv[4]))
15880       on = 0;
15881    else {
15882       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15883       return CLI_SHOWUSAGE;
15884    }
15885 
15886    ast_mutex_lock(&iflock);
15887    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15888       if (dahdi_chan->channel != channel)
15889          continue;
15890 
15891       /* Found the channel. Actually set it */
15892       dahdi_dnd(dahdi_chan, on);
15893       break;
15894    }
15895    ast_mutex_unlock(&iflock);
15896 
15897    if (!dahdi_chan) {
15898       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15899       return CLI_FAILURE;
15900    }
15901 
15902    return CLI_SUCCESS;
15903 }
15904 
15905 static struct ast_cli_entry dahdi_cli[] = {
15906    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15907    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15908    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15909    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15910    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15911    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15912    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15913    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15914    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15915    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15916 };
15917 
15918 #define TRANSFER  0
15919 #define HANGUP    1
15920 
15921 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15922 {
15923    if (p) {
15924       switch (mode) {
15925       case TRANSFER:
15926          p->fake_event = DAHDI_EVENT_WINKFLASH;
15927          break;
15928       case HANGUP:
15929          p->fake_event = DAHDI_EVENT_ONHOOK;
15930          break;
15931       default:
15932          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15933       }
15934    }
15935    return 0;
15936 }
15937 static struct dahdi_pvt *find_channel(int channel)
15938 {
15939    struct dahdi_pvt *p;
15940 
15941    ast_mutex_lock(&iflock);
15942    for (p = iflist; p; p = p->next) {
15943       if (p->channel == channel) {
15944          break;
15945       }
15946    }
15947    ast_mutex_unlock(&iflock);
15948    return p;
15949 }
15950 
15951 /*!
15952  * \internal
15953  * \brief Get private struct using given numeric channel string.
15954  *
15955  * \param channel Numeric channel number string get private struct.
15956  *
15957  * \retval pvt on success.
15958  * \retval NULL on error.
15959  */
15960 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15961 {
15962    int chan_num;
15963 
15964    if (sscanf(channel, "%30d", &chan_num) != 1) {
15965       /* Not numeric string. */
15966       return NULL;
15967    }
15968 
15969    return find_channel(chan_num);
15970 }
15971 
15972 static int action_dahdidndon(struct mansession *s, const struct message *m)
15973 {
15974    struct dahdi_pvt *p;
15975    const char *channel = astman_get_header(m, "DAHDIChannel");
15976 
15977    if (ast_strlen_zero(channel)) {
15978       astman_send_error(s, m, "No channel specified");
15979       return 0;
15980    }
15981    p = find_channel_from_str(channel);
15982    if (!p) {
15983       astman_send_error(s, m, "No such channel");
15984       return 0;
15985    }
15986    dahdi_dnd(p, 1);
15987    astman_send_ack(s, m, "DND Enabled");
15988    return 0;
15989 }
15990 
15991 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15992 {
15993    struct dahdi_pvt *p;
15994    const char *channel = astman_get_header(m, "DAHDIChannel");
15995 
15996    if (ast_strlen_zero(channel)) {
15997       astman_send_error(s, m, "No channel specified");
15998       return 0;
15999    }
16000    p = find_channel_from_str(channel);
16001    if (!p) {
16002       astman_send_error(s, m, "No such channel");
16003       return 0;
16004    }
16005    dahdi_dnd(p, 0);
16006    astman_send_ack(s, m, "DND Disabled");
16007    return 0;
16008 }
16009 
16010 static int action_transfer(struct mansession *s, const struct message *m)
16011 {
16012    struct dahdi_pvt *p;
16013    const char *channel = astman_get_header(m, "DAHDIChannel");
16014 
16015    if (ast_strlen_zero(channel)) {
16016       astman_send_error(s, m, "No channel specified");
16017       return 0;
16018    }
16019    p = find_channel_from_str(channel);
16020    if (!p) {
16021       astman_send_error(s, m, "No such channel");
16022       return 0;
16023    }
16024    if (!analog_lib_handles(p->sig, 0, 0)) {
16025       astman_send_error(s, m, "Channel signaling is not analog");
16026       return 0;
16027    }
16028    dahdi_fake_event(p,TRANSFER);
16029    astman_send_ack(s, m, "DAHDITransfer");
16030    return 0;
16031 }
16032 
16033 static int action_transferhangup(struct mansession *s, const struct message *m)
16034 {
16035    struct dahdi_pvt *p;
16036    const char *channel = astman_get_header(m, "DAHDIChannel");
16037 
16038    if (ast_strlen_zero(channel)) {
16039       astman_send_error(s, m, "No channel specified");
16040       return 0;
16041    }
16042    p = find_channel_from_str(channel);
16043    if (!p) {
16044       astman_send_error(s, m, "No such channel");
16045       return 0;
16046    }
16047    if (!analog_lib_handles(p->sig, 0, 0)) {
16048       astman_send_error(s, m, "Channel signaling is not analog");
16049       return 0;
16050    }
16051    dahdi_fake_event(p,HANGUP);
16052    astman_send_ack(s, m, "DAHDIHangup");
16053    return 0;
16054 }
16055 
16056 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16057 {
16058    struct dahdi_pvt *p;
16059    const char *channel = astman_get_header(m, "DAHDIChannel");
16060    const char *number = astman_get_header(m, "Number");
16061    int i;
16062 
16063    if (ast_strlen_zero(channel)) {
16064       astman_send_error(s, m, "No channel specified");
16065       return 0;
16066    }
16067    if (ast_strlen_zero(number)) {
16068       astman_send_error(s, m, "No number specified");
16069       return 0;
16070    }
16071    p = find_channel_from_str(channel);
16072    if (!p) {
16073       astman_send_error(s, m, "No such channel");
16074       return 0;
16075    }
16076    if (!p->owner) {
16077       astman_send_error(s, m, "Channel does not have it's owner");
16078       return 0;
16079    }
16080    for (i = 0; i < strlen(number); i++) {
16081       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16082       dahdi_queue_frame(p, &f);
16083    }
16084    astman_send_ack(s, m, "DAHDIDialOffhook");
16085    return 0;
16086 }
16087 
16088 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16089 {
16090    struct dahdi_pvt *tmp = NULL;
16091    const char *id = astman_get_header(m, "ActionID");
16092    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16093    char idText[256] = "";
16094    int channels = 0;
16095    int dahdichanquery;
16096 
16097    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16098       /* Not numeric string. */
16099       dahdichanquery = -1;
16100    }
16101 
16102    astman_send_ack(s, m, "DAHDI channel status will follow");
16103    if (!ast_strlen_zero(id))
16104       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16105 
16106    ast_mutex_lock(&iflock);
16107 
16108    for (tmp = iflist; tmp; tmp = tmp->next) {
16109       if (tmp->channel > 0) {
16110          int alm;
16111 
16112          /* If a specific channel is queried for, only deliver status for that channel */
16113          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16114             continue;
16115 
16116          alm = get_alarms(tmp);
16117          channels++;
16118          if (tmp->owner) {
16119             /* Add data if we have a current call */
16120             astman_append(s,
16121                "Event: DAHDIShowChannels\r\n"
16122                "DAHDIChannel: %d\r\n"
16123                "Channel: %s\r\n"
16124                "Uniqueid: %s\r\n"
16125                "AccountCode: %s\r\n"
16126                "Signalling: %s\r\n"
16127                "SignallingCode: %d\r\n"
16128                "Context: %s\r\n"
16129                "DND: %s\r\n"
16130                "Alarm: %s\r\n"
16131                "%s"
16132                "\r\n",
16133                tmp->channel,
16134                tmp->owner->name,
16135                tmp->owner->uniqueid,
16136                tmp->owner->accountcode,
16137                sig2str(tmp->sig),
16138                tmp->sig,
16139                tmp->context,
16140                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16141                alarm2str(alm), idText);
16142          } else {
16143             astman_append(s,
16144                "Event: DAHDIShowChannels\r\n"
16145                "DAHDIChannel: %d\r\n"
16146                "Signalling: %s\r\n"
16147                "SignallingCode: %d\r\n"
16148                "Context: %s\r\n"
16149                "DND: %s\r\n"
16150                "Alarm: %s\r\n"
16151                "%s"
16152                "\r\n",
16153                tmp->channel, sig2str(tmp->sig), tmp->sig,
16154                tmp->context,
16155                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16156                alarm2str(alm), idText);
16157          }
16158       }
16159    }
16160 
16161    ast_mutex_unlock(&iflock);
16162 
16163    astman_append(s,
16164       "Event: DAHDIShowChannelsComplete\r\n"
16165       "%s"
16166       "Items: %d\r\n"
16167       "\r\n",
16168       idText,
16169       channels);
16170    return 0;
16171 }
16172 
16173 #if defined(HAVE_SS7)
16174 static int linkset_addsigchan(int sigchan)
16175 {
16176    struct dahdi_ss7 *link;
16177    int res;
16178    int curfd;
16179    struct dahdi_params params;
16180    struct dahdi_bufferinfo bi;
16181    struct dahdi_spaninfo si;
16182 
16183    if (sigchan < 0) {
16184       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16185       return -1;
16186    }
16187    if (cur_ss7type < 0) {
16188       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16189       return -1;
16190    }
16191    if (cur_pointcode < 0) {
16192       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16193       return -1;
16194    }
16195    if (cur_adjpointcode < 0) {
16196       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16197       return -1;
16198    }
16199    if (cur_defaultdpc < 0) {
16200       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16201       return -1;
16202    }
16203    if (cur_networkindicator < 0) {
16204       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16205       return -1;
16206    }
16207    link = ss7_resolve_linkset(cur_linkset);
16208    if (!link) {
16209       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16210       return -1;
16211    }
16212    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16213       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16214       return -1;
16215    }
16216 
16217    curfd = link->ss7.numsigchans;
16218 
16219    /* Open signaling channel */
16220    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16221    if (link->ss7.fds[curfd] < 0) {
16222       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16223          strerror(errno));
16224       return -1;
16225    }
16226    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16227       dahdi_close_ss7_fd(link, curfd);
16228       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16229          strerror(errno));
16230       return -1;
16231    }
16232 
16233    /* Get signaling channel parameters */
16234    memset(&params, 0, sizeof(params));
16235    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16236    if (res) {
16237       dahdi_close_ss7_fd(link, curfd);
16238       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16239          strerror(errno));
16240       return -1;
16241    }
16242    if (params.sigtype != DAHDI_SIG_HDLCFCS
16243       && params.sigtype != DAHDI_SIG_HARDHDLC
16244       && params.sigtype != DAHDI_SIG_MTP2) {
16245       dahdi_close_ss7_fd(link, curfd);
16246       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16247       return -1;
16248    }
16249 
16250    /* Set signaling channel buffer policy. */
16251    memset(&bi, 0, sizeof(bi));
16252    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16253    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16254    bi.numbufs = 32;
16255    bi.bufsize = 512;
16256    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16257       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16258          sigchan, strerror(errno));
16259       dahdi_close_ss7_fd(link, curfd);
16260       return -1;
16261    }
16262 
16263    /* Get current signaling channel alarm status. */
16264    memset(&si, 0, sizeof(si));
16265    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16266    if (res) {
16267       dahdi_close_ss7_fd(link, curfd);
16268       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16269          strerror(errno));
16270    }
16271 
16272    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16273       (params.sigtype == DAHDI_SIG_MTP2)
16274          ? SS7_TRANSPORT_DAHDIMTP2
16275          : SS7_TRANSPORT_DAHDIDCHAN,
16276       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16277    if (res) {
16278       dahdi_close_ss7_fd(link, curfd);
16279       return -1;
16280    }
16281 
16282    ++link->ss7.numsigchans;
16283 
16284    return 0;
16285 }
16286 #endif   /* defined(HAVE_SS7) */
16287 
16288 #if defined(HAVE_SS7)
16289 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16290 {
16291    int span;
16292    switch (cmd) {
16293    case CLI_INIT:
16294       e->command = "ss7 set debug {on|off} linkset";
16295       e->usage =
16296          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16297          "       Enables debugging on a given SS7 linkset\n";
16298       return NULL;
16299    case CLI_GENERATE:
16300       return NULL;
16301    }
16302    if (a->argc < 6)
16303       return CLI_SHOWUSAGE;
16304    span = atoi(a->argv[5]);
16305    if ((span < 1) || (span > NUM_SPANS)) {
16306       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16307       return CLI_SUCCESS;
16308    }
16309    if (!linksets[span-1].ss7.ss7) {
16310       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16311    } else {
16312       if (!strcasecmp(a->argv[3], "on")) {
16313          linksets[span - 1].ss7.debug = 1;
16314          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16315          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16316       } else {
16317          linksets[span - 1].ss7.debug = 0;
16318          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16319          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16320       }
16321    }
16322 
16323    return CLI_SUCCESS;
16324 }
16325 #endif   /* defined(HAVE_SS7) */
16326 
16327 #if defined(HAVE_SS7)
16328 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16329 {
16330    int linkset, cic;
16331    int blocked = -1, i;
16332    switch (cmd) {
16333    case CLI_INIT:
16334       e->command = "ss7 block cic";
16335       e->usage =
16336          "Usage: ss7 block cic <linkset> <CIC>\n"
16337          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16338       return NULL;
16339    case CLI_GENERATE:
16340       return NULL;
16341    }
16342    if (a->argc == 5)
16343       linkset = atoi(a->argv[3]);
16344    else
16345       return CLI_SHOWUSAGE;
16346 
16347    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16348       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16349       return CLI_SUCCESS;
16350    }
16351 
16352    if (!linksets[linkset-1].ss7.ss7) {
16353       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16354       return CLI_SUCCESS;
16355    }
16356 
16357    cic = atoi(a->argv[4]);
16358 
16359    if (cic < 1) {
16360       ast_cli(a->fd, "Invalid CIC specified!\n");
16361       return CLI_SUCCESS;
16362    }
16363 
16364    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16365       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16366          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16367          if (!blocked) {
16368             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16369             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16370             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16371          }
16372       }
16373    }
16374 
16375    if (blocked < 0) {
16376       ast_cli(a->fd, "Invalid CIC specified!\n");
16377       return CLI_SUCCESS;
16378    }
16379 
16380    if (!blocked)
16381       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16382    else
16383       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16384 
16385    /* Break poll on the linkset so it sends our messages */
16386    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16387 
16388    return CLI_SUCCESS;
16389 }
16390 #endif   /* defined(HAVE_SS7) */
16391 
16392 #if defined(HAVE_SS7)
16393 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16394 {
16395    int linkset;
16396    int i;
16397    switch (cmd) {
16398    case CLI_INIT:
16399       e->command = "ss7 block linkset";
16400       e->usage =
16401          "Usage: ss7 block linkset <linkset number>\n"
16402          "       Sends a remote blocking request for all CICs on the given linkset\n";
16403       return NULL;
16404    case CLI_GENERATE:
16405       return NULL;
16406    }
16407    if (a->argc == 4)
16408       linkset = atoi(a->argv[3]);
16409    else
16410       return CLI_SHOWUSAGE;
16411 
16412    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16413       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16414       return CLI_SUCCESS;
16415    }
16416 
16417    if (!linksets[linkset-1].ss7.ss7) {
16418       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16419       return CLI_SUCCESS;
16420    }
16421 
16422    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16423       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16424       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16425       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16426       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16427    }
16428 
16429    /* Break poll on the linkset so it sends our messages */
16430    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16431 
16432    return CLI_SUCCESS;
16433 }
16434 #endif   /* defined(HAVE_SS7) */
16435 
16436 #if defined(HAVE_SS7)
16437 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16438 {
16439    int linkset, cic;
16440    int i, blocked = -1;
16441    switch (cmd) {
16442    case CLI_INIT:
16443       e->command = "ss7 unblock cic";
16444       e->usage =
16445          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16446          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16447       return NULL;
16448    case CLI_GENERATE:
16449       return NULL;
16450    }
16451 
16452    if (a->argc == 5)
16453       linkset = atoi(a->argv[3]);
16454    else
16455       return CLI_SHOWUSAGE;
16456 
16457    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16458       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16459       return CLI_SUCCESS;
16460    }
16461 
16462    if (!linksets[linkset-1].ss7.ss7) {
16463       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16464       return CLI_SUCCESS;
16465    }
16466 
16467    cic = atoi(a->argv[4]);
16468 
16469    if (cic < 1) {
16470       ast_cli(a->fd, "Invalid CIC specified!\n");
16471       return CLI_SUCCESS;
16472    }
16473 
16474    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16475       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16476          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16477          if (blocked) {
16478             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16479             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16480             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16481          }
16482       }
16483    }
16484 
16485    if (blocked > 0)
16486       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16487 
16488    /* Break poll on the linkset so it sends our messages */
16489    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16490 
16491    return CLI_SUCCESS;
16492 }
16493 #endif   /* defined(HAVE_SS7) */
16494 
16495 #if defined(HAVE_SS7)
16496 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16497 {
16498    int linkset;
16499    int i;
16500    switch (cmd) {
16501    case CLI_INIT:
16502       e->command = "ss7 unblock linkset";
16503       e->usage =
16504          "Usage: ss7 unblock linkset <linkset number>\n"
16505          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16506       return NULL;
16507    case CLI_GENERATE:
16508       return NULL;
16509    }
16510 
16511    if (a->argc == 4)
16512       linkset = atoi(a->argv[3]);
16513    else
16514       return CLI_SHOWUSAGE;
16515 
16516    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16517       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16518       return CLI_SUCCESS;
16519    }
16520 
16521    if (!linksets[linkset-1].ss7.ss7) {
16522       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16523       return CLI_SUCCESS;
16524    }
16525 
16526    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16527       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16528       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16529       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16530       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16531    }
16532 
16533    /* Break poll on the linkset so it sends our messages */
16534    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16535 
16536    return CLI_SUCCESS;
16537 }
16538 #endif   /* defined(HAVE_SS7) */
16539 
16540 #if defined(HAVE_SS7)
16541 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16542 {
16543    int linkset;
16544    struct sig_ss7_linkset *ss7;
16545    switch (cmd) {
16546    case CLI_INIT:
16547       e->command = "ss7 show linkset";
16548       e->usage =
16549          "Usage: ss7 show linkset <span>\n"
16550          "       Shows the status of an SS7 linkset.\n";
16551       return NULL;
16552    case CLI_GENERATE:
16553       return NULL;
16554    }
16555 
16556    if (a->argc < 4)
16557       return CLI_SHOWUSAGE;
16558    linkset = atoi(a->argv[3]);
16559    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16560       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16561       return CLI_SUCCESS;
16562    }
16563    ss7 = &linksets[linkset - 1].ss7;
16564    if (!ss7->ss7) {
16565       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16566       return CLI_SUCCESS;
16567    }
16568 
16569    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16570 
16571    return CLI_SUCCESS;
16572 }
16573 #endif   /* defined(HAVE_SS7) */
16574 
16575 #if defined(HAVE_SS7)
16576 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16577 {
16578    int linkset;
16579 
16580    switch (cmd) {
16581    case CLI_INIT:
16582       e->command = "ss7 show channels";
16583       e->usage =
16584          "Usage: ss7 show channels\n"
16585          "       Displays SS7 channel information at a glance.\n";
16586       return NULL;
16587    case CLI_GENERATE:
16588       return NULL;
16589    }
16590 
16591    if (a->argc != 3)
16592       return CLI_SHOWUSAGE;
16593 
16594    sig_ss7_cli_show_channels_header(a->fd);
16595    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16596       if (linksets[linkset].ss7.ss7) {
16597          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16598       }
16599    }
16600    return CLI_SUCCESS;
16601 }
16602 #endif   /* defined(HAVE_SS7) */
16603 
16604 #if defined(HAVE_SS7)
16605 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16606 {
16607    switch (cmd) {
16608    case CLI_INIT:
16609       e->command = "ss7 show version";
16610       e->usage =
16611          "Usage: ss7 show version\n"
16612          "  Show the libss7 version\n";
16613       return NULL;
16614    case CLI_GENERATE:
16615       return NULL;
16616    }
16617 
16618    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16619 
16620    return CLI_SUCCESS;
16621 }
16622 #endif   /* defined(HAVE_SS7) */
16623 
16624 #if defined(HAVE_SS7)
16625 static struct ast_cli_entry dahdi_ss7_cli[] = {
16626    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16627    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16628    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16629    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16630    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16631    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16632    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16633    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16634 };
16635 #endif   /* defined(HAVE_SS7) */
16636 
16637 #if defined(HAVE_PRI)
16638 #if defined(HAVE_PRI_CCSS)
16639 /*!
16640  * \internal
16641  * \brief CC agent initialization.
16642  * \since 1.8
16643  *
16644  * \param agent CC core agent control.
16645  * \param chan Original channel the agent will attempt to recall.
16646  *
16647  * \details
16648  * This callback is called when the CC core is initialized.  Agents should allocate
16649  * any private data necessary for the call and assign it to the private_data
16650  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16651  * specific agent type, they should be set in this function as well.
16652  *
16653  * \retval 0 on success.
16654  * \retval -1 on error.
16655  */
16656 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16657 {
16658    struct dahdi_pvt *pvt;
16659    struct sig_pri_chan *pvt_chan;
16660    int res;
16661 
16662    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16663 
16664    pvt = chan->tech_pvt;
16665    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16666       pvt_chan = pvt->sig_pvt;
16667    } else {
16668       pvt_chan = NULL;
16669    }
16670    if (!pvt_chan) {
16671       return -1;
16672    }
16673 
16674    ast_module_ref(ast_module_info->self);
16675 
16676    res = sig_pri_cc_agent_init(agent, pvt_chan);
16677    if (res) {
16678       ast_module_unref(ast_module_info->self);
16679    }
16680    return res;
16681 }
16682 #endif   /* defined(HAVE_PRI_CCSS) */
16683 #endif   /* defined(HAVE_PRI) */
16684 
16685 #if defined(HAVE_PRI)
16686 #if defined(HAVE_PRI_CCSS)
16687 /*!
16688  * \internal
16689  * \brief Destroy private data on the agent.
16690  * \since 1.8
16691  *
16692  * \param agent CC core agent control.
16693  *
16694  * \details
16695  * The core will call this function upon completion
16696  * or failure of CC.
16697  *
16698  * \return Nothing
16699  */
16700 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16701 {
16702    sig_pri_cc_agent_destructor(agent);
16703 
16704    ast_module_unref(ast_module_info->self);
16705 }
16706 #endif   /* defined(HAVE_PRI_CCSS) */
16707 #endif   /* defined(HAVE_PRI) */
16708 
16709 #if defined(HAVE_PRI)
16710 #if defined(HAVE_PRI_CCSS)
16711 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16712    .type = dahdi_pri_cc_type,
16713    .init = dahdi_pri_cc_agent_init,
16714    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16715    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16716    .respond = sig_pri_cc_agent_req_rsp,
16717    .status_request = sig_pri_cc_agent_status_req,
16718    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16719    .party_b_free = sig_pri_cc_agent_party_b_free,
16720    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16721    .callee_available = sig_pri_cc_agent_callee_available,
16722    .destructor = dahdi_pri_cc_agent_destructor,
16723 };
16724 #endif   /* defined(HAVE_PRI_CCSS) */
16725 #endif   /* defined(HAVE_PRI) */
16726 
16727 #if defined(HAVE_PRI)
16728 #if defined(HAVE_PRI_CCSS)
16729 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16730    .type = dahdi_pri_cc_type,
16731    .request_cc = sig_pri_cc_monitor_req_cc,
16732    .suspend = sig_pri_cc_monitor_suspend,
16733    .unsuspend = sig_pri_cc_monitor_unsuspend,
16734    .status_response = sig_pri_cc_monitor_status_rsp,
16735    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16736    .destructor = sig_pri_cc_monitor_destructor,
16737 };
16738 #endif   /* defined(HAVE_PRI_CCSS) */
16739 #endif   /* defined(HAVE_PRI) */
16740 
16741 static int __unload_module(void)
16742 {
16743    struct dahdi_pvt *p;
16744 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16745    int i, j;
16746 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16747 
16748 #ifdef HAVE_PRI
16749    for (i = 0; i < NUM_SPANS; i++) {
16750       if (pris[i].pri.master != AST_PTHREADT_NULL)
16751          pthread_cancel(pris[i].pri.master);
16752    }
16753    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16754    ast_unregister_application(dahdi_send_keypad_facility_app);
16755 #ifdef HAVE_PRI_PROG_W_CAUSE
16756    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16757 #endif
16758 #endif
16759 #if defined(HAVE_SS7)
16760    for (i = 0; i < NUM_SPANS; i++) {
16761       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16762          pthread_cancel(linksets[i].ss7.master);
16763       }
16764    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16765 #endif   /* defined(HAVE_SS7) */
16766 #if defined(HAVE_OPENR2)
16767    dahdi_r2_destroy_links();
16768    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16769    ast_unregister_application(dahdi_accept_r2_call_app);
16770 #endif
16771 
16772    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16773    ast_manager_unregister("DAHDIDialOffhook");
16774    ast_manager_unregister("DAHDIHangup");
16775    ast_manager_unregister("DAHDITransfer");
16776    ast_manager_unregister("DAHDIDNDoff");
16777    ast_manager_unregister("DAHDIDNDon");
16778    ast_manager_unregister("DAHDIShowChannels");
16779    ast_manager_unregister("DAHDIRestart");
16780    ast_data_unregister(NULL);
16781    ast_channel_unregister(&dahdi_tech);
16782 
16783    /* Hangup all interfaces if they have an owner */
16784    ast_mutex_lock(&iflock);
16785    for (p = iflist; p; p = p->next) {
16786       if (p->owner)
16787          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16788    }
16789    ast_mutex_unlock(&iflock);
16790 
16791    ast_mutex_lock(&monlock);
16792    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16793       pthread_cancel(monitor_thread);
16794       pthread_kill(monitor_thread, SIGURG);
16795       pthread_join(monitor_thread, NULL);
16796    }
16797    monitor_thread = AST_PTHREADT_STOP;
16798    ast_mutex_unlock(&monlock);
16799 
16800    destroy_all_channels();
16801 
16802 #if defined(HAVE_PRI)
16803    for (i = 0; i < NUM_SPANS; i++) {
16804       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16805          pthread_join(pris[i].pri.master, NULL);
16806       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16807          dahdi_close_pri_fd(&(pris[i]), j);
16808       }
16809       sig_pri_stop_pri(&pris[i].pri);
16810    }
16811 #if defined(HAVE_PRI_CCSS)
16812    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16813    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16814 #endif   /* defined(HAVE_PRI_CCSS) */
16815    sig_pri_unload();
16816 #endif
16817 
16818 #if defined(HAVE_SS7)
16819    for (i = 0; i < NUM_SPANS; i++) {
16820       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16821          pthread_join(linksets[i].ss7.master, NULL);
16822       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16823          dahdi_close_ss7_fd(&(linksets[i]), j);
16824       }
16825    }
16826 #endif   /* defined(HAVE_SS7) */
16827    ast_cond_destroy(&ss_thread_complete);
16828    return 0;
16829 }
16830 
16831 static int unload_module(void)
16832 {
16833 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16834    int y;
16835 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16836 #ifdef HAVE_PRI
16837    for (y = 0; y < NUM_SPANS; y++)
16838       ast_mutex_destroy(&pris[y].pri.lock);
16839 #endif
16840 #if defined(HAVE_SS7)
16841    for (y = 0; y < NUM_SPANS; y++)
16842       ast_mutex_destroy(&linksets[y].ss7.lock);
16843 #endif   /* defined(HAVE_SS7) */
16844    return __unload_module();
16845 }
16846 
16847 static void string_replace(char *str, int char1, int char2)
16848 {
16849    for (; *str; str++) {
16850       if (*str == char1) {
16851          *str = char2;
16852       }
16853    }
16854 }
16855 
16856 static char *parse_spanchan(char *chanstr, char **subdir)
16857 {
16858    char *p;
16859 
16860    if ((p = strrchr(chanstr, '!')) == NULL) {
16861       *subdir = NULL;
16862       return chanstr;
16863    }
16864    *p++ = '\0';
16865    string_replace(chanstr, '!', '/');
16866    *subdir = chanstr;
16867    return p;
16868 }
16869 
16870 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16871 {
16872    char *c, *chan;
16873    char *subdir;
16874    int x, start, finish;
16875    struct dahdi_pvt *tmp;
16876 
16877    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16878       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16879       return -1;
16880    }
16881 
16882    c = ast_strdupa(value);
16883    c = parse_spanchan(c, &subdir);
16884 
16885    while ((chan = strsep(&c, ","))) {
16886       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16887          /* Range */
16888       } else if (sscanf(chan, "%30d", &start)) {
16889          /* Just one */
16890          finish = start;
16891       } else if (!strcasecmp(chan, "pseudo")) {
16892          finish = start = CHAN_PSEUDO;
16893          if (found_pseudo)
16894             *found_pseudo = 1;
16895       } else {
16896          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16897          return -1;
16898       }
16899       if (finish < start) {
16900          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16901          x = finish;
16902          finish = start;
16903          start = x;
16904       }
16905 
16906       for (x = start; x <= finish; x++) {
16907          char fn[PATH_MAX];
16908          int real_channel = x;
16909 
16910          if (!ast_strlen_zero(subdir)) {
16911             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16912             if (real_channel < 0) {
16913                if (conf->ignore_failed_channels) {
16914                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16915                         subdir, x, real_channel);
16916                   continue;
16917                } else {
16918                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16919                         subdir, x, real_channel);
16920                   return -1;
16921                }
16922             }
16923          }
16924          tmp = mkintf(real_channel, conf, reload);
16925 
16926          if (tmp) {
16927             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16928          } else {
16929             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16930                   (reload == 1) ? "reconfigure" : "register", value);
16931             return -1;
16932          }
16933       }
16934    }
16935 
16936    return 0;
16937 }
16938 
16939 /** The length of the parameters list of 'dahdichan'.
16940  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16941 #define MAX_CHANLIST_LEN 80
16942 
16943 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16944 {
16945    char *parse = ast_strdupa(data);
16946    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16947    unsigned int param_count;
16948    unsigned int x;
16949 
16950    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16951       return;
16952 
16953    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16954 
16955    /* first parameter is tap length, process it here */
16956 
16957    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16958 
16959    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16960       confp->chan.echocancel.head.tap_length = x;
16961    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16962       confp->chan.echocancel.head.tap_length = 128;
16963 
16964    /* now process any remaining parameters */
16965 
16966    for (x = 1; x < param_count; x++) {
16967       struct {
16968          char *name;
16969          char *value;
16970       } param;
16971 
16972       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16973          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16974          continue;
16975       }
16976 
16977       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16978          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16979          continue;
16980       }
16981 
16982       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16983 
16984       if (param.value) {
16985          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16986             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16987             continue;
16988          }
16989       }
16990       confp->chan.echocancel.head.param_count++;
16991    }
16992 }
16993 
16994 /*! process_dahdi() - ignore keyword 'channel' and similar */
16995 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16996 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16997 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16998 
16999 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17000 {
17001    struct dahdi_pvt *tmp;
17002    int y;
17003    int found_pseudo = 0;
17004    struct ast_variable *dahdichan = NULL;
17005 
17006    for (; v; v = v->next) {
17007       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17008          continue;
17009 
17010       /* Create the interface list */
17011       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17012          if (options & PROC_DAHDI_OPT_NOCHAN) {
17013             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17014             continue;
17015          }
17016          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17017             if (confp->ignore_failed_channels) {
17018                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17019                continue;
17020             } else {
17021                return -1;
17022             }
17023          }
17024          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17025       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17026          confp->ignore_failed_channels = ast_true(v->value);
17027       } else if (!strcasecmp(v->name, "buffers")) {
17028          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17029             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17030             confp->chan.buf_no = numbufs;
17031             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17032          }
17033       } else if (!strcasecmp(v->name, "faxbuffers")) {
17034          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17035             confp->chan.usefaxbuffers = 1;
17036          }
17037       } else if (!strcasecmp(v->name, "dahdichan")) {
17038          /* Only process the last dahdichan value. */
17039          dahdichan = v;
17040       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17041          usedistinctiveringdetection = ast_true(v->value);
17042       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17043          distinctiveringaftercid = ast_true(v->value);
17044       } else if (!strcasecmp(v->name, "dring1context")) {
17045          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17046       } else if (!strcasecmp(v->name, "dring2context")) {
17047          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17048       } else if (!strcasecmp(v->name, "dring3context")) {
17049          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17050       } else if (!strcasecmp(v->name, "dring1range")) {
17051          confp->chan.drings.ringnum[0].range = atoi(v->value);
17052       } else if (!strcasecmp(v->name, "dring2range")) {
17053          confp->chan.drings.ringnum[1].range = atoi(v->value);
17054       } else if (!strcasecmp(v->name, "dring3range")) {
17055          confp->chan.drings.ringnum[2].range = atoi(v->value);
17056       } else if (!strcasecmp(v->name, "dring1")) {
17057          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]);
17058       } else if (!strcasecmp(v->name, "dring2")) {
17059          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]);
17060       } else if (!strcasecmp(v->name, "dring3")) {
17061          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]);
17062       } else if (!strcasecmp(v->name, "usecallerid")) {
17063          confp->chan.use_callerid = ast_true(v->value);
17064       } else if (!strcasecmp(v->name, "cidsignalling")) {
17065          if (!strcasecmp(v->value, "bell"))
17066             confp->chan.cid_signalling = CID_SIG_BELL;
17067          else if (!strcasecmp(v->value, "v23"))
17068             confp->chan.cid_signalling = CID_SIG_V23;
17069          else if (!strcasecmp(v->value, "dtmf"))
17070             confp->chan.cid_signalling = CID_SIG_DTMF;
17071          else if (!strcasecmp(v->value, "smdi"))
17072             confp->chan.cid_signalling = CID_SIG_SMDI;
17073          else if (!strcasecmp(v->value, "v23_jp"))
17074             confp->chan.cid_signalling = CID_SIG_V23_JP;
17075          else if (ast_true(v->value))
17076             confp->chan.cid_signalling = CID_SIG_BELL;
17077       } else if (!strcasecmp(v->name, "cidstart")) {
17078          if (!strcasecmp(v->value, "ring"))
17079             confp->chan.cid_start = CID_START_RING;
17080          else if (!strcasecmp(v->value, "polarity_in"))
17081             confp->chan.cid_start = CID_START_POLARITY_IN;
17082          else if (!strcasecmp(v->value, "polarity"))
17083             confp->chan.cid_start = CID_START_POLARITY;
17084          else if (!strcasecmp(v->value, "dtmf"))
17085             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17086          else if (ast_true(v->value))
17087             confp->chan.cid_start = CID_START_RING;
17088       } else if (!strcasecmp(v->name, "threewaycalling")) {
17089          confp->chan.threewaycalling = ast_true(v->value);
17090       } else if (!strcasecmp(v->name, "cancallforward")) {
17091          confp->chan.cancallforward = ast_true(v->value);
17092       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17093          if (ast_true(v->value))
17094             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17095          else
17096             confp->chan.dtmfrelax = 0;
17097       } else if (!strcasecmp(v->name, "mailbox")) {
17098          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17099       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17100          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17101             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17102          }
17103       } else if (!strcasecmp(v->name, "adsi")) {
17104          confp->chan.adsi = ast_true(v->value);
17105       } else if (!strcasecmp(v->name, "usesmdi")) {
17106          confp->chan.use_smdi = ast_true(v->value);
17107       } else if (!strcasecmp(v->name, "smdiport")) {
17108          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17109       } else if (!strcasecmp(v->name, "transfer")) {
17110          confp->chan.transfer = ast_true(v->value);
17111       } else if (!strcasecmp(v->name, "canpark")) {
17112          confp->chan.canpark = ast_true(v->value);
17113       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17114          confp->chan.echocanbridged = ast_true(v->value);
17115       } else if (!strcasecmp(v->name, "busydetect")) {
17116          confp->chan.busydetect = ast_true(v->value);
17117       } else if (!strcasecmp(v->name, "busycount")) {
17118          confp->chan.busycount = atoi(v->value);
17119       } else if (!strcasecmp(v->name, "silencethreshold")) {
17120          confp->chan.silencethreshold = atoi(v->value);
17121       } else if (!strcasecmp(v->name, "busycompare")) {
17122          confp->chan.busycompare = ast_true(v->value);
17123       } else if (!strcasecmp(v->name, "busypattern")) {
17124          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17125             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17126          }
17127          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17128          if (count == 1)
17129             confp->chan.busyquietlength = 0;
17130          else if (count < 1)
17131             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17132       } else if (!strcasecmp(v->name, "busyfuzziness")) {
17133          confp->chan.busyfuzziness = atoi(v->value);
17134       } else if (!strcasecmp(v->name, "callprogress")) {
17135          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17136          if (ast_true(v->value))
17137             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17138       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17139          confp->chan.waitfordialtone = atoi(v->value);
17140       } else if (!strcasecmp(v->name, "faxdetect")) {
17141          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17142          if (!strcasecmp(v->value, "incoming")) {
17143             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17144          } else if (!strcasecmp(v->value, "outgoing")) {
17145             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17146          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17147             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17148       } else if (!strcasecmp(v->name, "echocancel")) {
17149          process_echocancel(confp, v->value, v->lineno);
17150       } else if (!strcasecmp(v->name, "echotraining")) {
17151          if (sscanf(v->value, "%30d", &y) == 1) {
17152             if ((y < 10) || (y > 4000)) {
17153                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17154             } else {
17155                confp->chan.echotraining = y;
17156             }
17157          } else if (ast_true(v->value)) {
17158             confp->chan.echotraining = 400;
17159          } else
17160             confp->chan.echotraining = 0;
17161       } else if (!strcasecmp(v->name, "hidecallerid")) {
17162          confp->chan.hidecallerid = ast_true(v->value);
17163       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17164          confp->chan.hidecalleridname = ast_true(v->value);
17165       } else if (!strcasecmp(v->name, "pulsedial")) {
17166          confp->chan.pulse = ast_true(v->value);
17167       } else if (!strcasecmp(v->name, "callreturn")) {
17168          confp->chan.callreturn = ast_true(v->value);
17169       } else if (!strcasecmp(v->name, "callwaiting")) {
17170          confp->chan.callwaiting = ast_true(v->value);
17171       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17172          confp->chan.callwaitingcallerid = ast_true(v->value);
17173       } else if (!strcasecmp(v->name, "context")) {
17174          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17175       } else if (!strcasecmp(v->name, "language")) {
17176          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17177       } else if (!strcasecmp(v->name, "progzone")) {
17178          ast_copy_string(progzone, v->value, sizeof(progzone));
17179       } else if (!strcasecmp(v->name, "mohinterpret")
17180          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17181          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17182       } else if (!strcasecmp(v->name, "mohsuggest")) {
17183          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17184       } else if (!strcasecmp(v->name, "parkinglot")) {
17185          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17186       } else if (!strcasecmp(v->name, "stripmsd")) {
17187          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17188          confp->chan.stripmsd = atoi(v->value);
17189       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17190          numbufs = atoi(v->value);
17191       } else if (!strcasecmp(v->name, "group")) {
17192          confp->chan.group = ast_get_group(v->value);
17193       } else if (!strcasecmp(v->name, "callgroup")) {
17194          if (!strcasecmp(v->value, "none"))
17195             confp->chan.callgroup = 0;
17196          else
17197             confp->chan.callgroup = ast_get_group(v->value);
17198       } else if (!strcasecmp(v->name, "pickupgroup")) {
17199          if (!strcasecmp(v->value, "none"))
17200             confp->chan.pickupgroup = 0;
17201          else
17202             confp->chan.pickupgroup = ast_get_group(v->value);
17203       } else if (!strcasecmp(v->name, "setvar")) {
17204          char *varname = ast_strdupa(v->value), *varval = NULL;
17205          struct ast_variable *tmpvar;
17206          if (varname && (varval = strchr(varname, '='))) {
17207             *varval++ = '\0';
17208             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17209                tmpvar->next = confp->chan.vars;
17210                confp->chan.vars = tmpvar;
17211             }
17212          }
17213       } else if (!strcasecmp(v->name, "immediate")) {
17214          confp->chan.immediate = ast_true(v->value);
17215       } else if (!strcasecmp(v->name, "transfertobusy")) {
17216          confp->chan.transfertobusy = ast_true(v->value);
17217       } else if (!strcasecmp(v->name, "mwimonitor")) {
17218          confp->chan.mwimonitor_neon = 0;
17219          confp->chan.mwimonitor_fsk = 0;
17220          confp->chan.mwimonitor_rpas = 0;
17221          if (strcasestr(v->value, "fsk")) {
17222             confp->chan.mwimonitor_fsk = 1;
17223          }
17224          if (strcasestr(v->value, "rpas")) {
17225             confp->chan.mwimonitor_rpas = 1;
17226          }
17227          if (strcasestr(v->value, "neon")) {
17228             confp->chan.mwimonitor_neon = 1;
17229          }
17230          /* If set to true or yes, assume that simple fsk is desired */
17231          if (ast_true(v->value)) {
17232             confp->chan.mwimonitor_fsk = 1;
17233          }
17234       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17235          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17236             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17237          }
17238       } else if (!strcasecmp(v->name, "rxgain")) {
17239          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17240             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17241          }
17242       } else if (!strcasecmp(v->name, "txgain")) {
17243          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17244             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17245          }
17246       } else if (!strcasecmp(v->name, "txdrc")) {
17247          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17248             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17249          }
17250       } else if (!strcasecmp(v->name, "rxdrc")) {
17251          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17252             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17253          }
17254       } else if (!strcasecmp(v->name, "tonezone")) {
17255          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17256             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17257          }
17258       } else if (!strcasecmp(v->name, "callerid")) {
17259          if (!strcasecmp(v->value, "asreceived")) {
17260             confp->chan.cid_num[0] = '\0';
17261             confp->chan.cid_name[0] = '\0';
17262          } else {
17263             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17264          }
17265       } else if (!strcasecmp(v->name, "fullname")) {
17266          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17267       } else if (!strcasecmp(v->name, "cid_number")) {
17268          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17269       } else if (!strcasecmp(v->name, "cid_tag")) {
17270          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17271       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17272          confp->chan.dahditrcallerid = ast_true(v->value);
17273       } else if (!strcasecmp(v->name, "restrictcid")) {
17274          confp->chan.restrictcid = ast_true(v->value);
17275       } else if (!strcasecmp(v->name, "usecallingpres")) {
17276          confp->chan.use_callingpres = ast_true(v->value);
17277       } else if (!strcasecmp(v->name, "accountcode")) {
17278          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17279       } else if (!strcasecmp(v->name, "amaflags")) {
17280          y = ast_cdr_amaflags2int(v->value);
17281          if (y < 0)
17282             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17283          else
17284             confp->chan.amaflags = y;
17285       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17286          confp->chan.polarityonanswerdelay = atoi(v->value);
17287       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17288          confp->chan.answeronpolarityswitch = ast_true(v->value);
17289       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17290          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17291       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17292          confp->chan.sendcalleridafter = atoi(v->value);
17293       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17294          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17295       } else if (ast_cc_is_config_param(v->name)) {
17296          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17297       } else if (!strcasecmp(v->name, "mwisendtype")) {
17298 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17299          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17300             mwisend_rpas = 1;
17301          } else {
17302             mwisend_rpas = 0;
17303          }
17304 #else
17305          /* Default is fsk, to turn it off you must specify nofsk */
17306          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17307          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17308             confp->chan.mwisend_fsk = 0;
17309          } else {             /* Default FSK */
17310             confp->chan.mwisend_fsk = 1;
17311          }
17312          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17313             confp->chan.mwisend_rpas = 1;
17314          } else {
17315             confp->chan.mwisend_rpas = 0;
17316          }
17317          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17318             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17319          }
17320          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17321             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17322          }
17323          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17324             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17325          }
17326 #endif
17327       } else if (reload != 1) {
17328           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17329             int orig_radio = confp->chan.radio;
17330             int orig_outsigmod = confp->chan.outsigmod;
17331             int orig_auto = confp->is_sig_auto;
17332 
17333             confp->chan.radio = 0;
17334             confp->chan.outsigmod = -1;
17335             confp->is_sig_auto = 0;
17336             if (!strcasecmp(v->value, "em")) {
17337                confp->chan.sig = SIG_EM;
17338             } else if (!strcasecmp(v->value, "em_e1")) {
17339                confp->chan.sig = SIG_EM_E1;
17340             } else if (!strcasecmp(v->value, "em_w")) {
17341                confp->chan.sig = SIG_EMWINK;
17342             } else if (!strcasecmp(v->value, "fxs_ls")) {
17343                confp->chan.sig = SIG_FXSLS;
17344             } else if (!strcasecmp(v->value, "fxs_gs")) {
17345                confp->chan.sig = SIG_FXSGS;
17346             } else if (!strcasecmp(v->value, "fxs_ks")) {
17347                confp->chan.sig = SIG_FXSKS;
17348             } else if (!strcasecmp(v->value, "fxo_ls")) {
17349                confp->chan.sig = SIG_FXOLS;
17350             } else if (!strcasecmp(v->value, "fxo_gs")) {
17351                confp->chan.sig = SIG_FXOGS;
17352             } else if (!strcasecmp(v->value, "fxo_ks")) {
17353                confp->chan.sig = SIG_FXOKS;
17354             } else if (!strcasecmp(v->value, "fxs_rx")) {
17355                confp->chan.sig = SIG_FXSKS;
17356                confp->chan.radio = 1;
17357             } else if (!strcasecmp(v->value, "fxo_rx")) {
17358                confp->chan.sig = SIG_FXOLS;
17359                confp->chan.radio = 1;
17360             } else if (!strcasecmp(v->value, "fxs_tx")) {
17361                confp->chan.sig = SIG_FXSLS;
17362                confp->chan.radio = 1;
17363             } else if (!strcasecmp(v->value, "fxo_tx")) {
17364                confp->chan.sig = SIG_FXOGS;
17365                confp->chan.radio = 1;
17366             } else if (!strcasecmp(v->value, "em_rx")) {
17367                confp->chan.sig = SIG_EM;
17368                confp->chan.radio = 1;
17369             } else if (!strcasecmp(v->value, "em_tx")) {
17370                confp->chan.sig = SIG_EM;
17371                confp->chan.radio = 1;
17372             } else if (!strcasecmp(v->value, "em_rxtx")) {
17373                confp->chan.sig = SIG_EM;
17374                confp->chan.radio = 2;
17375             } else if (!strcasecmp(v->value, "em_txrx")) {
17376                confp->chan.sig = SIG_EM;
17377                confp->chan.radio = 2;
17378             } else if (!strcasecmp(v->value, "sf")) {
17379                confp->chan.sig = SIG_SF;
17380             } else if (!strcasecmp(v->value, "sf_w")) {
17381                confp->chan.sig = SIG_SFWINK;
17382             } else if (!strcasecmp(v->value, "sf_featd")) {
17383                confp->chan.sig = SIG_FEATD;
17384             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17385                confp->chan.sig = SIG_FEATDMF;
17386             } else if (!strcasecmp(v->value, "sf_featb")) {
17387                confp->chan.sig = SIG_SF_FEATB;
17388             } else if (!strcasecmp(v->value, "sf")) {
17389                confp->chan.sig = SIG_SF;
17390             } else if (!strcasecmp(v->value, "sf_rx")) {
17391                confp->chan.sig = SIG_SF;
17392                confp->chan.radio = 1;
17393             } else if (!strcasecmp(v->value, "sf_tx")) {
17394                confp->chan.sig = SIG_SF;
17395                confp->chan.radio = 1;
17396             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17397                confp->chan.sig = SIG_SF;
17398                confp->chan.radio = 2;
17399             } else if (!strcasecmp(v->value, "sf_txrx")) {
17400                confp->chan.sig = SIG_SF;
17401                confp->chan.radio = 2;
17402             } else if (!strcasecmp(v->value, "featd")) {
17403                confp->chan.sig = SIG_FEATD;
17404             } else if (!strcasecmp(v->value, "featdmf")) {
17405                confp->chan.sig = SIG_FEATDMF;
17406             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17407                confp->chan.sig = SIG_FEATDMF_TA;
17408             } else if (!strcasecmp(v->value, "e911")) {
17409                confp->chan.sig = SIG_E911;
17410             } else if (!strcasecmp(v->value, "fgccama")) {
17411                confp->chan.sig = SIG_FGC_CAMA;
17412             } else if (!strcasecmp(v->value, "fgccamamf")) {
17413                confp->chan.sig = SIG_FGC_CAMAMF;
17414             } else if (!strcasecmp(v->value, "featb")) {
17415                confp->chan.sig = SIG_FEATB;
17416 #ifdef HAVE_PRI
17417             } else if (!strcasecmp(v->value, "pri_net")) {
17418                confp->chan.sig = SIG_PRI;
17419                confp->pri.pri.nodetype = PRI_NETWORK;
17420             } else if (!strcasecmp(v->value, "pri_cpe")) {
17421                confp->chan.sig = SIG_PRI;
17422                confp->pri.pri.nodetype = PRI_CPE;
17423             } else if (!strcasecmp(v->value, "bri_cpe")) {
17424                confp->chan.sig = SIG_BRI;
17425                confp->pri.pri.nodetype = PRI_CPE;
17426             } else if (!strcasecmp(v->value, "bri_net")) {
17427                confp->chan.sig = SIG_BRI;
17428                confp->pri.pri.nodetype = PRI_NETWORK;
17429             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17430                confp->chan.sig = SIG_BRI_PTMP;
17431                confp->pri.pri.nodetype = PRI_CPE;
17432             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17433 #if defined(HAVE_PRI_CALL_HOLD)
17434                confp->chan.sig = SIG_BRI_PTMP;
17435                confp->pri.pri.nodetype = PRI_NETWORK;
17436 #else
17437                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17438 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17439 #endif
17440 #if defined(HAVE_SS7)
17441             } else if (!strcasecmp(v->value, "ss7")) {
17442                confp->chan.sig = SIG_SS7;
17443 #endif   /* defined(HAVE_SS7) */
17444 #ifdef HAVE_OPENR2
17445             } else if (!strcasecmp(v->value, "mfcr2")) {
17446                confp->chan.sig = SIG_MFCR2;
17447 #endif
17448             } else if (!strcasecmp(v->value, "auto")) {
17449                confp->is_sig_auto = 1;
17450             } else {
17451                confp->chan.outsigmod = orig_outsigmod;
17452                confp->chan.radio = orig_radio;
17453                confp->is_sig_auto = orig_auto;
17454                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17455             }
17456           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17457             if (!strcasecmp(v->value, "em")) {
17458                confp->chan.outsigmod = SIG_EM;
17459             } else if (!strcasecmp(v->value, "em_e1")) {
17460                confp->chan.outsigmod = SIG_EM_E1;
17461             } else if (!strcasecmp(v->value, "em_w")) {
17462                confp->chan.outsigmod = SIG_EMWINK;
17463             } else if (!strcasecmp(v->value, "sf")) {
17464                confp->chan.outsigmod = SIG_SF;
17465             } else if (!strcasecmp(v->value, "sf_w")) {
17466                confp->chan.outsigmod = SIG_SFWINK;
17467             } else if (!strcasecmp(v->value, "sf_featd")) {
17468                confp->chan.outsigmod = SIG_FEATD;
17469             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17470                confp->chan.outsigmod = SIG_FEATDMF;
17471             } else if (!strcasecmp(v->value, "sf_featb")) {
17472                confp->chan.outsigmod = SIG_SF_FEATB;
17473             } else if (!strcasecmp(v->value, "sf")) {
17474                confp->chan.outsigmod = SIG_SF;
17475             } else if (!strcasecmp(v->value, "featd")) {
17476                confp->chan.outsigmod = SIG_FEATD;
17477             } else if (!strcasecmp(v->value, "featdmf")) {
17478                confp->chan.outsigmod = SIG_FEATDMF;
17479             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17480                confp->chan.outsigmod = SIG_FEATDMF_TA;
17481             } else if (!strcasecmp(v->value, "e911")) {
17482                confp->chan.outsigmod = SIG_E911;
17483             } else if (!strcasecmp(v->value, "fgccama")) {
17484                confp->chan.outsigmod = SIG_FGC_CAMA;
17485             } else if (!strcasecmp(v->value, "fgccamamf")) {
17486                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17487             } else if (!strcasecmp(v->value, "featb")) {
17488                confp->chan.outsigmod = SIG_FEATB;
17489             } else {
17490                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17491             }
17492 #ifdef HAVE_PRI
17493          } else if (!strcasecmp(v->name, "pridialplan")) {
17494             if (!strcasecmp(v->value, "national")) {
17495                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17496             } else if (!strcasecmp(v->value, "unknown")) {
17497                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17498             } else if (!strcasecmp(v->value, "private")) {
17499                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17500             } else if (!strcasecmp(v->value, "international")) {
17501                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17502             } else if (!strcasecmp(v->value, "local")) {
17503                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17504             } else if (!strcasecmp(v->value, "dynamic")) {
17505                confp->pri.pri.dialplan = -1;
17506             } else if (!strcasecmp(v->value, "redundant")) {
17507                confp->pri.pri.dialplan = -2;
17508             } else {
17509                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17510             }
17511          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17512             if (!strcasecmp(v->value, "national")) {
17513                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17514             } else if (!strcasecmp(v->value, "unknown")) {
17515                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17516             } else if (!strcasecmp(v->value, "private")) {
17517                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17518             } else if (!strcasecmp(v->value, "international")) {
17519                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17520             } else if (!strcasecmp(v->value, "local")) {
17521                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17522             } else if (!strcasecmp(v->value, "dynamic")) {
17523                confp->pri.pri.localdialplan = -1;
17524             } else if (!strcasecmp(v->value, "redundant")) {
17525                confp->pri.pri.localdialplan = -2;
17526             } else {
17527                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17528             }
17529          } else if (!strcasecmp(v->name, "switchtype")) {
17530             if (!strcasecmp(v->value, "national"))
17531                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17532             else if (!strcasecmp(v->value, "ni1"))
17533                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17534             else if (!strcasecmp(v->value, "dms100"))
17535                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17536             else if (!strcasecmp(v->value, "4ess"))
17537                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17538             else if (!strcasecmp(v->value, "5ess"))
17539                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17540             else if (!strcasecmp(v->value, "euroisdn"))
17541                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17542             else if (!strcasecmp(v->value, "qsig"))
17543                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17544             else {
17545                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17546                return -1;
17547             }
17548          } else if (!strcasecmp(v->name, "msn")) {
17549             ast_copy_string(confp->pri.pri.msn_list, v->value,
17550                sizeof(confp->pri.pri.msn_list));
17551          } else if (!strcasecmp(v->name, "nsf")) {
17552             if (!strcasecmp(v->value, "sdn"))
17553                confp->pri.pri.nsf = PRI_NSF_SDN;
17554             else if (!strcasecmp(v->value, "megacom"))
17555                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17556             else if (!strcasecmp(v->value, "tollfreemegacom"))
17557                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17558             else if (!strcasecmp(v->value, "accunet"))
17559                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17560             else if (!strcasecmp(v->value, "none"))
17561                confp->pri.pri.nsf = PRI_NSF_NONE;
17562             else {
17563                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17564                confp->pri.pri.nsf = PRI_NSF_NONE;
17565             }
17566          } else if (!strcasecmp(v->name, "priindication")) {
17567             if (!strcasecmp(v->value, "outofband"))
17568                confp->chan.priindication_oob = 1;
17569             else if (!strcasecmp(v->value, "inband"))
17570                confp->chan.priindication_oob = 0;
17571             else
17572                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17573                   v->value, v->lineno);
17574          } else if (!strcasecmp(v->name, "priexclusive")) {
17575             confp->chan.priexclusive = ast_true(v->value);
17576          } else if (!strcasecmp(v->name, "internationalprefix")) {
17577             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17578          } else if (!strcasecmp(v->name, "nationalprefix")) {
17579             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17580          } else if (!strcasecmp(v->name, "localprefix")) {
17581             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17582          } else if (!strcasecmp(v->name, "privateprefix")) {
17583             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17584          } else if (!strcasecmp(v->name, "unknownprefix")) {
17585             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17586          } else if (!strcasecmp(v->name, "resetinterval")) {
17587             if (!strcasecmp(v->value, "never"))
17588                confp->pri.pri.resetinterval = -1;
17589             else if (atoi(v->value) >= 60)
17590                confp->pri.pri.resetinterval = atoi(v->value);
17591             else
17592                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17593                   v->value, v->lineno);
17594          } else if (!strcasecmp(v->name, "minunused")) {
17595             confp->pri.pri.minunused = atoi(v->value);
17596          } else if (!strcasecmp(v->name, "minidle")) {
17597             confp->pri.pri.minidle = atoi(v->value);
17598          } else if (!strcasecmp(v->name, "idleext")) {
17599             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17600          } else if (!strcasecmp(v->name, "idledial")) {
17601             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17602          } else if (!strcasecmp(v->name, "overlapdial")) {
17603             if (ast_true(v->value)) {
17604                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17605             } else if (!strcasecmp(v->value, "incoming")) {
17606                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17607             } else if (!strcasecmp(v->value, "outgoing")) {
17608                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17609             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17610                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17611             } else {
17612                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17613             }
17614 #ifdef HAVE_PRI_PROG_W_CAUSE
17615          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17616             if (!strcasecmp(v->value, "logical")) {
17617                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17618             } else if (!strcasecmp(v->value, "physical")) {
17619                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17620             } else {
17621                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17622             }
17623 #endif
17624          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17625             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17626 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17627          } else if (!strcasecmp(v->name, "service_message_support")) {
17628             /* assuming switchtype for this channel group has been configured already */
17629             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17630                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17631                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17632                confp->pri.pri.enable_service_message_support = 1;
17633             } else {
17634                confp->pri.pri.enable_service_message_support = 0;
17635             }
17636 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17637 #ifdef HAVE_PRI_INBANDDISCONNECT
17638          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17639             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17640 #endif
17641          } else if (!strcasecmp(v->name, "pritimer")) {
17642 #ifdef PRI_GETSET_TIMERS
17643             char tmp[20];
17644             char *timerc;
17645             char *c;
17646             int timer;
17647             int timeridx;
17648 
17649             ast_copy_string(tmp, v->value, sizeof(tmp));
17650             c = tmp;
17651             timerc = strsep(&c, ",");
17652             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17653                timeridx = pri_timer2idx(timerc);
17654                timer = atoi(c);
17655                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17656                   ast_log(LOG_WARNING,
17657                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17658                      v->lineno);
17659                } else if (!timer) {
17660                   ast_log(LOG_WARNING,
17661                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17662                      c, timerc, v->lineno);
17663                } else {
17664                   confp->pri.pri.pritimers[timeridx] = timer;
17665                }
17666             } else {
17667                ast_log(LOG_WARNING,
17668                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17669                   v->value, v->lineno);
17670             }
17671 #endif /* PRI_GETSET_TIMERS */
17672          } else if (!strcasecmp(v->name, "facilityenable")) {
17673             confp->pri.pri.facilityenable = ast_true(v->value);
17674 #if defined(HAVE_PRI_AOC_EVENTS)
17675          } else if (!strcasecmp(v->name, "aoc_enable")) {
17676             confp->pri.pri.aoc_passthrough_flag = 0;
17677             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17678                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17679             }
17680             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17681                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17682             }
17683             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17684                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17685             }
17686          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17687             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17688 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17689 #if defined(HAVE_PRI_CALL_HOLD)
17690          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17691             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17692 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17693 #if defined(HAVE_PRI_CCSS)
17694          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17695             if (!strcasecmp(v->value, "global")) {
17696                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17697             } else if (!strcasecmp(v->value, "specific")) {
17698                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17699             } else {
17700                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17701             }
17702          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17703             if (!strcasecmp(v->value, "release")) {
17704                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17705             } else if (!strcasecmp(v->value, "retain")) {
17706                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17707             } else if (!strcasecmp(v->value, "do_not_care")) {
17708                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17709             } else {
17710                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17711             }
17712          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17713             if (!strcasecmp(v->value, "release")) {
17714                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17715             } else if (!strcasecmp(v->value, "retain")) {
17716                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17717             } else {
17718                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17719             }
17720 #endif   /* defined(HAVE_PRI_CCSS) */
17721 #if defined(HAVE_PRI_CALL_WAITING)
17722          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17723             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17724             if (confp->pri.pri.max_call_waiting_calls < 0) {
17725                /* Negative values are not allowed. */
17726                confp->pri.pri.max_call_waiting_calls = 0;
17727             }
17728          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17729             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17730 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17731 #if defined(HAVE_PRI_MWI)
17732          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17733             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17734                sizeof(confp->pri.pri.mwi_mailboxes));
17735 #endif   /* defined(HAVE_PRI_MWI) */
17736          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17737             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17738          } else if (!strcasecmp(v->name, "layer1_presence")) {
17739             if (!strcasecmp(v->value, "required")) {
17740                confp->pri.pri.layer1_ignored = 0;
17741             } else if (!strcasecmp(v->value, "ignore")) {
17742                confp->pri.pri.layer1_ignored = 1;
17743             } else {
17744                /* Default */
17745                confp->pri.pri.layer1_ignored = 0;
17746             }
17747 #if defined(HAVE_PRI_L2_PERSISTENCE)
17748          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17749             if (!strcasecmp(v->value, "keep_up")) {
17750                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17751             } else if (!strcasecmp(v->value, "leave_down")) {
17752                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17753             } else {
17754                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17755             }
17756 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17757 #endif /* HAVE_PRI */
17758 #if defined(HAVE_SS7)
17759          } else if (!strcasecmp(v->name, "ss7type")) {
17760             if (!strcasecmp(v->value, "itu")) {
17761                cur_ss7type = SS7_ITU;
17762             } else if (!strcasecmp(v->value, "ansi")) {
17763                cur_ss7type = SS7_ANSI;
17764             } else
17765                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17766          } else if (!strcasecmp(v->name, "linkset")) {
17767             cur_linkset = atoi(v->value);
17768          } else if (!strcasecmp(v->name, "pointcode")) {
17769             cur_pointcode = parse_pointcode(v->value);
17770          } else if (!strcasecmp(v->name, "adjpointcode")) {
17771             cur_adjpointcode = parse_pointcode(v->value);
17772          } else if (!strcasecmp(v->name, "defaultdpc")) {
17773             cur_defaultdpc = parse_pointcode(v->value);
17774          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17775             cur_cicbeginswith = atoi(v->value);
17776          } else if (!strcasecmp(v->name, "networkindicator")) {
17777             if (!strcasecmp(v->value, "national"))
17778                cur_networkindicator = SS7_NI_NAT;
17779             else if (!strcasecmp(v->value, "national_spare"))
17780                cur_networkindicator = SS7_NI_NAT_SPARE;
17781             else if (!strcasecmp(v->value, "international"))
17782                cur_networkindicator = SS7_NI_INT;
17783             else if (!strcasecmp(v->value, "international_spare"))
17784                cur_networkindicator = SS7_NI_INT_SPARE;
17785             else
17786                cur_networkindicator = -1;
17787          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17788             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17789          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17790             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17791          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17792             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17793          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17794             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17795          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17796             if (!strcasecmp(v->value, "national")) {
17797                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17798             } else if (!strcasecmp(v->value, "international")) {
17799                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17800             } else if (!strcasecmp(v->value, "subscriber")) {
17801                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17802             } else if (!strcasecmp(v->value, "unknown")) {
17803                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17804             } else if (!strcasecmp(v->value, "dynamic")) {
17805                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17806             } else {
17807                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17808             }
17809          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17810             if (!strcasecmp(v->value, "national")) {
17811                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17812             } else if (!strcasecmp(v->value, "international")) {
17813                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17814             } else if (!strcasecmp(v->value, "subscriber")) {
17815                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17816             } else if (!strcasecmp(v->value, "unknown")) {
17817                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17818             } else if (!strcasecmp(v->value, "dynamic")) {
17819                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17820             } else {
17821                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17822             }
17823          } else if (!strcasecmp(v->name, "sigchan")) {
17824             int sigchan, res;
17825             sigchan = atoi(v->value);
17826             res = linkset_addsigchan(sigchan);
17827             if (res < 0)
17828                return -1;
17829 
17830          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17831             struct dahdi_ss7 *link;
17832             link = ss7_resolve_linkset(cur_linkset);
17833             if (!link) {
17834                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17835                return -1;
17836             }
17837             if (ast_true(v->value))
17838                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17839 #endif   /* defined(HAVE_SS7) */
17840 #ifdef HAVE_OPENR2
17841          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17842             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17843             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);
17844          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17845             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17846          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17847             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17848             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17849                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17850                confp->mfcr2.variant = OR2_VAR_ITU;
17851             }
17852          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17853             confp->mfcr2.mfback_timeout = atoi(v->value);
17854             if (!confp->mfcr2.mfback_timeout) {
17855                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17856                confp->mfcr2.mfback_timeout = -1;
17857             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17858                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17859             }
17860          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17861             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17862             if (confp->mfcr2.metering_pulse_timeout > 500) {
17863                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17864             }
17865          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17866             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17867          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17868             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17869          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17870             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17871          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17872             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17873          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17874             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17875          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17876             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17877          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17878             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17879 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17880          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17881             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17882 #endif
17883          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17884             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17885          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17886             confp->mfcr2.max_ani = atoi(v->value);
17887             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17888                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17889             }
17890          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17891             confp->mfcr2.max_dnis = atoi(v->value);
17892             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17893                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17894             }
17895          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17896             confp->mfcr2.category = openr2_proto_get_category(v->value);
17897             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17898                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17899                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17900                      v->value, v->lineno);
17901             }
17902          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17903             openr2_log_level_t tmplevel;
17904             char *clevel;
17905             char *logval = ast_strdupa(v->value);
17906             while (logval) {
17907                clevel = strsep(&logval,",");
17908                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17909                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17910                   continue;
17911                }
17912                confp->mfcr2.loglevel |= tmplevel;
17913             }
17914 #endif /* HAVE_OPENR2 */
17915          } else if (!strcasecmp(v->name, "cadence")) {
17916             /* setup to scan our argument */
17917             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17918             int i;
17919             struct dahdi_ring_cadence new_cadence;
17920             int cid_location = -1;
17921             int firstcadencepos = 0;
17922             char original_args[80];
17923             int cadence_is_ok = 1;
17924 
17925             ast_copy_string(original_args, v->value, sizeof(original_args));
17926             /* 16 cadences allowed (8 pairs) */
17927             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]);
17928 
17929             /* Cadence must be even (on/off) */
17930             if (element_count % 2 == 1) {
17931                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17932                cadence_is_ok = 0;
17933             }
17934 
17935             /* Ring cadences cannot be negative */
17936             for (i = 0; i < element_count; i++) {
17937                if (c[i] == 0) {
17938                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17939                   cadence_is_ok = 0;
17940                   break;
17941                } else if (c[i] < 0) {
17942                   if (i % 2 == 1) {
17943                      /* Silence duration, negative possibly okay */
17944                      if (cid_location == -1) {
17945                         cid_location = i;
17946                         c[i] *= -1;
17947                      } else {
17948                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17949                         cadence_is_ok = 0;
17950                         break;
17951                      }
17952                   } else {
17953                      if (firstcadencepos == 0) {
17954                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17955                                  /* duration will be passed negative to the DAHDI driver */
17956                      } else {
17957                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17958                         cadence_is_ok = 0;
17959                         break;
17960                      }
17961                   }
17962                }
17963             }
17964 
17965             /* Substitute our scanned cadence */
17966             for (i = 0; i < 16; i++) {
17967                new_cadence.ringcadence[i] = c[i];
17968             }
17969 
17970             if (cadence_is_ok) {
17971                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17972                if (element_count < 2) {
17973                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17974                } else {
17975                   if (cid_location == -1) {
17976                      /* user didn't say; default to first pause */
17977                      cid_location = 1;
17978                   } else {
17979                      /* convert element_index to cidrings value */
17980                      cid_location = (cid_location + 1) / 2;
17981                   }
17982                   /* ---we like their cadence; try to install it--- */
17983                   if (!user_has_defined_cadences++)
17984                      /* this is the first user-defined cadence; clear the default user cadences */
17985                      num_cadence = 0;
17986                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17987                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17988                   else {
17989                      cadences[num_cadence] = new_cadence;
17990                      cidrings[num_cadence++] = cid_location;
17991                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17992                   }
17993                }
17994             }
17995          } else if (!strcasecmp(v->name, "ringtimeout")) {
17996             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17997          } else if (!strcasecmp(v->name, "prewink")) {
17998             confp->timing.prewinktime = atoi(v->value);
17999          } else if (!strcasecmp(v->name, "preflash")) {
18000             confp->timing.preflashtime = atoi(v->value);
18001          } else if (!strcasecmp(v->name, "wink")) {
18002             confp->timing.winktime = atoi(v->value);
18003          } else if (!strcasecmp(v->name, "flash")) {
18004             confp->timing.flashtime = atoi(v->value);
18005          } else if (!strcasecmp(v->name, "start")) {
18006             confp->timing.starttime = atoi(v->value);
18007          } else if (!strcasecmp(v->name, "rxwink")) {
18008             confp->timing.rxwinktime = atoi(v->value);
18009          } else if (!strcasecmp(v->name, "rxflash")) {
18010             confp->timing.rxflashtime = atoi(v->value);
18011          } else if (!strcasecmp(v->name, "debounce")) {
18012             confp->timing.debouncetime = atoi(v->value);
18013          } else if (!strcasecmp(v->name, "toneduration")) {
18014             int toneduration;
18015             int ctlfd;
18016             int res;
18017             struct dahdi_dialparams dps;
18018 
18019             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18020             if (ctlfd == -1) {
18021                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18022                return -1;
18023             }
18024 
18025             toneduration = atoi(v->value);
18026             if (toneduration > -1) {
18027                memset(&dps, 0, sizeof(dps));
18028 
18029                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18030                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18031                if (res < 0) {
18032                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18033                   close(ctlfd);
18034                   return -1;
18035                }
18036             }
18037             close(ctlfd);
18038          } else if (!strcasecmp(v->name, "defaultcic")) {
18039             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18040          } else if (!strcasecmp(v->name, "defaultozz")) {
18041             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18042          } else if (!strcasecmp(v->name, "mwilevel")) {
18043             mwilevel = atoi(v->value);
18044          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18045             dtmfcid_level = atoi(v->value);
18046          } else if (!strcasecmp(v->name, "reportalarms")) {
18047             if (!strcasecmp(v->value, "all"))
18048                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18049             if (!strcasecmp(v->value, "none"))
18050                report_alarms = 0;
18051             else if (!strcasecmp(v->value, "channels"))
18052                report_alarms = REPORT_CHANNEL_ALARMS;
18053             else if (!strcasecmp(v->value, "spans"))
18054                report_alarms = REPORT_SPAN_ALARMS;
18055           }
18056       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18057          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18058    }
18059 
18060    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18061    if (confp->chan.vars) {
18062       ast_variables_destroy(confp->chan.vars);
18063       confp->chan.vars = NULL;
18064    }
18065 
18066    if (dahdichan) {
18067       /* Process the deferred dahdichan value. */
18068       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18069          &found_pseudo)) {
18070          if (confp->ignore_failed_channels) {
18071             ast_log(LOG_WARNING,
18072                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18073                dahdichan->value);
18074          } else {
18075             return -1;
18076          }
18077       }
18078    }
18079 
18080    /* mark the first channels of each DAHDI span to watch for their span alarms */
18081    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18082       if (!tmp->destroy && tmp->span != y) {
18083          tmp->manages_span_alarms = 1;
18084          y = tmp->span; 
18085       } else {
18086          tmp->manages_span_alarms = 0;
18087       }
18088    }
18089 
18090    /*< \todo why check for the pseudo in the per-channel section.
18091     * Any actual use for manual setup of the pseudo channel? */
18092    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18093       /* use the default configuration for a channel, so
18094          that any settings from real configured channels
18095          don't "leak" into the pseudo channel config
18096       */
18097       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18098 
18099       if (conf.chan.cc_params) {
18100          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18101       } else {
18102          tmp = NULL;
18103       }
18104       if (tmp) {
18105          ast_verb(3, "Automatically generated pseudo channel\n");
18106       } else {
18107          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18108       }
18109       ast_cc_config_params_destroy(conf.chan.cc_params);
18110    }
18111    return 0;
18112 }
18113 
18114 /*!
18115  * \internal
18116  * \brief Deep copy struct dahdi_chan_conf.
18117  * \since 1.8
18118  *
18119  * \param dest Destination.
18120  * \param src Source.
18121  *
18122  * \return Nothing
18123  */
18124 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18125 {
18126    struct ast_cc_config_params *cc_params;
18127 
18128    cc_params = dest->chan.cc_params;
18129    *dest = *src;
18130    dest->chan.cc_params = cc_params;
18131    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18132 }
18133 
18134 /*!
18135  * \internal
18136  * \brief Setup DAHDI channel driver.
18137  *
18138  * \param reload enum: load_module(0), reload(1), restart(2).
18139  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18140  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18141  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18142  *
18143  * \retval 0 on success.
18144  * \retval -1 on error.
18145  */
18146 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18147 {
18148    struct ast_config *cfg;
18149    struct ast_config *ucfg;
18150    struct ast_variable *v;
18151    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18152    const char *chans;
18153    const char *cat;
18154    int res;
18155 
18156 #ifdef HAVE_PRI
18157    char *c;
18158    int spanno;
18159    int i;
18160    int logicalspan;
18161    int trunkgroup;
18162    int dchannels[SIG_PRI_NUM_DCHANS];
18163 #endif
18164    int have_cfg_now;
18165    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18166 
18167    cfg = ast_config_load(config, config_flags);
18168    have_cfg_now = !!cfg;
18169    if (!cfg) {
18170       /* Error if we have no config file */
18171       if (had_cfg_before) {
18172          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18173          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18174       }
18175       cfg = ast_config_new();/* Dummy config */
18176       if (!cfg) {
18177          return 0;
18178       }
18179       ucfg = ast_config_load("users.conf", config_flags);
18180       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18181          ast_config_destroy(cfg);
18182          return 0;
18183       }
18184       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18186          ast_config_destroy(cfg);
18187          return 0;
18188       }
18189    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18190       ucfg = ast_config_load("users.conf", config_flags);
18191       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18192          return 0;
18193       }
18194       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18195          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18196          return 0;
18197       }
18198       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18199       cfg = ast_config_load(config, config_flags);
18200       have_cfg_now = !!cfg;
18201       if (!cfg) {
18202          if (had_cfg_before) {
18203             /* We should have been able to load the config. */
18204             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18205             ast_config_destroy(ucfg);
18206             return 0;
18207          }
18208          cfg = ast_config_new();/* Dummy config */
18209          if (!cfg) {
18210             ast_config_destroy(ucfg);
18211             return 0;
18212          }
18213       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18214          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18215          ast_config_destroy(ucfg);
18216          return 0;
18217       }
18218    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18219       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18220       return 0;
18221    } else {
18222       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18223       ucfg = ast_config_load("users.conf", config_flags);
18224       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18225          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18226          ast_config_destroy(cfg);
18227          return 0;
18228       }
18229    }
18230    had_cfg_before = have_cfg_now;
18231 
18232    /* It's a little silly to lock it, but we might as well just to be sure */
18233    ast_mutex_lock(&iflock);
18234 #ifdef HAVE_PRI
18235    if (reload != 1) {
18236       /* Process trunkgroups first */
18237       v = ast_variable_browse(cfg, "trunkgroups");
18238       while (v) {
18239          if (!strcasecmp(v->name, "trunkgroup")) {
18240             trunkgroup = atoi(v->value);
18241             if (trunkgroup > 0) {
18242                if ((c = strchr(v->value, ','))) {
18243                   i = 0;
18244                   memset(dchannels, 0, sizeof(dchannels));
18245                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18246                      dchannels[i] = atoi(c + 1);
18247                      if (dchannels[i] < 0) {
18248                         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);
18249                      } else
18250                         i++;
18251                      c = strchr(c + 1, ',');
18252                   }
18253                   if (i) {
18254                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18255                         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);
18256                   } else
18257                         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");
18258                   } else
18259                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18260                } else
18261                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18262             } else
18263                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18264          } else if (!strcasecmp(v->name, "spanmap")) {
18265             spanno = atoi(v->value);
18266             if (spanno > 0) {
18267                if ((c = strchr(v->value, ','))) {
18268                   trunkgroup = atoi(c + 1);
18269                   if (trunkgroup > 0) {
18270                      if ((c = strchr(c + 1, ',')))
18271                         logicalspan = atoi(c + 1);
18272                      else
18273                         logicalspan = 0;
18274                      if (logicalspan >= 0) {
18275                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18276                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18277                      } else
18278                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18279                      } else
18280                         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);
18281                   } else
18282                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18283                } else
18284                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18285             } else
18286                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18287          } else {
18288             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18289          }
18290          v = v->next;
18291       }
18292    }
18293 #endif
18294 
18295    /* Copy the default jb config over global_jbconf */
18296    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18297 
18298    mwimonitornotify[0] = '\0';
18299 
18300    v = ast_variable_browse(cfg, "channels");
18301    if ((res = process_dahdi(base_conf,
18302       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18303       v, reload, 0))) {
18304       ast_mutex_unlock(&iflock);
18305       ast_config_destroy(cfg);
18306       if (ucfg) {
18307          ast_config_destroy(ucfg);
18308       }
18309       return res;
18310    }
18311 
18312    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18313    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18314       /* [channels] and [trunkgroups] are used. Let's also reserve
18315        * [globals] and [general] for future use
18316        */
18317       if (!strcasecmp(cat, "general") ||
18318          !strcasecmp(cat, "trunkgroups") ||
18319          !strcasecmp(cat, "globals") ||
18320          !strcasecmp(cat, "channels")) {
18321          continue;
18322       }
18323 
18324       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18325       if (ast_strlen_zero(chans)) {
18326          /* Section is useless without a dahdichan value present. */
18327          continue;
18328       }
18329 
18330       /* Copy base_conf to conf. */
18331       deep_copy_dahdi_chan_conf(conf, base_conf);
18332 
18333       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18334          ast_mutex_unlock(&iflock);
18335          ast_config_destroy(cfg);
18336          if (ucfg) {
18337             ast_config_destroy(ucfg);
18338          }
18339          return res;
18340       }
18341    }
18342 
18343    ast_config_destroy(cfg);
18344 
18345    if (ucfg) {
18346       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18347       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18348       process_dahdi(base_conf,
18349          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18350          ast_variable_browse(ucfg, "general"), 1, 0);
18351 
18352       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18353          if (!strcasecmp(cat, "general")) {
18354             continue;
18355          }
18356 
18357          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18358          if (ast_strlen_zero(chans)) {
18359             /* Section is useless without a dahdichan value present. */
18360             continue;
18361          }
18362 
18363          /* Copy base_conf to conf. */
18364          deep_copy_dahdi_chan_conf(conf, base_conf);
18365 
18366          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18367             ast_config_destroy(ucfg);
18368             ast_mutex_unlock(&iflock);
18369             return res;
18370          }
18371       }
18372       ast_config_destroy(ucfg);
18373    }
18374    ast_mutex_unlock(&iflock);
18375 
18376 #ifdef HAVE_PRI
18377    if (reload != 1) {
18378       int x;
18379       for (x = 0; x < NUM_SPANS; x++) {
18380          if (pris[x].pri.pvts[0]) {
18381             prepare_pri(pris + x);
18382             if (sig_pri_start_pri(&pris[x].pri)) {
18383                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18384                return -1;
18385             } else
18386                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18387          }
18388       }
18389    }
18390 #endif
18391 #if defined(HAVE_SS7)
18392    if (reload != 1) {
18393       int x;
18394       for (x = 0; x < NUM_SPANS; x++) {
18395          if (linksets[x].ss7.ss7) {
18396             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18397             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18398                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18399                return -1;
18400             } else
18401                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18402          }
18403       }
18404    }
18405 #endif   /* defined(HAVE_SS7) */
18406 #ifdef HAVE_OPENR2
18407    if (reload != 1) {
18408       int x;
18409       for (x = 0; x < r2links_count; x++) {
18410          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18411             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18412             return -1;
18413          } else {
18414             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18415          }
18416       }
18417    }
18418 #endif
18419    /* And start the monitor for the first time */
18420    restart_monitor();
18421    return 0;
18422 }
18423 
18424 /*!
18425  * \internal
18426  * \brief Setup DAHDI channel driver.
18427  *
18428  * \param reload enum: load_module(0), reload(1), restart(2).
18429  *
18430  * \retval 0 on success.
18431  * \retval -1 on error.
18432  */
18433 static int setup_dahdi(int reload)
18434 {
18435    int res;
18436    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18437    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18438    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18439 
18440    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18441       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18442    } else {
18443       res = -1;
18444    }
18445    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18446    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18447    ast_cc_config_params_destroy(conf.chan.cc_params);
18448 
18449    return res;
18450 }
18451 
18452 /*!
18453  * \internal
18454  * \brief Callback used to generate the dahdi status tree.
18455  * \param[in] search The search pattern tree.
18456  * \retval NULL on error.
18457  * \retval non-NULL The generated tree.
18458  */
18459 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18460       struct ast_data *data_root)
18461 {
18462    int ctl, res, span;
18463    struct ast_data *data_span, *data_alarms;
18464    struct dahdi_spaninfo s;
18465 
18466    ctl = open("/dev/dahdi/ctl", O_RDWR);
18467    if (ctl < 0) {
18468       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18469       return -1;
18470    }
18471    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18472       s.spanno = span;
18473       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18474       if (res) {
18475          continue;
18476       }
18477 
18478       data_span = ast_data_add_node(data_root, "span");
18479       if (!data_span) {
18480          continue;
18481       }
18482       ast_data_add_str(data_span, "description", s.desc);
18483 
18484       /* insert the alarms status */
18485       data_alarms = ast_data_add_node(data_span, "alarms");
18486       if (!data_alarms) {
18487          continue;
18488       }
18489 
18490       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18491       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18492       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18493       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18494       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18495       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18496 
18497       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18498       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18499       ast_data_add_int(data_span, "crc4", s.crc4count);
18500       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18501                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18502                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18503                      "CAS");
18504       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18505                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18506                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18507                      "Unknown");
18508       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18509                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18510                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18511       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18512 
18513       /* if this span doesn't match remove it. */
18514       if (!ast_data_search_match(search, data_span)) {
18515          ast_data_remove_node(data_root, data_span);
18516       }
18517    }
18518    close(ctl);
18519 
18520    return 0;
18521 }
18522 
18523 /*!
18524  * \internal
18525  * \brief Callback used to generate the dahdi channels tree.
18526  * \param[in] search The search pattern tree.
18527  * \retval NULL on error.
18528  * \retval non-NULL The generated tree.
18529  */
18530 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18531       struct ast_data *data_root)
18532 {
18533    struct dahdi_pvt *tmp;
18534    struct ast_data *data_channel;
18535 
18536    ast_mutex_lock(&iflock);
18537    for (tmp = iflist; tmp; tmp = tmp->next) {
18538       data_channel = ast_data_add_node(data_root, "channel");
18539       if (!data_channel) {
18540          continue;
18541       }
18542 
18543       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18544 
18545       /* if this channel doesn't match remove it. */
18546       if (!ast_data_search_match(search, data_channel)) {
18547          ast_data_remove_node(data_root, data_channel);
18548       }
18549    }
18550    ast_mutex_unlock(&iflock);
18551 
18552    return 0;
18553 }
18554 
18555 /*!
18556  * \internal
18557  * \brief Callback used to generate the dahdi channels tree.
18558  * \param[in] search The search pattern tree.
18559  * \retval NULL on error.
18560  * \retval non-NULL The generated tree.
18561  */
18562 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18563       struct ast_data *data_root)
18564 {
18565    int pseudo_fd = -1;
18566    struct dahdi_versioninfo vi = {
18567       .version = "Unknown",
18568       .echo_canceller = "Unknown"
18569    };
18570 
18571    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18572       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18573       return -1;
18574    }
18575 
18576    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18577       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18578    }
18579 
18580    close(pseudo_fd);
18581 
18582    ast_data_add_str(data_root, "value", vi.version);
18583    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18584 
18585    return 0;
18586 }
18587 
18588 static const struct ast_data_handler dahdi_status_data_provider = {
18589    .version = AST_DATA_HANDLER_VERSION,
18590    .get = dahdi_status_data_provider_get
18591 };
18592 
18593 static const struct ast_data_handler dahdi_channels_data_provider = {
18594    .version = AST_DATA_HANDLER_VERSION,
18595    .get = dahdi_channels_data_provider_get
18596 };
18597 
18598 static const struct ast_data_handler dahdi_version_data_provider = {
18599    .version = AST_DATA_HANDLER_VERSION,
18600    .get = dahdi_version_data_provider_get
18601 };
18602 
18603 static const struct ast_data_entry dahdi_data_providers[] = {
18604    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18605    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18606    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18607 };
18608 
18609 static int load_module(void)
18610 {
18611    int res;
18612 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18613    int y;
18614 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18615 
18616 #ifdef HAVE_PRI
18617    memset(pris, 0, sizeof(pris));
18618    for (y = 0; y < NUM_SPANS; y++) {
18619       sig_pri_init_pri(&pris[y].pri);
18620    }
18621    pri_set_error(dahdi_pri_error);
18622    pri_set_message(dahdi_pri_message);
18623    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18624 #ifdef HAVE_PRI_PROG_W_CAUSE
18625    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18626 #endif
18627 #if defined(HAVE_PRI_CCSS)
18628    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18629       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18630       __unload_module();
18631       return AST_MODULE_LOAD_FAILURE;
18632    }
18633 #endif   /* defined(HAVE_PRI_CCSS) */
18634    if (sig_pri_load(
18635 #if defined(HAVE_PRI_CCSS)
18636       dahdi_pri_cc_type
18637 #else
18638       NULL
18639 #endif   /* defined(HAVE_PRI_CCSS) */
18640       )) {
18641       __unload_module();
18642       return AST_MODULE_LOAD_FAILURE;
18643    }
18644 #endif
18645 #if defined(HAVE_SS7)
18646    memset(linksets, 0, sizeof(linksets));
18647    for (y = 0; y < NUM_SPANS; y++) {
18648       sig_ss7_init_linkset(&linksets[y].ss7);
18649    }
18650    ss7_set_error(dahdi_ss7_error);
18651    ss7_set_message(dahdi_ss7_message);
18652 #endif   /* defined(HAVE_SS7) */
18653    res = setup_dahdi(0);
18654    /* Make sure we can register our DAHDI channel type */
18655    if (res)
18656       return AST_MODULE_LOAD_DECLINE;
18657    if (ast_channel_register(&dahdi_tech)) {
18658       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18659       __unload_module();
18660       return AST_MODULE_LOAD_FAILURE;
18661    }
18662 #ifdef HAVE_PRI
18663    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18664 #endif
18665 #if defined(HAVE_SS7)
18666    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18667 #endif   /* defined(HAVE_SS7) */
18668 #ifdef HAVE_OPENR2
18669    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18670    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18671 #endif
18672 
18673    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18674    /* register all the data providers */
18675    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18676    memset(round_robin, 0, sizeof(round_robin));
18677    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18678    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18679    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18680    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18681    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18682    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18683    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18684 
18685    ast_cond_init(&ss_thread_complete, NULL);
18686 
18687    return res;
18688 }
18689 
18690 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18691 {
18692 #define  END_SILENCE_LEN 400
18693 #define  HEADER_MS 50
18694 #define  TRAILER_MS 5
18695 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18696 #define  ASCII_BYTES_PER_CHAR 80
18697 
18698    unsigned char *buf,*mybuf;
18699    struct dahdi_pvt *p = c->tech_pvt;
18700    struct pollfd fds[1];
18701    int size,res,fd,len,x;
18702    int bytes=0;
18703    /* Initial carrier (imaginary) */
18704    float cr = 1.0;
18705    float ci = 0.0;
18706    float scont = 0.0;
18707    int idx;
18708 
18709    idx = dahdi_get_index(c, p, 0);
18710    if (idx < 0) {
18711       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18712       return -1;
18713    }
18714    if (!text[0]) return(0); /* if nothing to send, don't */
18715    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18716    if (p->mate)
18717       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18718    else
18719       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18720    if (!buf)
18721       return -1;
18722    mybuf = buf;
18723    if (p->mate) {
18724       int codec = AST_LAW(p);
18725       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18726          PUT_CLID_MARKMS;
18727       }
18728       /* Put actual message */
18729       for (x = 0; text[x]; x++) {
18730          PUT_CLID(text[x]);
18731       }
18732       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18733          PUT_CLID_MARKMS;
18734       }
18735       len = bytes;
18736       buf = mybuf;
18737    } else {
18738       len = tdd_generate(p->tdd, buf, text);
18739       if (len < 1) {
18740          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18741          ast_free(mybuf);
18742          return -1;
18743       }
18744    }
18745    memset(buf + len, 0x7f, END_SILENCE_LEN);
18746    len += END_SILENCE_LEN;
18747    fd = p->subs[idx].dfd;
18748    while (len) {
18749       if (ast_check_hangup(c)) {
18750          ast_free(mybuf);
18751          return -1;
18752       }
18753       size = len;
18754       if (size > READ_SIZE)
18755          size = READ_SIZE;
18756       fds[0].fd = fd;
18757       fds[0].events = POLLOUT | POLLPRI;
18758       fds[0].revents = 0;
18759       res = poll(fds, 1, -1);
18760       if (!res) {
18761          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18762          continue;
18763       }
18764       /* if got exception */
18765       if (fds[0].revents & POLLPRI) {
18766          ast_free(mybuf);
18767          return -1;
18768       }
18769       if (!(fds[0].revents & POLLOUT)) {
18770          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18771          continue;
18772       }
18773       res = write(fd, buf, size);
18774       if (res != size) {
18775          if (res == -1) {
18776             ast_free(mybuf);
18777             return -1;
18778          }
18779          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18780          break;
18781       }
18782       len -= size;
18783       buf += size;
18784    }
18785    ast_free(mybuf);
18786    return(0);
18787 }
18788 
18789 
18790 static int reload(void)
18791 {
18792    int res = 0;
18793 
18794    res = setup_dahdi(1);
18795    if (res) {
18796       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18797       return -1;
18798    }
18799    return 0;
18800 }
18801 
18802 /* This is a workaround so that menuselect displays a proper description
18803  * AST_MODULE_INFO(, , "DAHDI Telephony"
18804  */
18805 
18806 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18807    .load = load_module,
18808    .unload = unload_module,
18809    .reload = reload,
18810    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18811       .nonoptreq = "res_smdi",
18812    );

Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1