Thu Apr 3 08:20:18 2014

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: 404784 $")
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_conf {
00555    openr2_variant_t variant;
00556    int mfback_timeout;
00557    int metering_pulse_timeout;
00558    int max_ani;
00559    int max_dnis;
00560    signed int get_ani_first:2;
00561 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00562    signed int skip_category_request:2;
00563 #endif
00564    unsigned int call_files:1;
00565    unsigned int allow_collect_calls:1;
00566    unsigned int charge_calls:1;
00567    unsigned int accept_on_offer:1;
00568    unsigned int forced_release:1;
00569    unsigned int double_answer:1;
00570    signed int immediate_accept:2;
00571    char logdir[OR2_MAX_PATH];
00572    char r2proto_file[OR2_MAX_PATH];
00573    openr2_log_level_t loglevel;
00574    openr2_calling_party_category_t category;
00575 };
00576 
00577 /* MFC-R2 pseudo-link structure */
00578 struct dahdi_mfcr2 {
00579    pthread_t r2master;            /*!< Thread of master */
00580    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00581    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00582    int numchans;                          /*!< Number of channels in this R2 block */
00583    struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
00584 };
00585 
00586 /* malloc'd array of malloc'd r2links */
00587 static struct dahdi_mfcr2 **r2links;
00588 /* how many r2links have been malloc'd */
00589 static int r2links_count = 0;
00590 
00591 #endif /* HAVE_OPENR2 */
00592 
00593 #ifdef HAVE_PRI
00594 
00595 struct dahdi_pri {
00596    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00597    int mastertrunkgroup;               /*!< What trunk group is our master */
00598    int prilogicalspan;                 /*!< Logical span number within trunk group */
00599    struct sig_pri_span pri;
00600 };
00601 
00602 static struct dahdi_pri pris[NUM_SPANS];
00603 
00604 #if defined(HAVE_PRI_CCSS)
00605 /*! DAHDI PRI CCSS agent and monitor type name. */
00606 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00607 #endif   /* defined(HAVE_PRI_CCSS) */
00608 
00609 #else
00610 /*! Shut up the compiler */
00611 struct dahdi_pri;
00612 #endif
00613 
00614 #define SUB_REAL  0        /*!< Active call */
00615 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00616 #define SUB_THREEWAY 2        /*!< Three-way call */
00617 
00618 /* Polarity states */
00619 #define POLARITY_IDLE   0
00620 #define POLARITY_REV    1
00621 
00622 
00623 struct distRingData {
00624    int ring[3];
00625    int range;
00626 };
00627 struct ringContextData {
00628    char contextData[AST_MAX_CONTEXT];
00629 };
00630 struct dahdi_distRings {
00631    struct distRingData ringnum[3];
00632    struct ringContextData ringContext[3];
00633 };
00634 
00635 static const char * const subnames[] = {
00636    "Real",
00637    "Callwait",
00638    "Threeway"
00639 };
00640 
00641 struct dahdi_subchannel {
00642    int dfd;
00643    struct ast_channel *owner;
00644    int chan;
00645    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00646    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00647    unsigned int needringing:1;
00648    unsigned int needbusy:1;
00649    unsigned int needcongestion:1;
00650    unsigned int needanswer:1;
00651    unsigned int needflash:1;
00652    unsigned int needhold:1;
00653    unsigned int needunhold:1;
00654    unsigned int linear:1;
00655    unsigned int inthreeway:1;
00656    struct dahdi_confinfo curconf;
00657 };
00658 
00659 #define CONF_USER_REAL     (1 << 0)
00660 #define CONF_USER_THIRDCALL   (1 << 1)
00661 
00662 #define MAX_SLAVES   4
00663 
00664 /* States for sending MWI message
00665  * First three states are required for send Ring Pulse Alert Signal
00666  */
00667 typedef enum {
00668    MWI_SEND_NULL = 0,
00669    MWI_SEND_SA,
00670    MWI_SEND_SA_WAIT,
00671    MWI_SEND_PAUSE,
00672    MWI_SEND_SPILL,
00673    MWI_SEND_CLEANUP,
00674    MWI_SEND_DONE,
00675 } mwisend_states;
00676 
00677 struct mwisend_info {
00678    struct   timeval  pause;
00679    mwisend_states    mwisend_current;
00680 };
00681 
00682 /*! Specify the lists dahdi_pvt can be put in. */
00683 enum DAHDI_IFLIST {
00684    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00685    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00686 #if defined(HAVE_PRI)
00687    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00688 #endif   /* defined(HAVE_PRI) */
00689 };
00690 
00691 struct dahdi_pvt {
00692    ast_mutex_t lock;             /*!< Channel private lock. */
00693    struct callerid_state *cs;
00694    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00695                      /*!< Up to three channels can be associated with this call */
00696 
00697    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00698    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00699    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00700 
00701    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00702    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00703    int inconference;          /*!< If our real should be in the conference */
00704 
00705    int bufsize;                /*!< Size of the buffers */
00706    int buf_no;             /*!< Number of buffers */
00707    int buf_policy;            /*!< Buffer policy */
00708    int faxbuf_no;              /*!< Number of Fax buffers */
00709    int faxbuf_policy;          /*!< Fax buffer policy */
00710    int sig;             /*!< Signalling style */
00711    /*!
00712     * \brief Nonzero if the signaling type is sent over a radio.
00713     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00714     */
00715    int radio;
00716    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00717    int oprmode;               /*!< "Operator Services" mode */
00718    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00719    /*! \brief Amount of gain to increase during caller id */
00720    float cid_rxgain;
00721    /*! \brief Software Rx gain set by chan_dahdi.conf */
00722    float rxgain;
00723    /*! \brief Software Tx gain set by chan_dahdi.conf */
00724    float txgain;
00725 
00726    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00727    float rxdrc;
00728    
00729    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00730    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00731    struct dahdi_pvt *next;          /*!< Next channel in list */
00732    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00733 
00734    /* flags */
00735 
00736    /*!
00737     * \brief TRUE if ADSI (Analog Display Services Interface) available
00738     * \note Set from the "adsi" value read in from chan_dahdi.conf
00739     */
00740    unsigned int adsi:1;
00741    /*!
00742     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00743     * call is answered by the remote party.
00744     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00745     */
00746    unsigned int answeronpolarityswitch:1;
00747    /*!
00748     * \brief TRUE if busy detection is enabled.
00749     * (Listens for the beep-beep busy pattern.)
00750     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00751     */
00752    unsigned int busydetect:1;
00753    /*!
00754     * \brief TRUE if call return is enabled.
00755     * (*69, if your dialplan doesn't catch this first)
00756     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00757     */
00758    unsigned int callreturn:1;
00759    /*!
00760     * \brief TRUE if busy extensions will hear the call-waiting tone
00761     * and can use hook-flash to switch between callers.
00762     * \note Can be disabled by dialing *70.
00763     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00764     */
00765    unsigned int callwaiting:1;
00766    /*!
00767     * \brief TRUE if send caller ID for Call Waiting
00768     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00769     */
00770    unsigned int callwaitingcallerid:1;
00771    /*!
00772     * \brief TRUE if support for call forwarding enabled.
00773     * Dial *72 to enable call forwarding.
00774     * Dial *73 to disable call forwarding.
00775     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00776     */
00777    unsigned int cancallforward:1;
00778    /*!
00779     * \brief TRUE if support for call parking is enabled.
00780     * \note Set from the "canpark" value read in from chan_dahdi.conf
00781     */
00782    unsigned int canpark:1;
00783    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00784    unsigned int confirmanswer:1;
00785    /*!
00786     * \brief TRUE if the channel is to be destroyed on hangup.
00787     * (Used by pseudo channels.)
00788     */
00789    unsigned int destroy:1;
00790    unsigned int didtdd:1;           /*!< flag to say its done it once */
00791    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00792    unsigned int dialednone:1;
00793    /*!
00794     * \brief TRUE if in the process of dialing digits or sending something.
00795     * \note This is used as a receive squelch for ISDN until connected.
00796     */
00797    unsigned int dialing:1;
00798    /*! \brief TRUE if the transfer capability of the call is digital. */
00799    unsigned int digital:1;
00800    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00801    unsigned int dnd:1;
00802    /*! \brief XXX BOOLEAN Purpose??? */
00803    unsigned int echobreak:1;
00804    /*!
00805     * \brief TRUE if echo cancellation enabled when bridged.
00806     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00807     * \note Disabled if the echo canceller is not setup.
00808     */
00809    unsigned int echocanbridged:1;
00810    /*! \brief TRUE if echo cancellation is turned on. */
00811    unsigned int echocanon:1;
00812    /*! \brief TRUE if a fax tone has already been handled. */
00813    unsigned int faxhandled:1;
00814    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00815    unsigned int usefaxbuffers:1;
00816    /*! TRUE while buffer configuration override is in use */
00817    unsigned int bufferoverrideinuse:1;
00818    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00819    unsigned int firstradio:1;
00820    /*!
00821     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00822     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00823     */
00824    unsigned int hanguponpolarityswitch:1;
00825    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00826    unsigned int hardwaredtmf:1;
00827    /*!
00828     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00829     * \note Caller ID can be disabled by dialing *67.
00830     * \note Caller ID can be enabled by dialing *82.
00831     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00832     */
00833    unsigned int hidecallerid:1;
00834    /*!
00835     * \brief TRUE if hide just the name not the number for legacy PBX use.
00836     * \note Only applies to PRI channels.
00837     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00838     */
00839    unsigned int hidecalleridname:1;
00840    /*! \brief TRUE if DTMF detection is disabled. */
00841    unsigned int ignoredtmf:1;
00842    /*!
00843     * \brief TRUE if the channel should be answered immediately
00844     * without attempting to gather any digits.
00845     * \note Set from the "immediate" value read in from chan_dahdi.conf
00846     */
00847    unsigned int immediate:1;
00848    /*! \brief TRUE if in an alarm condition. */
00849    unsigned int inalarm:1;
00850    /*! \brief TRUE if TDD in MATE mode */
00851    unsigned int mate:1;
00852    /*! \brief TRUE if we originated the call leg. */
00853    unsigned int outgoing:1;
00854    /* unsigned int overlapdial:1;         unused and potentially confusing */
00855    /*!
00856     * \brief TRUE if busy extensions will hear the call-waiting tone
00857     * and can use hook-flash to switch between callers.
00858     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00859     */
00860    unsigned int permcallwaiting:1;
00861    /*!
00862     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00863     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00864     */
00865    unsigned int permhidecallerid:1;
00866    /*!
00867     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00868     * \note Set from the "priindication" value read in from chan_dahdi.conf
00869     */
00870    unsigned int priindication_oob:1;
00871    /*!
00872     * \brief TRUE if PRI B channels are always exclusively selected.
00873     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00874     */
00875    unsigned int priexclusive:1;
00876    /*!
00877     * \brief TRUE if we will pulse dial.
00878     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00879     */
00880    unsigned int pulse:1;
00881    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00882    unsigned int pulsedial:1;
00883    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00884    /*!
00885     * \brief TRUE if caller ID is restricted.
00886     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00887     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00888     */
00889    unsigned int restrictcid:1;
00890    /*!
00891     * \brief TRUE if three way calling is enabled
00892     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00893     */
00894    unsigned int threewaycalling:1;
00895    /*!
00896     * \brief TRUE if call transfer is enabled
00897     * \note For FXS ports (either direct analog or over T1/E1):
00898     *   Support flash-hook call transfer
00899     * \note For digital ports using ISDN PRI protocols:
00900     *   Support switch-side transfer (called 2BCT, RLT or other names)
00901     * \note Set from the "transfer" value read in from chan_dahdi.conf
00902     */
00903    unsigned int transfer:1;
00904    /*!
00905     * \brief TRUE if caller ID is used on this channel.
00906     * \note PRI and SS7 spans will save caller ID from the networking peer.
00907     * \note FXS ports will generate the caller ID spill.
00908     * \note FXO ports will listen for the caller ID spill.
00909     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00910     */
00911    unsigned int use_callerid:1;
00912    /*!
00913     * \brief TRUE if we will use the calling presentation setting
00914     * from the Asterisk channel for outgoing calls.
00915     * \note Only applies to PRI and SS7 channels.
00916     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00917     */
00918    unsigned int use_callingpres:1;
00919    /*!
00920     * \brief TRUE if distinctive rings are to be detected.
00921     * \note For FXO lines
00922     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00923     */
00924    unsigned int usedistinctiveringdetection:1;
00925    /*!
00926     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00927     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00928     */
00929    unsigned int dahditrcallerid:1;
00930    /*!
00931     * \brief TRUE if allowed to flash-transfer to busy channels.
00932     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00933     */
00934    unsigned int transfertobusy:1;
00935    /*!
00936     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00937     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00938     */
00939    unsigned int mwimonitor_neon:1;
00940    /*!
00941     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00942     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00943     */
00944    unsigned int mwimonitor_fsk:1;
00945    /*!
00946     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00947     * \note RPAS - Ring Pulse Alert Signal
00948     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00949     */
00950    unsigned int mwimonitor_rpas:1;
00951    /*! \brief TRUE if an MWI monitor thread is currently active */
00952    unsigned int mwimonitoractive:1;
00953    /*! \brief TRUE if a MWI message sending thread is active */
00954    unsigned int mwisendactive:1;
00955    /*!
00956     * \brief TRUE if channel is out of reset and ready
00957     * \note Set but not used.
00958     */
00959    unsigned int inservice:1;
00960    /*!
00961     * \brief TRUE if the channel is locally blocked.
00962     * \note Applies to SS7 and MFCR2 channels.
00963     */
00964    unsigned int locallyblocked:1;
00965    /*!
00966     * \brief TRUE if the channel is remotely blocked.
00967     * \note Applies to SS7 and MFCR2 channels.
00968     */
00969    unsigned int remotelyblocked:1;
00970    /*!
00971     * \brief TRUE if the channel alarms will be managed also as Span ones
00972     * \note Applies to all channels
00973     */
00974    unsigned int manages_span_alarms:1;
00975 
00976 #if defined(HAVE_PRI)
00977    struct sig_pri_span *pri;
00978    int logicalspan;
00979 #endif
00980    /*!
00981     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00982     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00983     */
00984    unsigned int use_smdi:1;
00985    struct mwisend_info mwisend_data;
00986    /*! \brief The SMDI interface to get SMDI messages from. */
00987    struct ast_smdi_interface *smdi_iface;
00988 
00989    /*! \brief Distinctive Ring data */
00990    struct dahdi_distRings drings;
00991 
00992    /*!
00993     * \brief The configured context for incoming calls.
00994     * \note The "context" string read in from chan_dahdi.conf
00995     */
00996    char context[AST_MAX_CONTEXT];
00997    /*!
00998     * \brief Saved context string.
00999     */
01000    char defcontext[AST_MAX_CONTEXT];
01001    /*! \brief Extension to use in the dialplan. */
01002    char exten[AST_MAX_EXTENSION];
01003    /*!
01004     * \brief Language configured for calls.
01005     * \note The "language" string read in from chan_dahdi.conf
01006     */
01007    char language[MAX_LANGUAGE];
01008    /*!
01009     * \brief The configured music-on-hold class to use for calls.
01010     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01011     */
01012    char mohinterpret[MAX_MUSICCLASS];
01013    /*!
01014     * \brief Suggested music-on-hold class for peer channel to use for calls.
01015     * \note The "mohsuggest" string read in from chan_dahdi.conf
01016     */
01017    char mohsuggest[MAX_MUSICCLASS];
01018    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01020    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01021    char cid_ani[AST_MAX_EXTENSION];
01022 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01023    /*! \brief Automatic Number Identification code from PRI */
01024    int cid_ani2;
01025    /*! \brief Caller ID number from an incoming call. */
01026    char cid_num[AST_MAX_EXTENSION];
01027    /*!
01028     * \brief Caller ID tag from incoming call
01029     * \note the "cid_tag" string read in from chan_dahdi.conf
01030     */
01031    char cid_tag[AST_MAX_EXTENSION];
01032    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01033    int cid_ton;
01034    /*! \brief Caller ID name from an incoming call. */
01035    char cid_name[AST_MAX_EXTENSION];
01036    /*! \brief Caller ID subaddress from an incoming call. */
01037    char cid_subaddr[AST_MAX_EXTENSION];
01038    char *origcid_num;            /*!< malloced original callerid */
01039    char *origcid_name;           /*!< malloced original callerid */
01040    /*! \brief Call waiting number. */
01041    char callwait_num[AST_MAX_EXTENSION];
01042    /*! \brief Call waiting name. */
01043    char callwait_name[AST_MAX_EXTENSION];
01044    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01045    char rdnis[AST_MAX_EXTENSION];
01046    /*! \brief Dialed Number Identifier */
01047    char dnid[AST_MAX_EXTENSION];
01048    /*!
01049     * \brief Bitmapped groups this belongs to.
01050     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01051     */
01052    ast_group_t group;
01053    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01054    int law_default;
01055    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01056    int law;
01057    int confno;             /*!< Our conference */
01058    int confusers;             /*!< Who is using our conference */
01059    int propconfno;               /*!< Propagated conference number */
01060    /*!
01061     * \brief Bitmapped call groups this belongs to.
01062     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01063     */
01064    ast_group_t callgroup;
01065    /*!
01066     * \brief Bitmapped pickup groups this belongs to.
01067     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01068     */
01069    ast_group_t pickupgroup;
01070    /*!
01071     * \brief Channel variable list with associated values to set when a channel is created.
01072     * \note The "setvar" strings read in from chan_dahdi.conf
01073     */
01074    struct ast_variable *vars;
01075    int channel;               /*!< Channel Number */
01076    int span;               /*!< Span number */
01077    time_t guardtime;          /*!< Must wait this much time before using for new call */
01078    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01079    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01080    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01081    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01082    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01083    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01084    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01085    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01086    /*! \brief Analog caller ID waveform sample buffer */
01087    unsigned char *cidspill;
01088    /*! \brief Position in the cidspill buffer to send out next. */
01089    int cidpos;
01090    /*! \brief Length of the cidspill buffer containing samples. */
01091    int cidlen;
01092    /*! \brief Ring timeout timer?? */
01093    int ringt;
01094    /*!
01095     * \brief Ring timeout base.
01096     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01097     */
01098    int ringt_base;
01099    /*!
01100     * \brief Number of most significant digits/characters to strip from the dialed number.
01101     * \note Feature is deprecated.  Use dialplan logic.
01102     * \note The characters are stripped before the PRI TON/NPI prefix
01103     * characters are processed.
01104     */
01105    int stripmsd;
01106    /*!
01107     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01108     * \note
01109     * After CAS is sent, the call waiting caller id will be sent if the phone
01110     * gives a positive reply.
01111     */
01112    int callwaitcas;
01113    /*! \brief Number of call waiting rings. */
01114    int callwaitrings;
01115    /*! \brief Echo cancel parameters. */
01116    struct {
01117       struct dahdi_echocanparams head;
01118       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01119    } echocancel;
01120    /*!
01121     * \brief Echo training time. 0 = disabled
01122     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01123     */
01124    int echotraining;
01125    /*! \brief Filled with 'w'.  XXX Purpose?? */
01126    char echorest[20];
01127    /*!
01128     * \brief Number of times to see "busy" tone before hanging up.
01129     * \note Set from the "busycount" value read in from chan_dahdi.conf
01130     */
01131    int busycount;
01132    /*!
01133     * \brief Length of "busy" tone on time.
01134     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01135     */
01136    int busy_tonelength;
01137    /*!
01138     * \brief Length of "busy" tone off time.
01139     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01140     */
01141    int busy_quietlength;
01142    /*!
01143     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01144     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01145     */
01146    int callprogress;
01147    /*!
01148     * \brief Number of milliseconds to wait for dialtone.
01149     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01150     */
01151    int waitfordialtone;
01152    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01153    struct timeval flashtime;        /*!< Last flash-hook time */
01154    /*! \brief Opaque DSP configuration structure. */
01155    struct ast_dsp *dsp;
01156    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01157    struct dahdi_dialoperation dop;
01158    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01159    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01160    char finaldial[64];
01161    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01162    int amaflags;              /*!< AMA Flags */
01163    struct tdd_state *tdd;           /*!< TDD flag */
01164    /*! \brief Accumulated call forwarding number. */
01165    char call_forward[AST_MAX_EXTENSION];
01166    /*!
01167     * \brief Voice mailbox location.
01168     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01169     */
01170    char mailbox[AST_MAX_EXTENSION];
01171    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01172    struct ast_event_sub *mwi_event_sub;
01173    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01174    char dialdest[256];
01175 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01176    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01177    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01178    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01179 #endif
01180    int distinctivering;          /*!< Which distinctivering to use */
01181    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01182    /*! \brief Holding place for event injected from outside normal operation. */
01183    int fake_event;
01184    /*!
01185     * \brief Minimal time period (ms) between the answer polarity
01186     * switch and hangup polarity switch.
01187     */
01188    int polarityonanswerdelay;
01189    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01190    struct timeval polaritydelaytv;
01191    /*!
01192     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01193     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01194     */
01195    int sendcalleridafter;
01196    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01197    int polarity;
01198    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01199    int dsp_features;
01200 #if defined(HAVE_SS7)
01201    /*! \brief SS7 control parameters */
01202    struct sig_ss7_linkset *ss7;
01203 #endif   /* defined(HAVE_SS7) */
01204 #ifdef HAVE_OPENR2
01205    struct dahdi_mfcr2 *mfcr2;
01206    openr2_chan_t *r2chan;
01207    openr2_calling_party_category_t mfcr2_recvd_category;
01208    openr2_calling_party_category_t mfcr2_category;
01209    int mfcr2_dnis_index;
01210    int mfcr2_ani_index;
01211    int mfcr2call:1;
01212    int mfcr2_answer_pending:1;
01213    int mfcr2_charge_calls:1;
01214    int mfcr2_allow_collect_calls:1;
01215    int mfcr2_forced_release:1;
01216    int mfcr2_dnis_matched:1;
01217    int mfcr2_call_accepted:1;
01218    int mfcr2_progress:1;
01219    int mfcr2_accept_on_offer:1;
01220 #endif
01221    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01222    char begindigit;
01223    /*! \brief TRUE if confrence is muted. */
01224    int muting;
01225    void *sig_pvt;
01226    struct ast_cc_config_params *cc_params;
01227    /* DAHDI channel names may differ greatly from the
01228     * string that was provided to an app such as Dial. We
01229     * need to save the original string passed to dahdi_request
01230     * for call completion purposes. This way, we can replicate
01231     * the original dialed string later.
01232     */
01233    char dialstring[AST_CHANNEL_NAME];
01234 };
01235 
01236 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01237    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01238    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01239    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01240    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01241    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01242    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01243    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01244    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01246    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01247    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01248    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01249    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01250    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01251    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01252    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01253    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01255    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01256    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01257    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01258    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01259    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01260    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01261    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01262    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01263    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01265    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01266    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01267    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01268    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01269    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01270    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01271    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01272    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01273    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01274    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01275    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01276    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01277    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01278    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01279    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01280    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01281    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01282    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01283    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01284    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01285    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01286    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01287    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01288    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01289    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01290    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01291    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01292    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01293    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01294    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01295    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01296    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01297    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01298    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01299    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01300    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01301    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01302    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01303    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01304 
01305 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01306 
01307 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01308 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01309 
01310 #if defined(HAVE_PRI)
01311 static struct dahdi_parms_pseudo {
01312    int buf_no;             /*!< Number of buffers */
01313    int buf_policy;            /*!< Buffer policy */
01314    int faxbuf_no;              /*!< Number of Fax buffers */
01315    int faxbuf_policy;          /*!< Fax buffer policy */
01316 } dahdi_pseudo_parms;
01317 #endif   /* defined(HAVE_PRI) */
01318 
01319 /*! \brief Channel configuration from chan_dahdi.conf .
01320  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01321  * Generally there is a field here for every possible configuration item.
01322  *
01323  * The state of fields is saved along the parsing and whenever a 'channel'
01324  * statement is reached, the current dahdi_chan_conf is used to configure the
01325  * channel (struct dahdi_pvt)
01326  *
01327  * \see dahdi_chan_init for the default values.
01328  */
01329 struct dahdi_chan_conf {
01330    struct dahdi_pvt chan;
01331 #ifdef HAVE_PRI
01332    struct dahdi_pri pri;
01333 #endif
01334 
01335 #if defined(HAVE_SS7)
01336    struct dahdi_ss7 ss7;
01337 #endif   /* defined(HAVE_SS7) */
01338 
01339 #ifdef HAVE_OPENR2
01340    struct dahdi_mfcr2_conf mfcr2;
01341 #endif
01342    struct dahdi_params timing;
01343    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01344    /*! Continue configuration even if a channel is not there. */
01345    int ignore_failed_channels;
01346 
01347    /*!
01348     * \brief The serial port to listen for SMDI data on
01349     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01350     */
01351    char smdi_port[SMDI_MAX_FILENAME_LEN];
01352 };
01353 
01354 /*! returns a new dahdi_chan_conf with default values (by-value) */
01355 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01356 {
01357    /* recall that if a field is not included here it is initialized
01358     * to 0 or equivalent
01359     */
01360    struct dahdi_chan_conf conf = {
01361 #ifdef HAVE_PRI
01362       .pri.pri = {
01363          .nsf = PRI_NSF_NONE,
01364          .switchtype = PRI_SWITCH_NI2,
01365          .dialplan = PRI_UNKNOWN + 1,
01366          .localdialplan = PRI_NATIONAL_ISDN + 1,
01367          .nodetype = PRI_CPE,
01368          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01369          .inband_on_proceeding = 1,
01370 
01371 #if defined(HAVE_PRI_CCSS)
01372          .cc_ptmp_recall_mode = 1,/* specificRecall */
01373          .cc_qsig_signaling_link_req = 1,/* retain */
01374          .cc_qsig_signaling_link_rsp = 1,/* retain */
01375 #endif   /* defined(HAVE_PRI_CCSS) */
01376 
01377          .minunused = 2,
01378          .idleext = "",
01379          .idledial = "",
01380          .internationalprefix = "",
01381          .nationalprefix = "",
01382          .localprefix = "",
01383          .privateprefix = "",
01384          .unknownprefix = "",
01385          .resetinterval = -1,
01386       },
01387 #endif
01388 #if defined(HAVE_SS7)
01389       .ss7.ss7 = {
01390          .called_nai = SS7_NAI_NATIONAL,
01391          .calling_nai = SS7_NAI_NATIONAL,
01392          .internationalprefix = "",
01393          .nationalprefix = "",
01394          .subscriberprefix = "",
01395          .unknownprefix = ""
01396       },
01397 #endif   /* defined(HAVE_SS7) */
01398 #ifdef HAVE_OPENR2
01399       .mfcr2 = {
01400          .variant = OR2_VAR_ITU,
01401          .mfback_timeout = -1,
01402          .metering_pulse_timeout = -1,
01403          .max_ani = 10,
01404          .max_dnis = 4,
01405          .get_ani_first = -1,
01406 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01407          .skip_category_request = -1,
01408 #endif
01409          .call_files = 0,
01410          .allow_collect_calls = 0,
01411          .charge_calls = 1,
01412          .accept_on_offer = 1,
01413          .forced_release = 0,
01414          .double_answer = 0,
01415          .immediate_accept = -1,
01416          .logdir = "",
01417          .r2proto_file = "",
01418          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01419          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01420       },
01421 #endif
01422       .chan = {
01423          .context = "default",
01424          .cid_num = "",
01425          .cid_name = "",
01426          .cid_tag = "",
01427          .mohinterpret = "default",
01428          .mohsuggest = "",
01429          .parkinglot = "",
01430          .transfertobusy = 1,
01431 
01432          .cid_signalling = CID_SIG_BELL,
01433          .cid_start = CID_START_RING,
01434          .dahditrcallerid = 0,
01435          .use_callerid = 1,
01436          .sig = -1,
01437          .outsigmod = -1,
01438 
01439          .cid_rxgain = +5.0,
01440 
01441          .tonezone = -1,
01442 
01443          .echocancel.head.tap_length = 1,
01444 
01445          .busycount = 3,
01446 
01447          .accountcode = "",
01448 
01449          .mailbox = "",
01450 
01451 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01452          .mwisend_fsk = 1,
01453 #endif
01454          .polarityonanswerdelay = 600,
01455 
01456          .sendcalleridafter = DEFAULT_CIDRINGS,
01457 
01458          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01459          .buf_no = numbufs,
01460          .usefaxbuffers = 0,
01461          .cc_params = ast_cc_config_params_init(),
01462       },
01463       .timing = {
01464          .prewinktime = -1,
01465          .preflashtime = -1,
01466          .winktime = -1,
01467          .flashtime = -1,
01468          .starttime = -1,
01469          .rxwinktime = -1,
01470          .rxflashtime = -1,
01471          .debouncetime = -1
01472       },
01473       .is_sig_auto = 1,
01474       .smdi_port = "/dev/ttyS0",
01475    };
01476 
01477    return conf;
01478 }
01479 
01480 
01481 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01482 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01483 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01485 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01486 static int dahdi_hangup(struct ast_channel *ast);
01487 static int dahdi_answer(struct ast_channel *ast);
01488 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01489 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01490 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01491 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01492 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01493 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01494 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01495 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01496 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01497 static int dahdi_devicestate(void *data);
01498 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01499 
01500 static const struct ast_channel_tech dahdi_tech = {
01501    .type = "DAHDI",
01502    .description = tdesc,
01503    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01504    .requester = dahdi_request,
01505    .send_digit_begin = dahdi_digit_begin,
01506    .send_digit_end = dahdi_digit_end,
01507    .send_text = dahdi_sendtext,
01508    .call = dahdi_call,
01509    .hangup = dahdi_hangup,
01510    .answer = dahdi_answer,
01511    .read = dahdi_read,
01512    .write = dahdi_write,
01513    .bridge = dahdi_bridge,
01514    .exception = dahdi_exception,
01515    .indicate = dahdi_indicate,
01516    .fixup = dahdi_fixup,
01517    .setoption = dahdi_setoption,
01518    .queryoption = dahdi_queryoption,
01519    .func_channel_read = dahdi_func_read,
01520    .func_channel_write = dahdi_func_write,
01521    .devicestate = dahdi_devicestate,
01522    .cc_callback = dahdi_cc_callback,
01523 };
01524 
01525 #define GET_CHANNEL(p) ((p)->channel)
01526 
01527 #define SIG_PRI_LIB_HANDLE_CASES \
01528    SIG_PRI:                \
01529    case SIG_BRI:              \
01530    case SIG_BRI_PTMP
01531 
01532 /*!
01533  * \internal
01534  * \brief Determine if sig_pri handles the signaling.
01535  * \since 1.8
01536  *
01537  * \param signaling Signaling to determine if is for sig_pri.
01538  *
01539  * \return TRUE if the signaling is for sig_pri.
01540  */
01541 static inline int dahdi_sig_pri_lib_handles(int signaling)
01542 {
01543    int handles;
01544 
01545    switch (signaling) {
01546    case SIG_PRI_LIB_HANDLE_CASES:
01547       handles = 1;
01548       break;
01549    default:
01550       handles = 0;
01551       break;
01552    }
01553 
01554    return handles;
01555 }
01556 
01557 static int analog_lib_handles(int signalling, int radio, int oprmode)
01558 {
01559    switch (signalling) {
01560    case SIG_FXOLS:
01561    case SIG_FXOGS:
01562    case SIG_FXOKS:
01563    case SIG_FXSLS:
01564    case SIG_FXSGS:
01565    case SIG_FXSKS:
01566    case SIG_EMWINK:
01567    case SIG_EM:
01568    case SIG_EM_E1:
01569    case SIG_FEATD:
01570    case SIG_FEATDMF:
01571    case SIG_E911:
01572    case SIG_FGC_CAMA:
01573    case SIG_FGC_CAMAMF:
01574    case SIG_FEATB:
01575    case SIG_SFWINK:
01576    case SIG_SF:
01577    case SIG_SF_FEATD:
01578    case SIG_SF_FEATDMF:
01579    case SIG_FEATDMF_TA:
01580    case SIG_SF_FEATB:
01581       break;
01582    default:
01583       /* The rest of the function should cover the remainder of signalling types */
01584       return 0;
01585    }
01586 
01587    if (radio) {
01588       return 0;
01589    }
01590 
01591    if (oprmode) {
01592       return 0;
01593    }
01594 
01595    return 1;
01596 }
01597 
01598 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01599 {
01600    switch (sig) {
01601    case SIG_FXOLS:
01602       return ANALOG_SIG_FXOLS;
01603    case SIG_FXOGS:
01604       return ANALOG_SIG_FXOGS;
01605    case SIG_FXOKS:
01606       return ANALOG_SIG_FXOKS;
01607    case SIG_FXSLS:
01608       return ANALOG_SIG_FXSLS;
01609    case SIG_FXSGS:
01610       return ANALOG_SIG_FXSGS;
01611    case SIG_FXSKS:
01612       return ANALOG_SIG_FXSKS;
01613    case SIG_EMWINK:
01614       return ANALOG_SIG_EMWINK;
01615    case SIG_EM:
01616       return ANALOG_SIG_EM;
01617    case SIG_EM_E1:
01618       return ANALOG_SIG_EM_E1;
01619    case SIG_FEATD:
01620       return ANALOG_SIG_FEATD;
01621    case SIG_FEATDMF:
01622       return ANALOG_SIG_FEATDMF;
01623    case SIG_E911:
01624       return SIG_E911;
01625    case SIG_FGC_CAMA:
01626       return ANALOG_SIG_FGC_CAMA;
01627    case SIG_FGC_CAMAMF:
01628       return ANALOG_SIG_FGC_CAMAMF;
01629    case SIG_FEATB:
01630       return ANALOG_SIG_FEATB;
01631    case SIG_SFWINK:
01632       return ANALOG_SIG_SFWINK;
01633    case SIG_SF:
01634       return ANALOG_SIG_SF;
01635    case SIG_SF_FEATD:
01636       return ANALOG_SIG_SF_FEATD;
01637    case SIG_SF_FEATDMF:
01638       return ANALOG_SIG_SF_FEATDMF;
01639    case SIG_FEATDMF_TA:
01640       return ANALOG_SIG_FEATDMF_TA;
01641    case SIG_SF_FEATB:
01642       return ANALOG_SIG_FEATB;
01643    default:
01644       return -1;
01645    }
01646 }
01647 
01648 
01649 static int analog_tone_to_dahditone(enum analog_tone tone)
01650 {
01651    switch (tone) {
01652    case ANALOG_TONE_RINGTONE:
01653       return DAHDI_TONE_RINGTONE;
01654    case ANALOG_TONE_STUTTER:
01655       return DAHDI_TONE_STUTTER;
01656    case ANALOG_TONE_CONGESTION:
01657       return DAHDI_TONE_CONGESTION;
01658    case ANALOG_TONE_DIALTONE:
01659       return DAHDI_TONE_DIALTONE;
01660    case ANALOG_TONE_DIALRECALL:
01661       return DAHDI_TONE_DIALRECALL;
01662    case ANALOG_TONE_INFO:
01663       return DAHDI_TONE_INFO;
01664    default:
01665       return -1;
01666    }
01667 }
01668 
01669 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01670 {
01671    int index;
01672 
01673    switch (analogsub) {
01674    case ANALOG_SUB_REAL:
01675       index = SUB_REAL;
01676       break;
01677    case ANALOG_SUB_CALLWAIT:
01678       index = SUB_CALLWAIT;
01679       break;
01680    case ANALOG_SUB_THREEWAY:
01681       index = SUB_THREEWAY;
01682       break;
01683    default:
01684       ast_log(LOG_ERROR, "Unidentified sub!\n");
01685       index = SUB_REAL;
01686    }
01687 
01688    return index;
01689 }
01690 
01691 static enum analog_event dahdievent_to_analogevent(int event);
01692 static int bump_gains(struct dahdi_pvt *p);
01693 static int dahdi_setlinear(int dfd, int linear);
01694 
01695 static int my_start_cid_detect(void *pvt, int cid_signalling)
01696 {
01697    struct dahdi_pvt *p = pvt;
01698    int index = SUB_REAL;
01699    p->cs = callerid_new(cid_signalling);
01700    if (!p->cs) {
01701       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01702       return -1;
01703    }
01704    bump_gains(p);
01705    dahdi_setlinear(p->subs[index].dfd, 0);
01706 
01707    return 0;
01708 }
01709 
01710 static int my_stop_cid_detect(void *pvt)
01711 {
01712    struct dahdi_pvt *p = pvt;
01713    int index = SUB_REAL;
01714    if (p->cs)
01715       callerid_free(p->cs);
01716    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01717    return 0;
01718 }
01719 
01720 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01721 {
01722    struct dahdi_pvt *p = pvt;
01723    struct analog_pvt *analog_p = p->sig_pvt;
01724    struct pollfd poller;
01725    char *name, *num;
01726    int index = SUB_REAL;
01727    int res;
01728    unsigned char buf[256];
01729    int flags;
01730 
01731    poller.fd = p->subs[SUB_REAL].dfd;
01732    poller.events = POLLPRI | POLLIN;
01733    poller.revents = 0;
01734 
01735    res = poll(&poller, 1, timeout);
01736 
01737    if (poller.revents & POLLPRI) {
01738       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01739       return 1;
01740    }
01741 
01742    if (poller.revents & POLLIN) {
01743       /*** NOTES ***/
01744       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01745        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01746        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01747        * a failure and die, and returning 2 means no event was received. */
01748       res = read(p->subs[index].dfd, buf, sizeof(buf));
01749       if (res < 0) {
01750          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01751          return -1;
01752       }
01753 
01754       if (analog_p->ringt > 0) {
01755          if (!(--analog_p->ringt)) {
01756             /* only return if we timeout from a ring event */
01757             return -1;
01758          }
01759       }
01760 
01761       if (p->cid_signalling == CID_SIG_V23_JP) {
01762          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01763       } else {
01764          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01765       }
01766       if (res < 0) {
01767          /*
01768           * The previous diagnostic message output likely
01769           * explains why it failed.
01770           */
01771          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01772          return -1;
01773       }
01774 
01775       if (res == 1) {
01776          callerid_get(p->cs, &name, &num, &flags);
01777          if (name)
01778             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01779          if (num)
01780             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01781 
01782          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01783          return 0;
01784       }
01785    }
01786 
01787    *ev = ANALOG_EVENT_NONE;
01788    return 2;
01789 }
01790 
01791 static const char *event2str(int event);
01792 static int restore_gains(struct dahdi_pvt *p);
01793 
01794 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01795 {
01796    unsigned char buf[256];
01797    int distMatches;
01798    int curRingData[RING_PATTERNS];
01799    int receivedRingT;
01800    int counter1;
01801    int counter;
01802    int i;
01803    int res;
01804    int checkaftercid = 0;
01805 
01806    struct dahdi_pvt *p = pvt;
01807    struct analog_pvt *analog_p = p->sig_pvt;
01808 
01809    if (ringdata == NULL) {
01810       ringdata = curRingData;
01811    } else {
01812       checkaftercid = 1;
01813    }
01814 
01815    /* We must have a ring by now, so, if configured, lets try to listen for
01816     * distinctive ringing */
01817    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01818       /* Clear the current ring data array so we don't have old data in it. */
01819       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01820          ringdata[receivedRingT] = 0;
01821       receivedRingT = 0;
01822       if (checkaftercid && distinctiveringaftercid)
01823          ast_verb(3, "Detecting post-CID distinctive ring\n");
01824       /* Check to see if context is what it should be, if not set to be. */
01825       else if (strcmp(p->context,p->defcontext) != 0) {
01826          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01827          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01828       }
01829 
01830       for (;;) {
01831          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01832          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01833             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01834             ast_hangup(chan);
01835             return 1;
01836          }
01837          if (i & DAHDI_IOMUX_SIGEVENT) {
01838             res = dahdi_get_event(p->subs[idx].dfd);
01839             if (res == DAHDI_EVENT_NOALARM) {
01840                p->inalarm = 0;
01841                analog_p->inalarm = 0;
01842             }
01843             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01844             res = 0;
01845             /* Let us detect distinctive ring */
01846 
01847             ringdata[receivedRingT] = analog_p->ringt;
01848 
01849             if (analog_p->ringt < analog_p->ringt_base/2)
01850                break;
01851             /* Increment the ringT counter so we can match it against
01852                values in chan_dahdi.conf for distinctive ring */
01853             if (++receivedRingT == RING_PATTERNS)
01854                break;
01855          } else if (i & DAHDI_IOMUX_READ) {
01856             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01857             if (res < 0) {
01858                if (errno != ELAST) {
01859                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01860                   ast_hangup(chan);
01861                   return 1;
01862                }
01863                break;
01864             }
01865             if (analog_p->ringt > 0) {
01866                if (!(--analog_p->ringt)) {
01867                   res = -1;
01868                   break;
01869                }
01870             }
01871          }
01872       }
01873    }
01874    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01875       /* this only shows up if you have n of the dring patterns filled in */
01876       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01877       for (counter = 0; counter < 3; counter++) {
01878       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01879          distMatches = 0;
01880          /* this only shows up if you have n of the dring patterns filled in */
01881          ast_verb(3, "Checking %d,%d,%d\n",
01882                p->drings.ringnum[counter].ring[0],
01883                p->drings.ringnum[counter].ring[1],
01884                p->drings.ringnum[counter].ring[2]);
01885          for (counter1 = 0; counter1 < 3; counter1++) {
01886             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01887             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01888                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01889                ringdata[counter1]);
01890                distMatches++;
01891             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01892                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01893                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01894                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01895                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01896                distMatches++;
01897             }
01898          }
01899 
01900          if (distMatches == 3) {
01901             /* The ring matches, set the context to whatever is for distinctive ring.. */
01902             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01903             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01904             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01905             break;
01906          }
01907       }
01908    }
01909    /* Restore linear mode (if appropriate) for Caller*ID processing */
01910    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01911    restore_gains(p);
01912 
01913    return 0;
01914 }
01915 
01916 static int my_stop_callwait(void *pvt)
01917 {
01918    struct dahdi_pvt *p = pvt;
01919    p->callwaitingrepeat = 0;
01920    p->cidcwexpire = 0;
01921    p->cid_suppress_expire = 0;
01922 
01923    return 0;
01924 }
01925 
01926 static int send_callerid(struct dahdi_pvt *p);
01927 static int save_conference(struct dahdi_pvt *p);
01928 static int restore_conference(struct dahdi_pvt *p);
01929 
01930 static int my_callwait(void *pvt)
01931 {
01932    struct dahdi_pvt *p = pvt;
01933    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01934    if (p->cidspill) {
01935       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01936       ast_free(p->cidspill);
01937    }
01938 
01939    /*
01940     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01941     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01942     */
01943    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01944       return -1;
01945    save_conference(p);
01946    /* Silence */
01947    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01948    if (!p->callwaitrings && p->callwaitingcallerid) {
01949       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01950       p->callwaitcas = 1;
01951       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01952    } else {
01953       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01954       p->callwaitcas = 0;
01955       p->cidlen = 2400 + READ_SIZE * 4;
01956    }
01957    p->cidpos = 0;
01958    send_callerid(p);
01959 
01960    return 0;
01961 }
01962 
01963 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01964 {
01965    struct dahdi_pvt *p = pvt;
01966 
01967    ast_debug(2, "Starting cid spill\n");
01968 
01969    if (p->cidspill) {
01970       ast_log(LOG_WARNING, "cidspill already exists??\n");
01971       ast_free(p->cidspill);
01972    }
01973 
01974    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01975       if (cwcid == 0) {
01976          p->cidlen = ast_callerid_generate(p->cidspill,
01977             caller->id.name.str,
01978             caller->id.number.str,
01979             AST_LAW(p));
01980       } else {
01981          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01982             caller->id.name.str, caller->id.number.str);
01983          p->callwaitcas = 0;
01984          p->cidcwexpire = 0;
01985          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01986             caller->id.name.str,
01987             caller->id.number.str,
01988             AST_LAW(p));
01989          p->cidlen += READ_SIZE * 4;
01990       }
01991       p->cidpos = 0;
01992       p->cid_suppress_expire = 0;
01993       send_callerid(p);
01994    }
01995    return 0;
01996 }
01997 
01998 static int my_dsp_reset_and_flush_digits(void *pvt)
01999 {
02000    struct dahdi_pvt *p = pvt;
02001    if (p->dsp)
02002       ast_dsp_digitreset(p->dsp);
02003 
02004    return 0;
02005 }
02006 
02007 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02008 {
02009    struct dahdi_pvt *p = pvt;
02010 
02011    if (p->channel == CHAN_PSEUDO)
02012       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02013 
02014    if (mode == ANALOG_DIGITMODE_DTMF) {
02015       /* If we do hardware dtmf, no need for a DSP */
02016       if (p->hardwaredtmf) {
02017          if (p->dsp) {
02018             ast_dsp_free(p->dsp);
02019             p->dsp = NULL;
02020          }
02021          return 0;
02022       }
02023 
02024       if (!p->dsp) {
02025          p->dsp = ast_dsp_new();
02026          if (!p->dsp) {
02027             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02028             return -1;
02029          }
02030       }
02031 
02032       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02033    } else if (mode == ANALOG_DIGITMODE_MF) {
02034       if (!p->dsp) {
02035          p->dsp = ast_dsp_new();
02036          if (!p->dsp) {
02037             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02038             return -1;
02039          }
02040       }
02041       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02042    }
02043    return 0;
02044 }
02045 
02046 static int dahdi_wink(struct dahdi_pvt *p, int index);
02047 
02048 static int my_wink(void *pvt, enum analog_sub sub)
02049 {
02050    struct dahdi_pvt *p = pvt;
02051    int index = analogsub_to_dahdisub(sub);
02052    if (index != SUB_REAL) {
02053       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02054    }
02055    return dahdi_wink(p, index);
02056 }
02057 
02058 static void wakeup_sub(struct dahdi_pvt *p, int a);
02059 
02060 static int reset_conf(struct dahdi_pvt *p);
02061 
02062 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02063 
02064 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02065 {
02066    struct ast_frame *f = *dest;
02067    struct dahdi_pvt *p = pvt;
02068    int idx = analogsub_to_dahdisub(analog_index);
02069 
02070    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02071       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02072       f->subclass.integer, f->subclass.integer, ast->name);
02073 
02074    if (f->subclass.integer == 'f') {
02075       if (f->frametype == AST_FRAME_DTMF_END) {
02076          /* Fax tone -- Handle and return NULL */
02077          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02078             /* If faxbuffers are configured, use them for the fax transmission */
02079             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02080                struct dahdi_bufferinfo bi = {
02081                   .txbufpolicy = p->faxbuf_policy,
02082                   .bufsize = p->bufsize,
02083                   .numbufs = p->faxbuf_no
02084                };
02085                int res;
02086 
02087                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02088                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02089                } else {
02090                   p->bufferoverrideinuse = 1;
02091                }
02092             }
02093             p->faxhandled = 1;
02094             if (p->dsp) {
02095                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02096                ast_dsp_set_features(p->dsp, p->dsp_features);
02097                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02098             }
02099             if (strcmp(ast->exten, "fax")) {
02100                const char *target_context = S_OR(ast->macrocontext, ast->context);
02101 
02102                /* We need to unlock 'ast' here because ast_exists_extension has the
02103                 * potential to start autoservice on the channel. Such action is prone
02104                 * to deadlock.
02105                 */
02106                ast_mutex_unlock(&p->lock);
02107                ast_channel_unlock(ast);
02108                if (ast_exists_extension(ast, target_context, "fax", 1,
02109                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02110                   ast_channel_lock(ast);
02111                   ast_mutex_lock(&p->lock);
02112                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02113                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02114                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02115                   if (ast_async_goto(ast, target_context, "fax", 1))
02116                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02117                } else {
02118                   ast_channel_lock(ast);
02119                   ast_mutex_lock(&p->lock);
02120                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02121                }
02122             } else {
02123                ast_debug(1, "Already in a fax extension, not redirecting\n");
02124             }
02125          } else {
02126             ast_debug(1, "Fax already handled\n");
02127          }
02128          dahdi_confmute(p, 0);
02129       }
02130       p->subs[idx].f.frametype = AST_FRAME_NULL;
02131       p->subs[idx].f.subclass.integer = 0;
02132       *dest = &p->subs[idx].f;
02133    }
02134 }
02135 
02136 static void my_lock_private(void *pvt)
02137 {
02138    struct dahdi_pvt *p = pvt;
02139    ast_mutex_lock(&p->lock);
02140 }
02141 
02142 static void my_unlock_private(void *pvt)
02143 {
02144    struct dahdi_pvt *p = pvt;
02145    ast_mutex_unlock(&p->lock);
02146 }
02147 
02148 static void my_deadlock_avoidance_private(void *pvt)
02149 {
02150    struct dahdi_pvt *p = pvt;
02151 
02152    DEADLOCK_AVOIDANCE(&p->lock);
02153 }
02154 
02155 /*!
02156  * \internal
02157  * \brief Post an AMI DAHDI channel association event.
02158  * \since 1.8
02159  *
02160  * \param p DAHDI private pointer
02161  * \param chan Channel associated with the private pointer
02162  *
02163  * \return Nothing
02164  */
02165 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02166 {
02167    char ch_name[20];
02168 
02169    if (p->channel < CHAN_PSEUDO) {
02170       /* No B channel */
02171       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02172    } else if (p->channel == CHAN_PSEUDO) {
02173       /* Pseudo channel */
02174       strcpy(ch_name, "pseudo");
02175    } else {
02176       /* Real channel */
02177       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02178    }
02179    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02180       "Channel: %s\r\n"
02181       "Uniqueid: %s\r\n"
02182       "DAHDISpan: %d\r\n"
02183       "DAHDIChannel: %s\r\n",
02184       chan->name,
02185       chan->uniqueid,
02186       p->span,
02187       ch_name);
02188 }
02189 
02190 #ifdef HAVE_PRI
02191 /*!
02192  * \internal
02193  * \brief Post an AMI DAHDI channel association event.
02194  * \since 1.8
02195  *
02196  * \param pvt DAHDI private pointer
02197  * \param chan Channel associated with the private pointer
02198  *
02199  * \return Nothing
02200  */
02201 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02202 {
02203    struct dahdi_pvt *p = pvt;
02204 
02205    dahdi_ami_channel_event(p, chan);
02206 }
02207 #endif
02208 
02209 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02210 *  returns the last value of the linear setting 
02211 */ 
02212 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02213 {
02214    struct dahdi_pvt *p = pvt;
02215    int oldval;
02216    int idx = analogsub_to_dahdisub(sub);
02217    
02218    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02219    oldval = p->subs[idx].linear;
02220    p->subs[idx].linear = linear_mode ? 1 : 0;
02221    return oldval;
02222 }
02223 
02224 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02225 {
02226    struct dahdi_pvt *p = pvt;
02227    int idx = analogsub_to_dahdisub(sub);
02228 
02229    p->subs[idx].inthreeway = inthreeway;
02230 }
02231 
02232 static int get_alarms(struct dahdi_pvt *p);
02233 static void handle_alarms(struct dahdi_pvt *p, int alms);
02234 static void my_get_and_handle_alarms(void *pvt)
02235 {
02236    int res;
02237    struct dahdi_pvt *p = pvt;
02238 
02239    res = get_alarms(p);
02240    handle_alarms(p, res);
02241 }
02242 
02243 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02244 {
02245    struct ast_channel *bridged = ast_bridged_channel(chan);
02246 
02247    if (bridged && bridged->tech == &dahdi_tech) {
02248       struct dahdi_pvt *p = bridged->tech_pvt;
02249 
02250       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02251          return p->sig_pvt;
02252       }
02253    }
02254    return NULL;
02255 }
02256 
02257 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02258 {
02259    struct dahdi_pvt *p = pvt;
02260    int dahdi_sub = analogsub_to_dahdisub(sub);
02261    return p->subs[dahdi_sub].dfd;
02262 }
02263 
02264 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02265 {
02266    struct dahdi_pvt *p = pvt;
02267 
02268    /* Choose proper cadence */
02269    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02270       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02271          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02272       *cid_rings = cidrings[p->distinctivering - 1];
02273    } else {
02274       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02275          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02276       *cid_rings = p->sendcalleridafter;
02277    }
02278 }
02279 
02280 static void my_set_alarm(void *pvt, int in_alarm)
02281 {
02282    struct dahdi_pvt *p = pvt;
02283 
02284    p->inalarm = in_alarm;
02285 }
02286 
02287 static void my_set_dialing(void *pvt, int is_dialing)
02288 {
02289    struct dahdi_pvt *p = pvt;
02290 
02291    p->dialing = is_dialing;
02292 }
02293 
02294 static void my_set_outgoing(void *pvt, int is_outgoing)
02295 {
02296    struct dahdi_pvt *p = pvt;
02297 
02298    p->outgoing = is_outgoing;
02299 }
02300 
02301 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02302 static void my_set_digital(void *pvt, int is_digital)
02303 {
02304    struct dahdi_pvt *p = pvt;
02305 
02306    p->digital = is_digital;
02307 }
02308 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02309 
02310 #if defined(HAVE_SS7)
02311 static void my_set_inservice(void *pvt, int is_inservice)
02312 {
02313    struct dahdi_pvt *p = pvt;
02314 
02315    p->inservice = is_inservice;
02316 }
02317 #endif   /* defined(HAVE_SS7) */
02318 
02319 #if defined(HAVE_SS7)
02320 static void my_set_locallyblocked(void *pvt, int is_blocked)
02321 {
02322    struct dahdi_pvt *p = pvt;
02323 
02324    p->locallyblocked = is_blocked;
02325 }
02326 #endif   /* defined(HAVE_SS7) */
02327 
02328 #if defined(HAVE_SS7)
02329 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02330 {
02331    struct dahdi_pvt *p = pvt;
02332 
02333    p->remotelyblocked = is_blocked;
02334 }
02335 #endif   /* defined(HAVE_SS7) */
02336 
02337 static void my_set_ringtimeout(void *pvt, int ringt)
02338 {
02339    struct dahdi_pvt *p = pvt;
02340    p->ringt = ringt;
02341 }
02342 
02343 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02344 {
02345    struct dahdi_pvt *p = pvt;
02346 
02347    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02348       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02349       gettimeofday(&p->waitingfordt, NULL);
02350       ast_setstate(ast, AST_STATE_OFFHOOK);
02351    }
02352 }
02353 
02354 static int my_check_waitingfordt(void *pvt)
02355 {
02356    struct dahdi_pvt *p = pvt;
02357 
02358    if (p->waitingfordt.tv_usec) {
02359       return 1;
02360    }
02361 
02362    return 0;
02363 }
02364 
02365 static void my_set_confirmanswer(void *pvt, int flag)
02366 {
02367    struct dahdi_pvt *p = pvt;
02368    p->confirmanswer = flag;
02369 }
02370 
02371 static int my_check_confirmanswer(void *pvt)
02372 {
02373    struct dahdi_pvt *p = pvt;
02374    if (p->confirmanswer) {
02375       return 1;
02376    }
02377 
02378    return 0;
02379 }
02380 
02381 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02382 {
02383    struct dahdi_pvt *p = pvt;
02384 
02385    p->callwaiting = callwaiting_enable;
02386 }
02387 
02388 static void my_cancel_cidspill(void *pvt)
02389 {
02390    struct dahdi_pvt *p = pvt;
02391 
02392    ast_free(p->cidspill);
02393    p->cidspill = NULL;
02394    restore_conference(p);
02395 }
02396 
02397 static int my_confmute(void *pvt, int mute)
02398 {
02399    struct dahdi_pvt *p = pvt;
02400    return dahdi_confmute(p, mute);
02401 }
02402 
02403 static void my_set_pulsedial(void *pvt, int flag)
02404 {
02405    struct dahdi_pvt *p = pvt;
02406    p->pulsedial = flag;
02407 }
02408 
02409 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    p->owner = new_owner;
02414 }
02415 
02416 static const char *my_get_orig_dialstring(void *pvt)
02417 {
02418    struct dahdi_pvt *p = pvt;
02419 
02420    return p->dialstring;
02421 }
02422 
02423 static void my_increase_ss_count(void)
02424 {
02425    ast_mutex_lock(&ss_thread_lock);
02426    ss_thread_count++;
02427    ast_mutex_unlock(&ss_thread_lock);
02428 }
02429 
02430 static void my_decrease_ss_count(void)
02431 {
02432    ast_mutex_lock(&ss_thread_lock);
02433    ss_thread_count--;
02434    ast_cond_signal(&ss_thread_complete);
02435    ast_mutex_unlock(&ss_thread_lock);
02436 }
02437 
02438 static void my_all_subchannels_hungup(void *pvt)
02439 {
02440    struct dahdi_pvt *p = pvt;
02441    int res, law;
02442 
02443    p->faxhandled = 0;
02444    p->didtdd = 0;
02445 
02446    if (p->dsp) {
02447       ast_dsp_free(p->dsp);
02448       p->dsp = NULL;
02449    }
02450 
02451    p->law = p->law_default;
02452    law = p->law_default;
02453    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02454    if (res < 0)
02455       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02456 
02457    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02458 
02459 #if 1
02460    {
02461    int i;
02462    p->owner = NULL;
02463    /* Cleanup owners here */
02464    for (i = 0; i < 3; i++) {
02465       p->subs[i].owner = NULL;
02466    }
02467    }
02468 #endif
02469 
02470    reset_conf(p);
02471    if (num_restart_pending == 0) {
02472       restart_monitor();
02473    }
02474 }
02475 
02476 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02477 
02478 static int my_conf_del(void *pvt, enum analog_sub sub)
02479 {
02480    struct dahdi_pvt *p = pvt;
02481    int x = analogsub_to_dahdisub(sub);
02482 
02483    return conf_del(p, &p->subs[x], x);
02484 }
02485 
02486 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02487 
02488 static int my_conf_add(void *pvt, enum analog_sub sub)
02489 {
02490    struct dahdi_pvt *p = pvt;
02491    int x = analogsub_to_dahdisub(sub);
02492 
02493    return conf_add(p, &p->subs[x], x, 0);
02494 }
02495 
02496 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02497 
02498 static int my_complete_conference_update(void *pvt, int needconference)
02499 {
02500    struct dahdi_pvt *p = pvt;
02501    int needconf = needconference;
02502    int x;
02503    int useslavenative;
02504    struct dahdi_pvt *slave = NULL;
02505 
02506    useslavenative = isslavenative(p, &slave);
02507 
02508    /* If we have a slave, add him to our conference now. or DAX
02509       if this is slave native */
02510    for (x = 0; x < MAX_SLAVES; x++) {
02511       if (p->slaves[x]) {
02512          if (useslavenative)
02513             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02514          else {
02515             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02516             needconf++;
02517          }
02518       }
02519    }
02520    /* If we're supposed to be in there, do so now */
02521    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02522       if (useslavenative)
02523          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02524       else {
02525          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02526          needconf++;
02527       }
02528    }
02529    /* If we have a master, add ourselves to his conference */
02530    if (p->master) {
02531       if (isslavenative(p->master, NULL)) {
02532          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02533       } else {
02534          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02535       }
02536    }
02537    if (!needconf) {
02538       /* Nobody is left (or should be left) in our conference.
02539          Kill it. */
02540       p->confno = -1;
02541    }
02542 
02543    return 0;
02544 }
02545 
02546 static int check_for_conference(struct dahdi_pvt *p);
02547 
02548 static int my_check_for_conference(void *pvt)
02549 {
02550    struct dahdi_pvt *p = pvt;
02551    return check_for_conference(p);
02552 }
02553 
02554 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)
02555 {
02556    struct dahdi_pvt *p = pvt;
02557    int da, db;
02558    int tchan;
02559    int tinthreeway;
02560 
02561    da = analogsub_to_dahdisub(a);
02562    db = analogsub_to_dahdisub(b);
02563 
02564    tchan = p->subs[da].chan;
02565    p->subs[da].chan = p->subs[db].chan;
02566    p->subs[db].chan = tchan;
02567 
02568    tinthreeway = p->subs[da].inthreeway;
02569    p->subs[da].inthreeway = p->subs[db].inthreeway;
02570    p->subs[db].inthreeway = tinthreeway;
02571 
02572    p->subs[da].owner = ast_a;
02573    p->subs[db].owner = ast_b;
02574 
02575    if (ast_a)
02576       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02577    if (ast_b)
02578       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02579 
02580    wakeup_sub(p, a);
02581    wakeup_sub(p, b);
02582 
02583    return;
02584 }
02585 
02586 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02587 
02588 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02589 {
02590    struct dahdi_pvt *p = pvt;
02591    int dsub = analogsub_to_dahdisub(sub);
02592 
02593    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02594 }
02595 
02596 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02597 static int dahdi_setlaw(int dfd, int law)
02598 {
02599    int res;
02600    res = ioctl(dfd, DAHDI_SETLAW, &law);
02601    if (res)
02602       return res;
02603    return 0;
02604 }
02605 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02606 
02607 #if defined(HAVE_PRI)
02608 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)
02609 {
02610    struct dahdi_pvt *p = pvt;
02611    int audio;
02612    int newlaw = -1;
02613 
02614    switch (p->sig) {
02615    case SIG_PRI_LIB_HANDLE_CASES:
02616       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02617          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02618          break;
02619       }
02620       /* Fall through */
02621    default:
02622       /* Set to audio mode at this point */
02623       audio = 1;
02624       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02625          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02626             p->channel, audio, strerror(errno));
02627       }
02628       break;
02629    }
02630 
02631    if (law != SIG_PRI_DEFLAW) {
02632       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02633    }
02634 
02635    ast_copy_string(p->exten, exten, sizeof(p->exten));
02636 
02637    switch (law) {
02638       case SIG_PRI_DEFLAW:
02639          newlaw = 0;
02640          break;
02641       case SIG_PRI_ALAW:
02642          newlaw = DAHDI_LAW_ALAW;
02643          break;
02644       case SIG_PRI_ULAW:
02645          newlaw = DAHDI_LAW_MULAW;
02646          break;
02647    }
02648    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02649 }
02650 #endif   /* defined(HAVE_PRI) */
02651 
02652 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02653 
02654 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02655 /*!
02656  * \internal
02657  * \brief Open the PRI/SS7 channel media path.
02658  * \since 1.8
02659  *
02660  * \param p Channel private control structure.
02661  *
02662  * \return Nothing
02663  */
02664 static void my_pri_ss7_open_media(void *p)
02665 {
02666    struct dahdi_pvt *pvt = p;
02667    int res;
02668    int dfd;
02669    int set_val;
02670 
02671    dfd = pvt->subs[SUB_REAL].dfd;
02672 
02673    /* Open the media path. */
02674    set_val = 1;
02675    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02676    if (res < 0) {
02677       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02678          pvt->channel, strerror(errno));
02679    }
02680 
02681    /* Set correct companding law for this call. */
02682    res = dahdi_setlaw(dfd, pvt->law);
02683    if (res < 0) {
02684       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02685    }
02686 
02687    /* Set correct gain for this call. */
02688    if (pvt->digital) {
02689       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02690    } else {
02691       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02692          pvt->law);
02693    }
02694    if (res < 0) {
02695       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02696    }
02697 
02698    if (pvt->dsp_features && pvt->dsp) {
02699       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02700       pvt->dsp_features = 0;
02701    }
02702 }
02703 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02704 
02705 #if defined(HAVE_PRI)
02706 /*!
02707  * \internal
02708  * \brief Ask DAHDI to dial the given dial string.
02709  * \since 1.8.11
02710  *
02711  * \param p Channel private control structure.
02712  * \param dial_string String to pass to DAHDI to dial.
02713  *
02714  * \note The channel private lock needs to be held when calling.
02715  *
02716  * \return Nothing
02717  */
02718 static void my_pri_dial_digits(void *p, const char *dial_string)
02719 {
02720    struct dahdi_dialoperation zo = {
02721       .op = DAHDI_DIAL_OP_APPEND,
02722    };
02723    struct dahdi_pvt *pvt = p;
02724    int res;
02725 
02726    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02727    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02728    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02729    if (res) {
02730       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02731          pvt->channel, dial_string, strerror(errno));
02732    } else {
02733       pvt->dialing = 1;
02734    }
02735 }
02736 #endif   /* defined(HAVE_PRI) */
02737 
02738 static int unalloc_sub(struct dahdi_pvt *p, int x);
02739 
02740 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02741 {
02742    struct dahdi_pvt *p = pvt;
02743 
02744    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02745 }
02746 
02747 static int alloc_sub(struct dahdi_pvt *p, int x);
02748 
02749 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02750 {
02751    struct dahdi_pvt *p = pvt;
02752 
02753    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02754 }
02755 
02756 static int has_voicemail(struct dahdi_pvt *p);
02757 
02758 static int my_has_voicemail(void *pvt)
02759 {
02760    struct dahdi_pvt *p = pvt;
02761 
02762    return has_voicemail(p);
02763 }
02764 
02765 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02766 {
02767    struct dahdi_pvt *p = pvt;
02768    int index;
02769 
02770    index = analogsub_to_dahdisub(sub);
02771 
02772    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02773 }
02774 
02775 static enum analog_event dahdievent_to_analogevent(int event)
02776 {
02777    enum analog_event res;
02778 
02779    switch (event) {
02780    case DAHDI_EVENT_ONHOOK:
02781       res = ANALOG_EVENT_ONHOOK;
02782       break;
02783    case DAHDI_EVENT_RINGOFFHOOK:
02784       res = ANALOG_EVENT_RINGOFFHOOK;
02785       break;
02786    case DAHDI_EVENT_WINKFLASH:
02787       res = ANALOG_EVENT_WINKFLASH;
02788       break;
02789    case DAHDI_EVENT_ALARM:
02790       res = ANALOG_EVENT_ALARM;
02791       break;
02792    case DAHDI_EVENT_NOALARM:
02793       res = ANALOG_EVENT_NOALARM;
02794       break;
02795    case DAHDI_EVENT_DIALCOMPLETE:
02796       res = ANALOG_EVENT_DIALCOMPLETE;
02797       break;
02798    case DAHDI_EVENT_RINGERON:
02799       res = ANALOG_EVENT_RINGERON;
02800       break;
02801    case DAHDI_EVENT_RINGEROFF:
02802       res = ANALOG_EVENT_RINGEROFF;
02803       break;
02804    case DAHDI_EVENT_HOOKCOMPLETE:
02805       res = ANALOG_EVENT_HOOKCOMPLETE;
02806       break;
02807    case DAHDI_EVENT_PULSE_START:
02808       res = ANALOG_EVENT_PULSE_START;
02809       break;
02810    case DAHDI_EVENT_POLARITY:
02811       res = ANALOG_EVENT_POLARITY;
02812       break;
02813    case DAHDI_EVENT_RINGBEGIN:
02814       res = ANALOG_EVENT_RINGBEGIN;
02815       break;
02816    case DAHDI_EVENT_EC_DISABLED:
02817       res = ANALOG_EVENT_EC_DISABLED;
02818       break;
02819    case DAHDI_EVENT_REMOVED:
02820       res = ANALOG_EVENT_REMOVED;
02821       break;
02822    case DAHDI_EVENT_NEONMWI_ACTIVE:
02823       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02824       break;
02825    case DAHDI_EVENT_NEONMWI_INACTIVE:
02826       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02827       break;
02828 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02829    case DAHDI_EVENT_TX_CED_DETECTED:
02830       res = ANALOG_EVENT_TX_CED_DETECTED;
02831       break;
02832    case DAHDI_EVENT_RX_CED_DETECTED:
02833       res = ANALOG_EVENT_RX_CED_DETECTED;
02834       break;
02835    case DAHDI_EVENT_EC_NLP_DISABLED:
02836       res = ANALOG_EVENT_EC_NLP_DISABLED;
02837       break;
02838    case DAHDI_EVENT_EC_NLP_ENABLED:
02839       res = ANALOG_EVENT_EC_NLP_ENABLED;
02840       break;
02841 #endif
02842    case DAHDI_EVENT_PULSEDIGIT:
02843       res = ANALOG_EVENT_PULSEDIGIT;
02844       break;
02845    case DAHDI_EVENT_DTMFDOWN:
02846       res = ANALOG_EVENT_DTMFDOWN;
02847       break;
02848    case DAHDI_EVENT_DTMFUP:
02849       res = ANALOG_EVENT_DTMFUP;
02850       break;
02851    default:
02852       switch(event & 0xFFFF0000) {
02853       case DAHDI_EVENT_PULSEDIGIT:
02854       case DAHDI_EVENT_DTMFDOWN:
02855       case DAHDI_EVENT_DTMFUP:
02856          /* The event includes a digit number in the low word.
02857           * Converting it to a 'enum analog_event' would remove
02858           * that information. Thus it is returned as-is.
02859           */
02860          return event;
02861       }
02862 
02863       res = ANALOG_EVENT_ERROR;
02864       break;
02865    }
02866 
02867    return res;
02868 }
02869 
02870 static inline int dahdi_wait_event(int fd);
02871 
02872 static int my_wait_event(void *pvt)
02873 {
02874    struct dahdi_pvt *p = pvt;
02875 
02876    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02877 }
02878 
02879 static int my_get_event(void *pvt)
02880 {
02881    struct dahdi_pvt *p = pvt;
02882    int res;
02883 
02884    if (p->fake_event) {
02885       res = p->fake_event;
02886       p->fake_event = 0;
02887    } else
02888       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02889 
02890    return dahdievent_to_analogevent(res);
02891 }
02892 
02893 static int my_is_off_hook(void *pvt)
02894 {
02895    struct dahdi_pvt *p = pvt;
02896    int res;
02897    struct dahdi_params par;
02898 
02899    memset(&par, 0, sizeof(par));
02900 
02901    if (p->subs[SUB_REAL].dfd > -1)
02902       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02903    else {
02904       /* Assume not off hook on CVRS */
02905       res = 0;
02906       par.rxisoffhook = 0;
02907    }
02908    if (res) {
02909       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02910    }
02911 
02912    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02913       /* When "onhook" that means no battery on the line, and thus
02914       it is out of service..., if it's on a TDM card... If it's a channel
02915       bank, there is no telling... */
02916       return (par.rxbits > -1) || par.rxisoffhook;
02917    }
02918 
02919    return par.rxisoffhook;
02920 }
02921 
02922 static void dahdi_enable_ec(struct dahdi_pvt *p);
02923 static void dahdi_disable_ec(struct dahdi_pvt *p);
02924 
02925 static int my_set_echocanceller(void *pvt, int enable)
02926 {
02927    struct dahdi_pvt *p = pvt;
02928 
02929    if (enable)
02930       dahdi_enable_ec(p);
02931    else
02932       dahdi_disable_ec(p);
02933 
02934    return 0;
02935 }
02936 
02937 static int dahdi_ring_phone(struct dahdi_pvt *p);
02938 
02939 static int my_ring(void *pvt)
02940 {
02941    struct dahdi_pvt *p = pvt;
02942 
02943    return dahdi_ring_phone(p);
02944 }
02945 
02946 static int my_flash(void *pvt)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949    int func = DAHDI_FLASH;
02950    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02951 }
02952 
02953 static inline int dahdi_set_hook(int fd, int hs);
02954 
02955 static int my_off_hook(void *pvt)
02956 {
02957    struct dahdi_pvt *p = pvt;
02958    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02959 }
02960 
02961 static void my_set_needringing(void *pvt, int value)
02962 {
02963    struct dahdi_pvt *p = pvt;
02964    p->subs[SUB_REAL].needringing = value;
02965 }
02966 
02967 static void my_set_polarity(void *pvt, int value)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970 
02971    if (p->channel == CHAN_PSEUDO) {
02972       return;
02973    }
02974    p->polarity = value;
02975    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02976 }
02977 
02978 static void my_start_polarityswitch(void *pvt)
02979 {
02980    struct dahdi_pvt *p = pvt;
02981 
02982    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02983       my_set_polarity(pvt, 0);
02984    }
02985 }
02986 
02987 static void my_answer_polarityswitch(void *pvt)
02988 {
02989    struct dahdi_pvt *p = pvt;
02990 
02991    if (!p->answeronpolarityswitch) {
02992       return;
02993    }
02994 
02995    my_set_polarity(pvt, 1);
02996 }
02997 
02998 static void my_hangup_polarityswitch(void *pvt)
02999 {
03000    struct dahdi_pvt *p = pvt;
03001 
03002    if (!p->hanguponpolarityswitch) {
03003       return;
03004    }
03005 
03006    if (p->answeronpolarityswitch) {
03007       my_set_polarity(pvt, 0);
03008    } else {
03009       my_set_polarity(pvt, 1);
03010    }
03011 }
03012 
03013 static int my_start(void *pvt)
03014 {
03015    struct dahdi_pvt *p = pvt;
03016    int x = DAHDI_START;
03017 
03018    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03019 }
03020 
03021 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03022 {
03023    int index = analogsub_to_dahdisub(sub);
03024    int res;
03025    struct dahdi_pvt *p = pvt;
03026    struct dahdi_dialoperation ddop;
03027 
03028    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03029       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03030       return -1;
03031    }
03032 
03033    if (sub != ANALOG_SUB_REAL) {
03034       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03035          dop->dialstr, p->channel, sub);
03036       return -1;
03037    }
03038 
03039    ddop.op = DAHDI_DIAL_OP_REPLACE;
03040    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03041 
03042    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03043 
03044    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03045    if (res == -1) {
03046       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03047    }
03048 
03049    return res;
03050 }
03051 
03052 static void dahdi_train_ec(struct dahdi_pvt *p);
03053 
03054 static int my_train_echocanceller(void *pvt)
03055 {
03056    struct dahdi_pvt *p = pvt;
03057 
03058    dahdi_train_ec(p);
03059 
03060    return 0;
03061 }
03062 
03063 static int my_is_dialing(void *pvt, enum analog_sub sub)
03064 {
03065    struct dahdi_pvt *p = pvt;
03066    int index;
03067    int x;
03068 
03069    index = analogsub_to_dahdisub(sub);
03070 
03071    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03072       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03073       return -1;
03074    }
03075 
03076    return x;
03077 }
03078 
03079 static int my_on_hook(void *pvt)
03080 {
03081    struct dahdi_pvt *p = pvt;
03082    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03083 }
03084 
03085 #if defined(HAVE_PRI)
03086 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03087 {
03088    struct dahdi_pvt *old_chan = chan_old;
03089    struct dahdi_pvt *new_chan = chan_new;
03090 
03091    new_chan->owner = old_chan->owner;
03092    old_chan->owner = NULL;
03093    if (new_chan->owner) {
03094       new_chan->owner->tech_pvt = new_chan;
03095       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03096       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03097       old_chan->subs[SUB_REAL].owner = NULL;
03098    }
03099    /* Copy any DSP that may be present */
03100    new_chan->dsp = old_chan->dsp;
03101    new_chan->dsp_features = old_chan->dsp_features;
03102    old_chan->dsp = NULL;
03103    old_chan->dsp_features = 0;
03104 
03105    /* Transfer flags from the old channel. */
03106    new_chan->dialing = old_chan->dialing;
03107    new_chan->digital = old_chan->digital;
03108    new_chan->outgoing = old_chan->outgoing;
03109    old_chan->dialing = 0;
03110    old_chan->digital = 0;
03111    old_chan->outgoing = 0;
03112 
03113    /* More stuff to transfer to the new channel. */
03114    new_chan->law = old_chan->law;
03115    strcpy(new_chan->dialstring, old_chan->dialstring);
03116 }
03117 #endif   /* defined(HAVE_PRI) */
03118 
03119 #if defined(HAVE_PRI)
03120 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03121 {
03122    switch (tone) {
03123    case SIG_PRI_TONE_RINGTONE:
03124       return DAHDI_TONE_RINGTONE;
03125    case SIG_PRI_TONE_STUTTER:
03126       return DAHDI_TONE_STUTTER;
03127    case SIG_PRI_TONE_CONGESTION:
03128       return DAHDI_TONE_CONGESTION;
03129    case SIG_PRI_TONE_DIALTONE:
03130       return DAHDI_TONE_DIALTONE;
03131    case SIG_PRI_TONE_DIALRECALL:
03132       return DAHDI_TONE_DIALRECALL;
03133    case SIG_PRI_TONE_INFO:
03134       return DAHDI_TONE_INFO;
03135    case SIG_PRI_TONE_BUSY:
03136       return DAHDI_TONE_BUSY;
03137    default:
03138       return -1;
03139    }
03140 }
03141 #endif   /* defined(HAVE_PRI) */
03142 
03143 #if defined(HAVE_PRI)
03144 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03145 {
03146    int x;
03147 
03148    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03149    switch (x) {
03150    case DAHDI_EVENT_NONE:
03151       break;
03152    case DAHDI_EVENT_ALARM:
03153    case DAHDI_EVENT_NOALARM:
03154       if (sig_pri_is_alarm_ignored(pri)) {
03155          break;
03156       }
03157       /* Fall through */
03158    default:
03159       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03160          event2str(x), x, pri->span);
03161       break;
03162    }
03163    /* Keep track of alarm state */
03164    switch (x) {
03165    case DAHDI_EVENT_ALARM:
03166       pri_event_alarm(pri, index, 0);
03167       break;
03168    case DAHDI_EVENT_NOALARM:
03169       pri_event_noalarm(pri, index, 0);
03170       break;
03171    default:
03172       break;
03173    }
03174 }
03175 #endif   /* defined(HAVE_PRI) */
03176 
03177 #if defined(HAVE_PRI)
03178 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03179 {
03180    struct dahdi_pvt *p = pvt;
03181 
03182    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03183 }
03184 #endif   /* defined(HAVE_PRI) */
03185 
03186 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03187 /*!
03188  * \internal
03189  * \brief Set the caller id information.
03190  * \since 1.8
03191  *
03192  * \param pvt DAHDI private structure
03193  * \param caller Caller-id information to set.
03194  *
03195  * \return Nothing
03196  */
03197 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03198 {
03199    struct dahdi_pvt *p = pvt;
03200 
03201    ast_copy_string(p->cid_num,
03202       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03203       sizeof(p->cid_num));
03204    ast_copy_string(p->cid_name,
03205       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03206       sizeof(p->cid_name));
03207    ast_copy_string(p->cid_subaddr,
03208       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03209       sizeof(p->cid_subaddr));
03210    p->cid_ton = caller->id.number.plan;
03211    p->callingpres = ast_party_id_presentation(&caller->id);
03212    if (caller->id.tag) {
03213       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03214    }
03215    ast_copy_string(p->cid_ani,
03216       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03217       sizeof(p->cid_ani));
03218    p->cid_ani2 = caller->ani2;
03219 }
03220 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03221 
03222 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03223 /*!
03224  * \internal
03225  * \brief Set the Dialed Number Identifier.
03226  * \since 1.8
03227  *
03228  * \param pvt DAHDI private structure
03229  * \param dnid Dialed Number Identifier string.
03230  *
03231  * \return Nothing
03232  */
03233 static void my_set_dnid(void *pvt, const char *dnid)
03234 {
03235    struct dahdi_pvt *p = pvt;
03236 
03237    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03238 }
03239 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03240 
03241 #if defined(HAVE_PRI)
03242 /*!
03243  * \internal
03244  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03245  * \since 1.8
03246  *
03247  * \param pvt DAHDI private structure
03248  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03249  *
03250  * \return Nothing
03251  */
03252 static void my_set_rdnis(void *pvt, const char *rdnis)
03253 {
03254    struct dahdi_pvt *p = pvt;
03255 
03256    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03257 }
03258 #endif   /* defined(HAVE_PRI) */
03259 
03260 #if defined(HAVE_PRI)
03261 /*!
03262  * \internal
03263  * \brief Make a dialstring for native ISDN CC to recall properly.
03264  * \since 1.8
03265  *
03266  * \param priv Channel private control structure.
03267  * \param buf Where to put the modified dialstring.
03268  * \param buf_size Size of modified dialstring buffer.
03269  *
03270  * \details
03271  * original dialstring:
03272  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03273  *
03274  * The modified dialstring will have prefixed the channel-group section
03275  * with the ISDN channel restriction.
03276  *
03277  * buf:
03278  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03279  *
03280  * The routine will check to see if the ISDN channel restriction is already
03281  * in the original dialstring.
03282  *
03283  * \return Nothing
03284  */
03285 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03286 {
03287    char *dial;
03288    struct dahdi_pvt *pvt;
03289    AST_DECLARE_APP_ARGS(args,
03290       AST_APP_ARG(tech);   /* channel technology token */
03291       AST_APP_ARG(group);  /* channel/group token */
03292       //AST_APP_ARG(ext);  /* extension token */
03293       //AST_APP_ARG(opts); /* options token */
03294       //AST_APP_ARG(other);   /* Any remining unused arguments */
03295    );
03296 
03297    pvt = priv;
03298    dial = ast_strdupa(pvt->dialstring);
03299    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03300    if (!args.tech) {
03301       ast_copy_string(buf, pvt->dialstring, buf_size);
03302       return;
03303    }
03304    if (!args.group) {
03305       /* Append the ISDN span channel restriction to the dialstring. */
03306       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03307       return;
03308    }
03309    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03310       /* The ISDN span channel restriction is not needed or already
03311        * in the dialstring. */
03312       ast_copy_string(buf, pvt->dialstring, buf_size);
03313       return;
03314    }
03315    /* Insert the ISDN span channel restriction into the dialstring. */
03316    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03317 }
03318 #endif   /* defined(HAVE_PRI) */
03319 
03320 #if defined(HAVE_PRI)
03321 /*!
03322  * \internal
03323  * \brief Reevaluate the PRI span device state.
03324  * \since 1.8
03325  *
03326  * \param pri Asterisk D channel control structure.
03327  *
03328  * \return Nothing
03329  *
03330  * \note Assumes the pri->lock is already obtained.
03331  */
03332 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03333 {
03334    unsigned idx;
03335    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03336    unsigned in_use;     /* Number of B channels in use on the span. */
03337    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03338    enum ast_device_state new_state;
03339 
03340    /* Count the number of B channels and the number of B channels in use. */
03341    num_b_chans = 0;
03342    in_use = 0;
03343    in_alarm = 1;
03344    for (idx = pri->numchans; idx--;) {
03345       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03346          /* This is a B channel interface. */
03347          ++num_b_chans;
03348          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03349             ++in_use;
03350          }
03351          if (!pri->pvts[idx]->inalarm) {
03352             /* There is a channel that is not in alarm. */
03353             in_alarm = 0;
03354          }
03355       }
03356    }
03357 
03358    /* Update the span congestion device state and report any change. */
03359    if (in_alarm) {
03360       new_state = AST_DEVICE_UNAVAILABLE;
03361    } else {
03362       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03363    }
03364    if (pri->congestion_devstate != new_state) {
03365       pri->congestion_devstate = new_state;
03366       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03367    }
03368 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03369    /* Update the span threshold device state and report any change. */
03370    if (in_alarm) {
03371       new_state = AST_DEVICE_UNAVAILABLE;
03372    } else if (!in_use) {
03373       new_state = AST_DEVICE_NOT_INUSE;
03374    } else if (!pri->user_busy_threshold) {
03375       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03376    } else {
03377       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03378          : AST_DEVICE_BUSY;
03379    }
03380    if (pri->threshold_devstate != new_state) {
03381       pri->threshold_devstate = new_state;
03382       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03383    }
03384 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03385 }
03386 #endif   /* defined(HAVE_PRI) */
03387 
03388 #if defined(HAVE_PRI)
03389 /*!
03390  * \internal
03391  * \brief Reference this module.
03392  * \since 1.8
03393  *
03394  * \return Nothing
03395  */
03396 static void my_module_ref(void)
03397 {
03398    ast_module_ref(ast_module_info->self);
03399 }
03400 #endif   /* defined(HAVE_PRI) */
03401 
03402 #if defined(HAVE_PRI)
03403 /*!
03404  * \internal
03405  * \brief Unreference this module.
03406  * \since 1.8
03407  *
03408  * \return Nothing
03409  */
03410 static void my_module_unref(void)
03411 {
03412    ast_module_unref(ast_module_info->self);
03413 }
03414 #endif   /* defined(HAVE_PRI) */
03415 
03416 #if defined(HAVE_PRI)
03417 #if defined(HAVE_PRI_CALL_WAITING)
03418 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03419 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03420 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03421 
03422 static struct sig_pri_callback dahdi_pri_callbacks =
03423 {
03424    .handle_dchan_exception = my_handle_dchan_exception,
03425    .play_tone = my_pri_play_tone,
03426    .set_echocanceller = my_set_echocanceller,
03427    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03428    .lock_private = my_lock_private,
03429    .unlock_private = my_unlock_private,
03430    .new_ast_channel = my_new_pri_ast_channel,
03431    .fixup_chans = my_pri_fixup_chans,
03432    .set_alarm = my_set_alarm,
03433    .set_dialing = my_set_dialing,
03434    .set_outgoing = my_set_outgoing,
03435    .set_digital = my_set_digital,
03436    .set_callerid = my_set_callerid,
03437    .set_dnid = my_set_dnid,
03438    .set_rdnis = my_set_rdnis,
03439    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03440 #if defined(HAVE_PRI_CALL_WAITING)
03441    .init_config = my_pri_init_config,
03442 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03443    .get_orig_dialstring = my_get_orig_dialstring,
03444    .make_cc_dialstring = my_pri_make_cc_dialstring,
03445    .update_span_devstate = dahdi_pri_update_span_devstate,
03446    .module_ref = my_module_ref,
03447    .module_unref = my_module_unref,
03448    .dial_digits = my_pri_dial_digits,
03449    .open_media = my_pri_ss7_open_media,
03450    .ami_channel_event = my_ami_channel_event,
03451 };
03452 #endif   /* defined(HAVE_PRI) */
03453 
03454 #if defined(HAVE_SS7)
03455 /*!
03456  * \internal
03457  * \brief Handle the SS7 link exception.
03458  * \since 1.8
03459  *
03460  * \param linkset Controlling linkset for the channel.
03461  * \param which Link index of the signaling channel.
03462  *
03463  * \return Nothing
03464  */
03465 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03466 {
03467    int event;
03468 
03469    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03470       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03471          linkset->span, which);
03472       return;
03473    }
03474    switch (event) {
03475    case DAHDI_EVENT_NONE:
03476       break;
03477    case DAHDI_EVENT_ALARM:
03478       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03479          event2str(event), event, linkset->span, which);
03480       sig_ss7_link_alarm(linkset, which);
03481       break;
03482    case DAHDI_EVENT_NOALARM:
03483       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03484          event2str(event), event, linkset->span, which);
03485       sig_ss7_link_noalarm(linkset, which);
03486       break;
03487    default:
03488       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03489          event2str(event), event, linkset->span, which);
03490       break;
03491    }
03492 }
03493 #endif   /* defined(HAVE_SS7) */
03494 
03495 #if defined(HAVE_SS7)
03496 static void my_ss7_set_loopback(void *pvt, int enable)
03497 {
03498    struct dahdi_pvt *p = pvt;
03499 
03500    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03501       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03502          strerror(errno));
03503    }
03504 }
03505 #endif   /* defined(HAVE_SS7) */
03506 
03507 #if defined(HAVE_SS7)
03508 /*!
03509  * \internal
03510  * \brief Create a new asterisk channel structure for SS7.
03511  * \since 1.8
03512  *
03513  * \param pvt Private channel structure.
03514  * \param state Initial state of new channel.
03515  * \param law Combanding law to use.
03516  * \param exten Dialplan extension for incoming call.
03517  * \param requestor Channel requesting this new channel.
03518  *
03519  * \retval ast_channel on success.
03520  * \retval NULL on error.
03521  */
03522 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)
03523 {
03524    struct dahdi_pvt *p = pvt;
03525    int audio;
03526    int newlaw;
03527 
03528    /* Set to audio mode at this point */
03529    audio = 1;
03530    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03531       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03532          p->channel, audio, strerror(errno));
03533 
03534    if (law != SIG_SS7_DEFLAW) {
03535       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03536          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03537    }
03538 
03539    ast_copy_string(p->exten, exten, sizeof(p->exten));
03540 
03541    newlaw = -1;
03542    switch (law) {
03543    case SIG_SS7_DEFLAW:
03544       newlaw = 0;
03545       break;
03546    case SIG_SS7_ALAW:
03547       newlaw = DAHDI_LAW_ALAW;
03548       break;
03549    case SIG_SS7_ULAW:
03550       newlaw = DAHDI_LAW_MULAW;
03551       break;
03552    }
03553    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03554 }
03555 #endif   /* defined(HAVE_SS7) */
03556 
03557 #if defined(HAVE_SS7)
03558 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03559 {
03560    switch (tone) {
03561    case SIG_SS7_TONE_RINGTONE:
03562       return DAHDI_TONE_RINGTONE;
03563    case SIG_SS7_TONE_STUTTER:
03564       return DAHDI_TONE_STUTTER;
03565    case SIG_SS7_TONE_CONGESTION:
03566       return DAHDI_TONE_CONGESTION;
03567    case SIG_SS7_TONE_DIALTONE:
03568       return DAHDI_TONE_DIALTONE;
03569    case SIG_SS7_TONE_DIALRECALL:
03570       return DAHDI_TONE_DIALRECALL;
03571    case SIG_SS7_TONE_INFO:
03572       return DAHDI_TONE_INFO;
03573    case SIG_SS7_TONE_BUSY:
03574       return DAHDI_TONE_BUSY;
03575    default:
03576       return -1;
03577    }
03578 }
03579 #endif   /* defined(HAVE_SS7) */
03580 
03581 #if defined(HAVE_SS7)
03582 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03583 {
03584    struct dahdi_pvt *p = pvt;
03585 
03586    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03587 }
03588 #endif   /* defined(HAVE_SS7) */
03589 
03590 #if defined(HAVE_SS7)
03591 static struct sig_ss7_callback dahdi_ss7_callbacks =
03592 {
03593    .lock_private = my_lock_private,
03594    .unlock_private = my_unlock_private,
03595 
03596    .set_echocanceller = my_set_echocanceller,
03597    .set_loopback = my_ss7_set_loopback,
03598 
03599    .new_ast_channel = my_new_ss7_ast_channel,
03600    .play_tone = my_ss7_play_tone,
03601 
03602    .handle_link_exception = my_handle_link_exception,
03603    .set_alarm = my_set_alarm,
03604    .set_dialing = my_set_dialing,
03605    .set_outgoing = my_set_outgoing,
03606    .set_digital = my_set_digital,
03607    .set_inservice = my_set_inservice,
03608    .set_locallyblocked = my_set_locallyblocked,
03609    .set_remotelyblocked = my_set_remotelyblocked,
03610    .set_callerid = my_set_callerid,
03611    .set_dnid = my_set_dnid,
03612    .open_media = my_pri_ss7_open_media,
03613 };
03614 #endif   /* defined(HAVE_SS7) */
03615 
03616 /*!
03617  * \brief Send MWI state change
03618  *
03619  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03620  *      MWI state has changed on.
03621  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03622  *      whether there are messages waiting or not.
03623  *
03624  *  \return nothing
03625  *
03626  * This function does two things:
03627  *
03628  * 1) It generates an internal Asterisk event notifying any other module that
03629  *    cares about MWI that the state of a mailbox has changed.
03630  *
03631  * 2) It runs the script specified by the mwimonitornotify option to allow
03632  *    some custom handling of the state change.
03633  */
03634 static void notify_message(char *mailbox_full, int thereornot)
03635 {
03636    char s[sizeof(mwimonitornotify) + 80];
03637    struct ast_event *event;
03638    char *mailbox, *context;
03639 
03640    /* Strip off @default */
03641    context = mailbox = ast_strdupa(mailbox_full);
03642    strsep(&context, "@");
03643    if (ast_strlen_zero(context))
03644       context = "default";
03645 
03646    if (!(event = ast_event_new(AST_EVENT_MWI,
03647          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03648          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03649          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03650          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03651          AST_EVENT_IE_END))) {
03652       return;
03653    }
03654 
03655    ast_event_queue_and_cache(event);
03656 
03657    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03658       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03659       ast_safe_system(s);
03660    }
03661 }
03662 
03663 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03664 {
03665    struct dahdi_pvt *p = pvt;
03666 
03667    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03668       return;
03669 
03670    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03671       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03672       notify_message(p->mailbox, 1);
03673    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03674       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03675       notify_message(p->mailbox, 0);
03676    }
03677    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03678    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03679    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03680       ast_hangup(chan);
03681       return;
03682    }
03683 }
03684 
03685 static int my_have_progressdetect(void *pvt)
03686 {
03687    struct dahdi_pvt *p = pvt;
03688 
03689    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03690       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03691       return 1;
03692    } else {
03693       /* Don't have progress detection. */
03694       return 0;
03695    }
03696 }
03697 
03698 static struct analog_callback dahdi_analog_callbacks =
03699 {
03700    .play_tone = my_play_tone,
03701    .get_event = my_get_event,
03702    .wait_event = my_wait_event,
03703    .is_off_hook = my_is_off_hook,
03704    .set_echocanceller = my_set_echocanceller,
03705    .ring = my_ring,
03706    .flash = my_flash,
03707    .off_hook = my_off_hook,
03708    .dial_digits = my_dial_digits,
03709    .train_echocanceller = my_train_echocanceller,
03710    .on_hook = my_on_hook,
03711    .is_dialing = my_is_dialing,
03712    .allocate_sub = my_allocate_sub,
03713    .unallocate_sub = my_unallocate_sub,
03714    .swap_subs = my_swap_subchannels,
03715    .has_voicemail = my_has_voicemail,
03716    .check_for_conference = my_check_for_conference,
03717    .conf_add = my_conf_add,
03718    .conf_del = my_conf_del,
03719    .complete_conference_update = my_complete_conference_update,
03720    .start = my_start,
03721    .all_subchannels_hungup = my_all_subchannels_hungup,
03722    .lock_private = my_lock_private,
03723    .unlock_private = my_unlock_private,
03724    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03725    .handle_dtmf = my_handle_dtmf,
03726    .wink = my_wink,
03727    .new_ast_channel = my_new_analog_ast_channel,
03728    .dsp_set_digitmode = my_dsp_set_digitmode,
03729    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03730    .send_callerid = my_send_callerid,
03731    .callwait = my_callwait,
03732    .stop_callwait = my_stop_callwait,
03733    .get_callerid = my_get_callerid,
03734    .start_cid_detect = my_start_cid_detect,
03735    .stop_cid_detect = my_stop_cid_detect,
03736    .handle_notify_message = my_handle_notify_message,
03737    .increase_ss_count = my_increase_ss_count,
03738    .decrease_ss_count = my_decrease_ss_count,
03739    .distinctive_ring = my_distinctive_ring,
03740    .set_linear_mode = my_set_linear_mode,
03741    .set_inthreeway = my_set_inthreeway,
03742    .get_and_handle_alarms = my_get_and_handle_alarms,
03743    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03744    .get_sub_fd = my_get_sub_fd,
03745    .set_cadence = my_set_cadence,
03746    .set_alarm = my_set_alarm,
03747    .set_dialing = my_set_dialing,
03748    .set_outgoing = my_set_outgoing,
03749    .set_ringtimeout = my_set_ringtimeout,
03750    .set_waitingfordt = my_set_waitingfordt,
03751    .check_waitingfordt = my_check_waitingfordt,
03752    .set_confirmanswer = my_set_confirmanswer,
03753    .check_confirmanswer = my_check_confirmanswer,
03754    .set_callwaiting = my_set_callwaiting,
03755    .cancel_cidspill = my_cancel_cidspill,
03756    .confmute = my_confmute,
03757    .set_pulsedial = my_set_pulsedial,
03758    .set_new_owner = my_set_new_owner,
03759    .get_orig_dialstring = my_get_orig_dialstring,
03760    .set_needringing = my_set_needringing,
03761    .set_polarity = my_set_polarity,
03762    .start_polarityswitch = my_start_polarityswitch,
03763    .answer_polarityswitch = my_answer_polarityswitch,
03764    .hangup_polarityswitch = my_hangup_polarityswitch,
03765    .have_progressdetect = my_have_progressdetect,
03766 };
03767 
03768 /*! Round robin search locations. */
03769 static struct dahdi_pvt *round_robin[32];
03770 
03771 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03772 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03773 {
03774    int res;
03775    if (p->subs[SUB_REAL].owner == ast)
03776       res = 0;
03777    else if (p->subs[SUB_CALLWAIT].owner == ast)
03778       res = 1;
03779    else if (p->subs[SUB_THREEWAY].owner == ast)
03780       res = 2;
03781    else {
03782       res = -1;
03783       if (!nullok)
03784          ast_log(LOG_WARNING,
03785             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03786             ast ? ast->name : "", p->channel, fname, line);
03787    }
03788    return res;
03789 }
03790 
03791 /*!
03792  * \internal
03793  * \brief Obtain the specified subchannel owner lock if the owner exists.
03794  *
03795  * \param pvt Channel private struct.
03796  * \param sub_idx Subchannel owner to lock.
03797  *
03798  * \note Assumes the pvt->lock is already obtained.
03799  *
03800  * \note
03801  * Because deadlock avoidance may have been necessary, you need to confirm
03802  * the state of things before continuing.
03803  *
03804  * \return Nothing
03805  */
03806 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03807 {
03808    for (;;) {
03809       if (!pvt->subs[sub_idx].owner) {
03810          /* No subchannel owner pointer */
03811          break;
03812       }
03813       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03814          /* Got subchannel owner lock */
03815          break;
03816       }
03817       /* We must unlock the private to avoid the possibility of a deadlock */
03818       DEADLOCK_AVOIDANCE(&pvt->lock);
03819    }
03820 }
03821 
03822 static void wakeup_sub(struct dahdi_pvt *p, int a)
03823 {
03824    dahdi_lock_sub_owner(p, a);
03825    if (p->subs[a].owner) {
03826       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03827       ast_channel_unlock(p->subs[a].owner);
03828    }
03829 }
03830 
03831 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03832 {
03833    for (;;) {
03834       if (p->owner) {
03835          if (ast_channel_trylock(p->owner)) {
03836             DEADLOCK_AVOIDANCE(&p->lock);
03837          } else {
03838             ast_queue_frame(p->owner, f);
03839             ast_channel_unlock(p->owner);
03840             break;
03841          }
03842       } else
03843          break;
03844    }
03845 }
03846 
03847 static void handle_clear_alarms(struct dahdi_pvt *p)
03848 {
03849 #if defined(HAVE_PRI)
03850    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03851       return;
03852    }
03853 #endif   /* defined(HAVE_PRI) */
03854 
03855    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03856       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03857       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03858    }
03859    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03860       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03861       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03862    }
03863 }
03864 
03865 #ifdef HAVE_OPENR2
03866 
03867 static int dahdi_r2_answer(struct dahdi_pvt *p)
03868 {
03869    int res = 0;
03870    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03871    * and does not has support for openr2_chan_answer_call_with_mode
03872    *  */
03873 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03874    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03875    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03876    if (!double_answer) {
03877       /* this still can result in double answer if the channel context
03878       * was configured that way */
03879       res = openr2_chan_answer_call(p->r2chan);
03880    } else if (wants_double_answer) {
03881       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03882    } else {
03883       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03884    }
03885 #else
03886    res = openr2_chan_answer_call(p->r2chan);
03887 #endif
03888    return res;
03889 }
03890 
03891 
03892 
03893 /* should be called with the ast_channel locked */
03894 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03895 {
03896    openr2_calling_party_category_t cat;
03897    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03898    struct dahdi_pvt *p = c->tech_pvt;
03899    if (ast_strlen_zero(catstr)) {
03900       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03901             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03902       return p->mfcr2_category;
03903    }
03904    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03905       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03906             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03907       return p->mfcr2_category;
03908    }
03909    ast_debug(1, "Using category %s\n", catstr);
03910    return cat;
03911 }
03912 
03913 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03914 {
03915    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03916    ast_mutex_lock(&p->lock);
03917    if (p->mfcr2call) {
03918       ast_mutex_unlock(&p->lock);
03919       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03920          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03921          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03922          the other end will see our seize as a forced release and drop the call, we will see an invalid
03923          pattern that will be seen and treated as protocol error. */
03924       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03925       return;
03926    }
03927    p->mfcr2call = 1;
03928    /* better safe than sorry ... */
03929    p->cid_name[0] = '\0';
03930    p->cid_num[0] = '\0';
03931    p->cid_subaddr[0] = '\0';
03932    p->rdnis[0] = '\0';
03933    p->exten[0] = '\0';
03934    p->mfcr2_ani_index = '\0';
03935    p->mfcr2_dnis_index = '\0';
03936    p->mfcr2_dnis_matched = 0;
03937    p->mfcr2_answer_pending = 0;
03938    p->mfcr2_call_accepted = 0;
03939    ast_mutex_unlock(&p->lock);
03940    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03941 }
03942 
03943 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03944 {
03945    int res;
03946    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03947    ast_mutex_lock(&p->lock);
03948    p->inalarm = alarm ? 1 : 0;
03949    if (p->inalarm) {
03950       res = get_alarms(p);
03951       handle_alarms(p, res);
03952    } else {
03953       handle_clear_alarms(p);
03954    }
03955    ast_mutex_unlock(&p->lock);
03956 }
03957 
03958 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03959 {
03960    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03961 }
03962 
03963 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03964 {
03965    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03966    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03967    if (p->owner) {
03968       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03969       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03970    }
03971    ast_mutex_lock(&p->lock);
03972    p->mfcr2call = 0;
03973    ast_mutex_unlock(&p->lock);
03974 }
03975 
03976 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03977 {
03978    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03979       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03980          p->channel, openr2_proto_get_disconnect_string(cause));
03981       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03982       openr2_chan_set_idle(p->r2chan);
03983       ast_mutex_lock(&p->lock);
03984       p->mfcr2call = 0;
03985       ast_mutex_unlock(&p->lock);
03986    }
03987 }
03988 
03989 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03990 {
03991    struct dahdi_pvt *p;
03992    struct ast_channel *c;
03993    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03994          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03995          openr2_proto_get_category_string(category));
03996    p = openr2_chan_get_client_data(r2chan);
03997    /* if collect calls are not allowed and this is a collect call, reject it! */
03998    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03999       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04000       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04001       return;
04002    }
04003    ast_mutex_lock(&p->lock);
04004    p->mfcr2_recvd_category = category;
04005    /* if we're not supposed to use CID, clear whatever we have */
04006    if (!p->use_callerid) {
04007       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04008       p->cid_num[0] = 0;
04009       p->cid_name[0] = 0;
04010    }
04011    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04012    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04013       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04014       p->exten[0] = 's';
04015       p->exten[1] = 0;
04016    }
04017    ast_mutex_unlock(&p->lock);
04018    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04019       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04020             p->channel, p->exten, p->context);
04021       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04022       return;
04023    }
04024    if (!p->mfcr2_accept_on_offer) {
04025       /* The user wants us to start the PBX thread right away without accepting the call first */
04026       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04027       if (c) {
04028          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04029             the call or reject it and detect the tone off condition of the other end, all of this
04030             will be done in the PBX thread now */
04031          return;
04032       }
04033       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04034       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04035    } else if (p->mfcr2_charge_calls) {
04036       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04037       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04038    } else {
04039       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04040       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04041    }
04042 }
04043 
04044 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04045 {
04046    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04047    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04048    ast_mutex_lock(&p->lock);
04049    p->mfcr2call = 0;
04050    ast_mutex_unlock(&p->lock);
04051 }
04052 
04053 static void dahdi_enable_ec(struct dahdi_pvt *p);
04054 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04055 {
04056    struct dahdi_pvt *p = NULL;
04057    struct ast_channel *c = NULL;
04058    p = openr2_chan_get_client_data(r2chan);
04059    dahdi_enable_ec(p);
04060    p->mfcr2_call_accepted = 1;
04061    /* if it's an incoming call ... */
04062    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04063       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04064       /* If accept on offer is not set, it means at this point the PBX thread is already
04065          launched (was launched in the 'on call offered' handler) and therefore this callback
04066          is being executed already in the PBX thread rather than the monitor thread, don't launch
04067          any other thread, just disable the openr2 reading and answer the call if needed */
04068       if (!p->mfcr2_accept_on_offer) {
04069          openr2_chan_disable_read(r2chan);
04070          if (p->mfcr2_answer_pending) {
04071             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04072             dahdi_r2_answer(p);
04073          }
04074          return;
04075       }
04076       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04077       if (c) {
04078          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04079             library to forget about it */
04080          openr2_chan_disable_read(r2chan);
04081          return;
04082       }
04083       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04084       /* failed to create the channel, bail out and report it as an out of order line */
04085       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04086       return;
04087    }
04088    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04089    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04090    p->subs[SUB_REAL].needringing = 1;
04091    p->dialing = 0;
04092    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04093    openr2_chan_disable_read(r2chan);
04094 }
04095 
04096 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04097 {
04098    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04099    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04100    p->subs[SUB_REAL].needanswer = 1;
04101 }
04102 
04103 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04104 {
04105    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04106 }
04107 
04108 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04109 {
04110    switch (cause) {
04111    case OR2_CAUSE_BUSY_NUMBER:
04112       return AST_CAUSE_BUSY;
04113    case OR2_CAUSE_NETWORK_CONGESTION:
04114       return AST_CAUSE_CONGESTION;
04115    case OR2_CAUSE_OUT_OF_ORDER:
04116       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04117    case OR2_CAUSE_UNALLOCATED_NUMBER:
04118       return AST_CAUSE_UNREGISTERED;
04119    case OR2_CAUSE_NO_ANSWER:
04120       return AST_CAUSE_NO_ANSWER;
04121    case OR2_CAUSE_NORMAL_CLEARING:
04122       return AST_CAUSE_NORMAL_CLEARING;
04123    case OR2_CAUSE_UNSPECIFIED:
04124    default:
04125       return AST_CAUSE_NOTDEFINED;
04126    }
04127 }
04128 
04129 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04130 {
04131    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04132    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04133    ast_mutex_lock(&p->lock);
04134    if (!p->owner) {
04135       ast_mutex_unlock(&p->lock);
04136       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04137       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04138       return;
04139    }
04140    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04141       be done in dahdi_hangup */
04142    if (p->owner->_state == AST_STATE_UP) {
04143       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04144       ast_mutex_unlock(&p->lock);
04145    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04146       /* being the forward side we must report what happened to the call to whoever requested it */
04147       switch (cause) {
04148       case OR2_CAUSE_BUSY_NUMBER:
04149          p->subs[SUB_REAL].needbusy = 1;
04150          break;
04151       case OR2_CAUSE_NETWORK_CONGESTION:
04152       case OR2_CAUSE_OUT_OF_ORDER:
04153       case OR2_CAUSE_UNALLOCATED_NUMBER:
04154       case OR2_CAUSE_NO_ANSWER:
04155       case OR2_CAUSE_UNSPECIFIED:
04156       case OR2_CAUSE_NORMAL_CLEARING:
04157          p->subs[SUB_REAL].needcongestion = 1;
04158          break;
04159       default:
04160          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04161       }
04162       ast_mutex_unlock(&p->lock);
04163    } else {
04164       ast_mutex_unlock(&p->lock);
04165       /* being the backward side and not UP yet, we only need to request hangup */
04166       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04167       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04168    }
04169 }
04170 
04171 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04172 {
04173    switch (level) {
04174    case OR2_LOG_NOTICE:
04175       ast_verbose("%s", logmessage);
04176       break;
04177    case OR2_LOG_WARNING:
04178       ast_log(LOG_WARNING, "%s", logmessage);
04179       break;
04180    case OR2_LOG_ERROR:
04181       ast_log(LOG_ERROR, "%s", logmessage);
04182       break;
04183    case OR2_LOG_STACK_TRACE:
04184    case OR2_LOG_MF_TRACE:
04185    case OR2_LOG_CAS_TRACE:
04186    case OR2_LOG_DEBUG:
04187    case OR2_LOG_EX_DEBUG:
04188       ast_log(LOG_DEBUG, "%s", logmessage);
04189       break;
04190    default:
04191       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04192       ast_log(LOG_DEBUG, "%s", logmessage);
04193       break;
04194    }
04195 }
04196 
04197 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04198 {
04199    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04200    ast_mutex_lock(&p->lock);
04201    p->remotelyblocked = 1;
04202    ast_mutex_unlock(&p->lock);
04203    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04204 }
04205 
04206 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04207 {
04208    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04209    ast_mutex_lock(&p->lock);
04210    p->remotelyblocked = 0;
04211    ast_mutex_unlock(&p->lock);
04212    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04213 }
04214 
04215 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04216    __attribute__((format (printf, 3, 0)));
04217 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04218 {
04219 #define CONTEXT_TAG "Context - "
04220    char logmsg[256];
04221    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04222    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04223    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04224    dahdi_r2_write_log(level, completemsg);
04225 #undef CONTEXT_TAG
04226 }
04227 
04228 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04229    __attribute__((format (printf, 3, 0)));
04230 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04231 {
04232 #define CHAN_TAG "Chan "
04233    char logmsg[256];
04234    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04235    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04236    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04237    dahdi_r2_write_log(level, completemsg);
04238 }
04239 
04240 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04241 {
04242    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04243    /* if 'immediate' is set, let's stop requesting DNIS */
04244    if (p->immediate) {
04245       return 0;
04246    }
04247    p->exten[p->mfcr2_dnis_index] = digit;
04248    p->rdnis[p->mfcr2_dnis_index] = digit;
04249    p->mfcr2_dnis_index++;
04250    p->exten[p->mfcr2_dnis_index] = 0;
04251    p->rdnis[p->mfcr2_dnis_index] = 0;
04252    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04253    if ((p->mfcr2_dnis_matched ||
04254        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04255        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04256       return 0;
04257    }
04258    /* otherwise keep going */
04259    return 1;
04260 }
04261 
04262 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04263 {
04264    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04265    p->cid_num[p->mfcr2_ani_index] = digit;
04266    p->cid_name[p->mfcr2_ani_index] = digit;
04267    p->mfcr2_ani_index++;
04268    p->cid_num[p->mfcr2_ani_index] = 0;
04269    p->cid_name[p->mfcr2_ani_index] = 0;
04270 }
04271 
04272 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04273 {
04274    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04275 }
04276 
04277 static openr2_event_interface_t dahdi_r2_event_iface = {
04278    .on_call_init = dahdi_r2_on_call_init,
04279    .on_call_offered = dahdi_r2_on_call_offered,
04280    .on_call_accepted = dahdi_r2_on_call_accepted,
04281    .on_call_answered = dahdi_r2_on_call_answered,
04282    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04283    .on_call_end = dahdi_r2_on_call_end,
04284    .on_call_read = dahdi_r2_on_call_read,
04285    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04286    .on_os_error = dahdi_r2_on_os_error,
04287    .on_protocol_error = dahdi_r2_on_protocol_error,
04288    .on_line_blocked = dahdi_r2_on_line_blocked,
04289    .on_line_idle = dahdi_r2_on_line_idle,
04290    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04291    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04292    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04293    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04294    /* so far we do nothing with billing pulses */
04295    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04296 };
04297 
04298 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04299 {
04300    return AST_ALAW(sample);
04301 }
04302 
04303 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04304 {
04305    return AST_LIN2A(sample);
04306 }
04307 
04308 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04309    dahdi_r2_alaw_to_linear,
04310    dahdi_r2_linear_to_alaw
04311 };
04312 
04313 #endif /* HAVE_OPENR2 */
04314 
04315 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04316 {
04317    int tchan;
04318    int tinthreeway;
04319    struct ast_channel *towner;
04320 
04321    ast_debug(1, "Swapping %d and %d\n", a, b);
04322 
04323    tchan = p->subs[a].chan;
04324    towner = p->subs[a].owner;
04325    tinthreeway = p->subs[a].inthreeway;
04326 
04327    p->subs[a].chan = p->subs[b].chan;
04328    p->subs[a].owner = p->subs[b].owner;
04329    p->subs[a].inthreeway = p->subs[b].inthreeway;
04330 
04331    p->subs[b].chan = tchan;
04332    p->subs[b].owner = towner;
04333    p->subs[b].inthreeway = tinthreeway;
04334 
04335    if (p->subs[a].owner)
04336       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04337    if (p->subs[b].owner)
04338       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04339    wakeup_sub(p, a);
04340    wakeup_sub(p, b);
04341 }
04342 
04343 static int dahdi_open(char *fn)
04344 {
04345    int fd;
04346    int isnum;
04347    int chan = 0;
04348    int bs;
04349    int x;
04350    isnum = 1;
04351    for (x = 0; x < strlen(fn); x++) {
04352       if (!isdigit(fn[x])) {
04353          isnum = 0;
04354          break;
04355       }
04356    }
04357    if (isnum) {
04358       chan = atoi(fn);
04359       if (chan < 1) {
04360          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04361          return -1;
04362       }
04363       fn = "/dev/dahdi/channel";
04364    }
04365    fd = open(fn, O_RDWR | O_NONBLOCK);
04366    if (fd < 0) {
04367       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04368       return -1;
04369    }
04370    if (chan) {
04371       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04372          x = errno;
04373          close(fd);
04374          errno = x;
04375          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04376          return -1;
04377       }
04378    }
04379    bs = READ_SIZE;
04380    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04381       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04382       x = errno;
04383       close(fd);
04384       errno = x;
04385       return -1;
04386    }
04387    return fd;
04388 }
04389 
04390 static void dahdi_close(int fd)
04391 {
04392    if (fd > 0)
04393       close(fd);
04394 }
04395 
04396 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04397 {
04398    dahdi_close(chan_pvt->subs[sub_num].dfd);
04399    chan_pvt->subs[sub_num].dfd = -1;
04400 }
04401 
04402 #if defined(HAVE_PRI)
04403 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04404 {
04405    dahdi_close(pri->pri.fds[fd_num]);
04406    pri->pri.fds[fd_num] = -1;
04407 }
04408 #endif   /* defined(HAVE_PRI) */
04409 
04410 #if defined(HAVE_SS7)
04411 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04412 {
04413    dahdi_close(ss7->ss7.fds[fd_num]);
04414    ss7->ss7.fds[fd_num] = -1;
04415 }
04416 #endif   /* defined(HAVE_SS7) */
04417 
04418 static int dahdi_setlinear(int dfd, int linear)
04419 {
04420    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04421 }
04422 
04423 
04424 static int alloc_sub(struct dahdi_pvt *p, int x)
04425 {
04426    struct dahdi_bufferinfo bi;
04427    int res;
04428    if (p->subs[x].dfd >= 0) {
04429       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04430       return -1;
04431    }
04432 
04433    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04434    if (p->subs[x].dfd <= -1) {
04435       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04436       return -1;
04437    }
04438 
04439    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04440    if (!res) {
04441       bi.txbufpolicy = p->buf_policy;
04442       bi.rxbufpolicy = p->buf_policy;
04443       bi.numbufs = p->buf_no;
04444       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04445       if (res < 0) {
04446          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04447       }
04448    } else
04449       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04450 
04451    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04452       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04453       dahdi_close_sub(p, x);
04454       p->subs[x].dfd = -1;
04455       return -1;
04456    }
04457    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04458    return 0;
04459 }
04460 
04461 static int unalloc_sub(struct dahdi_pvt *p, int x)
04462 {
04463    if (!x) {
04464       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04465       return -1;
04466    }
04467    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04468    dahdi_close_sub(p, x);
04469    p->subs[x].linear = 0;
04470    p->subs[x].chan = 0;
04471    p->subs[x].owner = NULL;
04472    p->subs[x].inthreeway = 0;
04473    p->polarity = POLARITY_IDLE;
04474    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04475    return 0;
04476 }
04477 
04478 static int digit_to_dtmfindex(char digit)
04479 {
04480    if (isdigit(digit))
04481       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04482    else if (digit >= 'A' && digit <= 'D')
04483       return DAHDI_TONE_DTMF_A + (digit - 'A');
04484    else if (digit >= 'a' && digit <= 'd')
04485       return DAHDI_TONE_DTMF_A + (digit - 'a');
04486    else if (digit == '*')
04487       return DAHDI_TONE_DTMF_s;
04488    else if (digit == '#')
04489       return DAHDI_TONE_DTMF_p;
04490    else
04491       return -1;
04492 }
04493 
04494 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04495 {
04496    struct dahdi_pvt *pvt;
04497    int idx;
04498    int dtmf = -1;
04499    int res;
04500 
04501    pvt = chan->tech_pvt;
04502 
04503    ast_mutex_lock(&pvt->lock);
04504 
04505    idx = dahdi_get_index(chan, pvt, 0);
04506 
04507    if ((idx != SUB_REAL) || !pvt->owner)
04508       goto out;
04509 
04510 #ifdef HAVE_PRI
04511    switch (pvt->sig) {
04512    case SIG_PRI_LIB_HANDLE_CASES:
04513       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04514       if (!res)
04515          goto out;
04516       break;
04517    default:
04518       break;
04519    }
04520 #endif
04521    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04522       goto out;
04523 
04524    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04525       struct dahdi_dialoperation zo = {
04526          .op = DAHDI_DIAL_OP_APPEND,
04527       };
04528 
04529       zo.dialstr[0] = 'T';
04530       zo.dialstr[1] = digit;
04531       zo.dialstr[2] = '\0';
04532       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04533          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04534             chan->name, digit, strerror(errno));
04535       else
04536          pvt->dialing = 1;
04537    } else {
04538       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04539          chan->name, digit);
04540       pvt->dialing = 1;
04541       pvt->begindigit = digit;
04542    }
04543 
04544 out:
04545    ast_mutex_unlock(&pvt->lock);
04546 
04547    return 0;
04548 }
04549 
04550 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04551 {
04552    struct dahdi_pvt *pvt;
04553    int res = 0;
04554    int idx;
04555    int x;
04556 
04557    pvt = chan->tech_pvt;
04558 
04559    ast_mutex_lock(&pvt->lock);
04560 
04561    idx = dahdi_get_index(chan, pvt, 0);
04562 
04563    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04564       goto out;
04565 
04566 #ifdef HAVE_PRI
04567    /* This means that the digit was already sent via PRI signalling */
04568    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04569       goto out;
04570    }
04571 #endif
04572 
04573    if (pvt->begindigit) {
04574       x = -1;
04575       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04576          chan->name, digit);
04577       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04578       pvt->dialing = 0;
04579       pvt->begindigit = 0;
04580    }
04581 
04582 out:
04583    ast_mutex_unlock(&pvt->lock);
04584 
04585    return res;
04586 }
04587 
04588 static const char * const events[] = {
04589    "No event",
04590    "On hook",
04591    "Ring/Answered",
04592    "Wink/Flash",
04593    "Alarm",
04594    "No more alarm",
04595    "HDLC Abort",
04596    "HDLC Overrun",
04597    "HDLC Bad FCS",
04598    "Dial Complete",
04599    "Ringer On",
04600    "Ringer Off",
04601    "Hook Transition Complete",
04602    "Bits Changed",
04603    "Pulse Start",
04604    "Timer Expired",
04605    "Timer Ping",
04606    "Polarity Reversal",
04607    "Ring Begin",
04608 };
04609 
04610 static struct {
04611    int alarm;
04612    char *name;
04613 } alarms[] = {
04614    { DAHDI_ALARM_RED, "Red Alarm" },
04615    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04616    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04617    { DAHDI_ALARM_RECOVER, "Recovering" },
04618    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04619    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04620    { DAHDI_ALARM_NONE, "None" },
04621 };
04622 
04623 static char *alarm2str(int alm)
04624 {
04625    int x;
04626    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04627       if (alarms[x].alarm & alm)
04628          return alarms[x].name;
04629    }
04630    return alm ? "Unknown Alarm" : "No Alarm";
04631 }
04632 
04633 static const char *event2str(int event)
04634 {
04635    static char buf[256];
04636    if ((event < (ARRAY_LEN(events))) && (event > -1))
04637       return events[event];
04638    sprintf(buf, "Event %d", event); /* safe */
04639    return buf;
04640 }
04641 
04642 static char *dahdi_sig2str(int sig)
04643 {
04644    static char buf[256];
04645    switch (sig) {
04646    case SIG_EM:
04647       return "E & M Immediate";
04648    case SIG_EMWINK:
04649       return "E & M Wink";
04650    case SIG_EM_E1:
04651       return "E & M E1";
04652    case SIG_FEATD:
04653       return "Feature Group D (DTMF)";
04654    case SIG_FEATDMF:
04655       return "Feature Group D (MF)";
04656    case SIG_FEATDMF_TA:
04657       return "Feature Groud D (MF) Tandem Access";
04658    case SIG_FEATB:
04659       return "Feature Group B (MF)";
04660    case SIG_E911:
04661       return "E911 (MF)";
04662    case SIG_FGC_CAMA:
04663       return "FGC/CAMA (Dialpulse)";
04664    case SIG_FGC_CAMAMF:
04665       return "FGC/CAMA (MF)";
04666    case SIG_FXSLS:
04667       return "FXS Loopstart";
04668    case SIG_FXSGS:
04669       return "FXS Groundstart";
04670    case SIG_FXSKS:
04671       return "FXS Kewlstart";
04672    case SIG_FXOLS:
04673       return "FXO Loopstart";
04674    case SIG_FXOGS:
04675       return "FXO Groundstart";
04676    case SIG_FXOKS:
04677       return "FXO Kewlstart";
04678    case SIG_PRI:
04679       return "ISDN PRI";
04680    case SIG_BRI:
04681       return "ISDN BRI Point to Point";
04682    case SIG_BRI_PTMP:
04683       return "ISDN BRI Point to MultiPoint";
04684    case SIG_SS7:
04685       return "SS7";
04686    case SIG_MFCR2:
04687       return "MFC/R2";
04688    case SIG_SF:
04689       return "SF (Tone) Immediate";
04690    case SIG_SFWINK:
04691       return "SF (Tone) Wink";
04692    case SIG_SF_FEATD:
04693       return "SF (Tone) with Feature Group D (DTMF)";
04694    case SIG_SF_FEATDMF:
04695       return "SF (Tone) with Feature Group D (MF)";
04696    case SIG_SF_FEATB:
04697       return "SF (Tone) with Feature Group B (MF)";
04698    case 0:
04699       return "Pseudo";
04700    default:
04701       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04702       return buf;
04703    }
04704 }
04705 
04706 #define sig2str dahdi_sig2str
04707 
04708 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04709 {
04710    /* If the conference already exists, and we're already in it
04711       don't bother doing anything */
04712    struct dahdi_confinfo zi;
04713 
04714    memset(&zi, 0, sizeof(zi));
04715    zi.chan = 0;
04716 
04717    if (slavechannel > 0) {
04718       /* If we have only one slave, do a digital mon */
04719       zi.confmode = DAHDI_CONF_DIGITALMON;
04720       zi.confno = slavechannel;
04721    } else {
04722       if (!idx) {
04723          /* Real-side and pseudo-side both participate in conference */
04724          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04725             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04726       } else
04727          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04728       zi.confno = p->confno;
04729    }
04730    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04731       return 0;
04732    if (c->dfd < 0)
04733       return 0;
04734    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04735       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04736       return -1;
04737    }
04738    if (slavechannel < 1) {
04739       p->confno = zi.confno;
04740    }
04741    c->curconf = zi;
04742    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04743    return 0;
04744 }
04745 
04746 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04747 {
04748    /* If they're listening to our channel, they're ours */
04749    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04750       return 1;
04751    /* If they're a talker on our (allocated) conference, they're ours */
04752    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04753       return 1;
04754    return 0;
04755 }
04756 
04757 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04758 {
04759    struct dahdi_confinfo zi;
04760    if (/* Can't delete if there's no dfd */
04761       (c->dfd < 0) ||
04762       /* Don't delete from the conference if it's not our conference */
04763       !isourconf(p, c)
04764       /* Don't delete if we don't think it's conferenced at all (implied) */
04765       ) return 0;
04766    memset(&zi, 0, sizeof(zi));
04767    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04768       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04769       return -1;
04770    }
04771    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04772    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04773    return 0;
04774 }
04775 
04776 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04777 {
04778    int x;
04779    int useslavenative;
04780    struct dahdi_pvt *slave = NULL;
04781    /* Start out optimistic */
04782    useslavenative = 1;
04783    /* Update conference state in a stateless fashion */
04784    for (x = 0; x < 3; x++) {
04785       /* Any three-way calling makes slave native mode *definitely* out
04786          of the question */
04787       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04788          useslavenative = 0;
04789    }
04790    /* If we don't have any 3-way calls, check to see if we have
04791       precisely one slave */
04792    if (useslavenative) {
04793       for (x = 0; x < MAX_SLAVES; x++) {
04794          if (p->slaves[x]) {
04795             if (slave) {
04796                /* Whoops already have a slave!  No
04797                   slave native and stop right away */
04798                slave = NULL;
04799                useslavenative = 0;
04800                break;
04801             } else {
04802                /* We have one slave so far */
04803                slave = p->slaves[x];
04804             }
04805          }
04806       }
04807    }
04808    /* If no slave, slave native definitely out */
04809    if (!slave)
04810       useslavenative = 0;
04811    else if (slave->law != p->law) {
04812       useslavenative = 0;
04813       slave = NULL;
04814    }
04815    if (out)
04816       *out = slave;
04817    return useslavenative;
04818 }
04819 
04820 static int reset_conf(struct dahdi_pvt *p)
04821 {
04822    p->confno = -1;
04823    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04824    if (p->subs[SUB_REAL].dfd > -1) {
04825       struct dahdi_confinfo zi;
04826 
04827       memset(&zi, 0, sizeof(zi));
04828       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04829          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04830    }
04831    return 0;
04832 }
04833 
04834 static int update_conf(struct dahdi_pvt *p)
04835 {
04836    int needconf = 0;
04837    int x;
04838    int useslavenative;
04839    struct dahdi_pvt *slave = NULL;
04840 
04841    useslavenative = isslavenative(p, &slave);
04842    /* Start with the obvious, general stuff */
04843    for (x = 0; x < 3; x++) {
04844       /* Look for three way calls */
04845       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04846          conf_add(p, &p->subs[x], x, 0);
04847          needconf++;
04848       } else {
04849          conf_del(p, &p->subs[x], x);
04850       }
04851    }
04852    /* If we have a slave, add him to our conference now. or DAX
04853       if this is slave native */
04854    for (x = 0; x < MAX_SLAVES; x++) {
04855       if (p->slaves[x]) {
04856          if (useslavenative)
04857             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04858          else {
04859             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04860             needconf++;
04861          }
04862       }
04863    }
04864    /* If we're supposed to be in there, do so now */
04865    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04866       if (useslavenative)
04867          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04868       else {
04869          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04870          needconf++;
04871       }
04872    }
04873    /* If we have a master, add ourselves to his conference */
04874    if (p->master) {
04875       if (isslavenative(p->master, NULL)) {
04876          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04877       } else {
04878          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04879       }
04880    }
04881    if (!needconf) {
04882       /* Nobody is left (or should be left) in our conference.
04883          Kill it. */
04884       p->confno = -1;
04885    }
04886    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04887    return 0;
04888 }
04889 
04890 static void dahdi_enable_ec(struct dahdi_pvt *p)
04891 {
04892    int res;
04893    if (!p)
04894       return;
04895    if (p->echocanon) {
04896       ast_debug(1, "Echo cancellation already on\n");
04897       return;
04898    }
04899    if (p->digital) {
04900       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04901       return;
04902    }
04903    if (p->echocancel.head.tap_length) {
04904 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04905       switch (p->sig) {
04906 #if defined(HAVE_PRI)
04907       case SIG_PRI_LIB_HANDLE_CASES:
04908          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04909             /*
04910              * PRI nobch pseudo channel.  Does not need ec anyway.
04911              * Does not handle ioctl(DAHDI_AUDIOMODE)
04912              */
04913             return;
04914          }
04915          /* Fall through */
04916 #endif   /* defined(HAVE_PRI) */
04917 #if defined(HAVE_SS7)
04918       case SIG_SS7:
04919 #endif   /* defined(HAVE_SS7) */
04920          {
04921             int x = 1;
04922 
04923             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04924             if (res)
04925                ast_log(LOG_WARNING,
04926                   "Unable to enable audio mode on channel %d (%s)\n",
04927                   p->channel, strerror(errno));
04928          }
04929          break;
04930       default:
04931          break;
04932       }
04933 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04934       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04935       if (res) {
04936          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04937       } else {
04938          p->echocanon = 1;
04939          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04940       }
04941    } else
04942       ast_debug(1, "No echo cancellation requested\n");
04943 }
04944 
04945 static void dahdi_train_ec(struct dahdi_pvt *p)
04946 {
04947    int x;
04948    int res;
04949 
04950    if (p && p->echocanon && p->echotraining) {
04951       x = p->echotraining;
04952       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04953       if (res)
04954          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04955       else
04956          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04957    } else {
04958       ast_debug(1, "No echo training requested\n");
04959    }
04960 }
04961 
04962 static void dahdi_disable_ec(struct dahdi_pvt *p)
04963 {
04964    int res;
04965 
04966    if (p->echocanon) {
04967       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04968 
04969       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04970 
04971       if (res)
04972          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04973       else
04974          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04975    }
04976 
04977    p->echocanon = 0;
04978 }
04979 
04980 /* perform a dynamic range compression transform on the given sample */
04981 static int drc_sample(int sample, float drc)
04982 {
04983    float neg;
04984    float shallow, steep;
04985    float max = SHRT_MAX;
04986    
04987    neg = (sample < 0 ? -1 : 1);
04988    steep = drc*sample;
04989    shallow = neg*(max-max/drc)+(float)sample/drc;
04990    if (abs(steep) < abs(shallow)) {
04991       sample = steep;
04992    }
04993    else {
04994       sample = shallow;
04995    }
04996 
04997    return sample;
04998 }
04999 
05000 
05001 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05002 {
05003    int j;
05004    int k;
05005 
05006    float linear_gain = pow(10.0, gain / 20.0);
05007 
05008    switch (law) {
05009    case DAHDI_LAW_ALAW:
05010       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05011          if (gain || drc) {
05012             k = AST_ALAW(j);
05013             if (drc) {
05014                k = drc_sample(k, drc);
05015             }
05016             k = (float)k * linear_gain;
05017             if (k > 32767) {
05018                k = 32767;
05019             } else if (k < -32768) {
05020                k = -32768;
05021             }
05022             g->txgain[j] = AST_LIN2A(k);
05023          } else {
05024             g->txgain[j] = j;
05025          }
05026       }
05027       break;
05028    case DAHDI_LAW_MULAW:
05029       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05030          if (gain || drc) {
05031             k = AST_MULAW(j);
05032             if (drc) {
05033                k = drc_sample(k, drc);
05034             }
05035             k = (float)k * linear_gain;
05036             if (k > 32767) {
05037                k = 32767;
05038             } else if (k < -32768) {
05039                k = -32768;
05040             }
05041             g->txgain[j] = AST_LIN2MU(k);
05042 
05043          } else {
05044             g->txgain[j] = j;
05045          }
05046       }
05047       break;
05048    }
05049 }
05050 
05051 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05052 {
05053    int j;
05054    int k;
05055    float linear_gain = pow(10.0, gain / 20.0);
05056 
05057    switch (law) {
05058    case DAHDI_LAW_ALAW:
05059       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05060          if (gain || drc) {
05061             k = AST_ALAW(j);
05062             if (drc) {
05063                k = drc_sample(k, drc);
05064             }
05065             k = (float)k * linear_gain;
05066             if (k > 32767) {
05067                k = 32767;
05068             } else if (k < -32768) {
05069                k = -32768;
05070             }
05071             g->rxgain[j] = AST_LIN2A(k);
05072          } else {
05073             g->rxgain[j] = j;
05074          }
05075       }
05076       break;
05077    case DAHDI_LAW_MULAW:
05078       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05079          if (gain || drc) {
05080             k = AST_MULAW(j);
05081             if (drc) {
05082                k = drc_sample(k, drc);
05083             }
05084             k = (float)k * linear_gain;
05085             if (k > 32767) {
05086                k = 32767;
05087             } else if (k < -32768) {
05088                k = -32768;
05089             }
05090             g->rxgain[j] = AST_LIN2MU(k);
05091          } else {
05092             g->rxgain[j] = j;
05093          }
05094       }
05095       break;
05096    }
05097 }
05098 
05099 static int set_actual_txgain(int fd, float gain, float drc, int law)
05100 {
05101    struct dahdi_gains g;
05102    int res;
05103 
05104    memset(&g, 0, sizeof(g));
05105    res = ioctl(fd, DAHDI_GETGAINS, &g);
05106    if (res) {
05107       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05108       return res;
05109    }
05110 
05111    fill_txgain(&g, gain, drc, law);
05112 
05113    return ioctl(fd, DAHDI_SETGAINS, &g);
05114 }
05115 
05116 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05117 {
05118    struct dahdi_gains g;
05119    int res;
05120 
05121    memset(&g, 0, sizeof(g));
05122    res = ioctl(fd, DAHDI_GETGAINS, &g);
05123    if (res) {
05124       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05125       return res;
05126    }
05127 
05128    fill_rxgain(&g, gain, drc, law);
05129 
05130    return ioctl(fd, DAHDI_SETGAINS, &g);
05131 }
05132 
05133 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05134 {
05135    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05136 }
05137 
05138 static int bump_gains(struct dahdi_pvt *p)
05139 {
05140    int res;
05141 
05142    /* Bump receive gain by value stored in cid_rxgain */
05143    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05144    if (res) {
05145       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05146       return -1;
05147    }
05148 
05149    return 0;
05150 }
05151 
05152 static int restore_gains(struct dahdi_pvt *p)
05153 {
05154    int res;
05155 
05156    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05157    if (res) {
05158       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05159       return -1;
05160    }
05161 
05162    return 0;
05163 }
05164 
05165 static inline int dahdi_set_hook(int fd, int hs)
05166 {
05167    int x, res;
05168 
05169    x = hs;
05170    res = ioctl(fd, DAHDI_HOOK, &x);
05171 
05172    if (res < 0) {
05173       if (errno == EINPROGRESS)
05174          return 0;
05175       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05176       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05177    }
05178 
05179    return res;
05180 }
05181 
05182 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05183 {
05184    int x, res;
05185 
05186    x = muted;
05187 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05188    switch (p->sig) {
05189 #if defined(HAVE_PRI)
05190    case SIG_PRI_LIB_HANDLE_CASES:
05191       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05192          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05193          break;
05194       }
05195       /* Fall through */
05196 #endif   /* defined(HAVE_PRI) */
05197 #if defined(HAVE_SS7)
05198    case SIG_SS7:
05199 #endif   /* defined(HAVE_SS7) */
05200       {
05201          int y = 1;
05202 
05203          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05204          if (res)
05205             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05206                p->channel, strerror(errno));
05207       }
05208       break;
05209    default:
05210       break;
05211    }
05212 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05213    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05214    if (res < 0)
05215       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05216    return res;
05217 }
05218 
05219 static int save_conference(struct dahdi_pvt *p)
05220 {
05221    struct dahdi_confinfo c;
05222    int res;
05223    if (p->saveconf.confmode) {
05224       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05225       return -1;
05226    }
05227    p->saveconf.chan = 0;
05228    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05229    if (res) {
05230       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05231       p->saveconf.confmode = 0;
05232       return -1;
05233    }
05234    memset(&c, 0, sizeof(c));
05235    c.confmode = DAHDI_CONF_NORMAL;
05236    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05237    if (res) {
05238       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05239       return -1;
05240    }
05241    ast_debug(1, "Disabled conferencing\n");
05242    return 0;
05243 }
05244 
05245 static int restore_conference(struct dahdi_pvt *p)
05246 {
05247    int res;
05248    if (p->saveconf.confmode) {
05249       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05250       p->saveconf.confmode = 0;
05251       if (res) {
05252          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05253          return -1;
05254       }
05255       ast_debug(1, "Restored conferencing\n");
05256    }
05257    return 0;
05258 }
05259 
05260 static int send_cwcidspill(struct dahdi_pvt *p)
05261 {
05262    p->callwaitcas = 0;
05263    p->cidcwexpire = 0;
05264    p->cid_suppress_expire = 0;
05265    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05266       return -1;
05267    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05268    /* Make sure we account for the end */
05269    p->cidlen += READ_SIZE * 4;
05270    p->cidpos = 0;
05271    send_callerid(p);
05272    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05273    return 0;
05274 }
05275 
05276 static int has_voicemail(struct dahdi_pvt *p)
05277 {
05278    int new_msgs;
05279    struct ast_event *event;
05280    char *mailbox, *context;
05281 
05282    mailbox = context = ast_strdupa(p->mailbox);
05283    strsep(&context, "@");
05284    if (ast_strlen_zero(context))
05285       context = "default";
05286 
05287    event = ast_event_get_cached(AST_EVENT_MWI,
05288       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05289       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05290       AST_EVENT_IE_END);
05291 
05292    if (event) {
05293       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05294       ast_event_destroy(event);
05295    } else
05296       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05297 
05298    return new_msgs;
05299 }
05300 
05301 
05302 
05303 static int send_callerid(struct dahdi_pvt *p)
05304 {
05305    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05306    int res;
05307    /* Take out of linear mode if necessary */
05308    if (p->subs[SUB_REAL].linear) {
05309       p->subs[SUB_REAL].linear = 0;
05310       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05311    }
05312    while (p->cidpos < p->cidlen) {
05313       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05314       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05315       if (res < 0) {
05316          if (errno == EAGAIN)
05317             return 0;
05318          else {
05319             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05320             return -1;
05321          }
05322       }
05323       if (!res)
05324          return 0;
05325       p->cidpos += res;
05326    }
05327    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05328    ast_free(p->cidspill);
05329    p->cidspill = NULL;
05330    if (p->callwaitcas) {
05331       /* Wait for CID/CW to expire */
05332       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05333       p->cid_suppress_expire = p->cidcwexpire;
05334    } else
05335       restore_conference(p);
05336    return 0;
05337 }
05338 
05339 static int dahdi_callwait(struct ast_channel *ast)
05340 {
05341    struct dahdi_pvt *p = ast->tech_pvt;
05342    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05343    if (p->cidspill) {
05344       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05345       ast_free(p->cidspill);
05346    }
05347 
05348    /*
05349     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05350     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05351     */
05352    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05353       return -1;
05354    save_conference(p);
05355    /* Silence */
05356    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05357    if (!p->callwaitrings && p->callwaitingcallerid) {
05358       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05359       p->callwaitcas = 1;
05360       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05361    } else {
05362       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05363       p->callwaitcas = 0;
05364       p->cidlen = 2400 + READ_SIZE * 4;
05365    }
05366    p->cidpos = 0;
05367    send_callerid(p);
05368 
05369    return 0;
05370 }
05371 
05372 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05373 {
05374    struct dahdi_pvt *p = ast->tech_pvt;
05375    int x, res, mysig;
05376    char dest[256]; /* must be same length as p->dialdest */
05377 
05378    ast_mutex_lock(&p->lock);
05379    ast_copy_string(dest, rdest, sizeof(dest));
05380    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05381    if ((ast->_state == AST_STATE_BUSY)) {
05382       p->subs[SUB_REAL].needbusy = 1;
05383       ast_mutex_unlock(&p->lock);
05384       return 0;
05385    }
05386    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05387       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05388       ast_mutex_unlock(&p->lock);
05389       return -1;
05390    }
05391    p->waitingfordt.tv_sec = 0;
05392    p->dialednone = 0;
05393    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05394    {
05395       /* Special pseudo -- automatically up */
05396       ast_setstate(ast, AST_STATE_UP);
05397       ast_mutex_unlock(&p->lock);
05398       return 0;
05399    }
05400    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05401    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05402    if (res)
05403       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05404    p->outgoing = 1;
05405 
05406    if (IS_DIGITAL(ast->transfercapability)){
05407       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05408    } else {
05409       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05410    }  
05411 
05412 #ifdef HAVE_PRI
05413    if (dahdi_sig_pri_lib_handles(p->sig)) {
05414       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05415          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05416       ast_mutex_unlock(&p->lock);
05417       return res;
05418    }
05419 #endif
05420 
05421 #if defined(HAVE_SS7)
05422    if (p->sig == SIG_SS7) {
05423       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05424       ast_mutex_unlock(&p->lock);
05425       return res;
05426    }
05427 #endif   /* defined(HAVE_SS7) */
05428 
05429    /* If this is analog signalling we can exit here */
05430    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05431       p->callwaitrings = 0;
05432       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05433       ast_mutex_unlock(&p->lock);
05434       return res;
05435    }
05436 
05437    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05438    switch (mysig) {
05439    case 0:
05440       /* Special pseudo -- automatically up*/
05441       ast_setstate(ast, AST_STATE_UP);
05442       break;
05443    case SIG_MFCR2:
05444       break;
05445    default:
05446       ast_debug(1, "not yet implemented\n");
05447       ast_mutex_unlock(&p->lock);
05448       return -1;
05449    }
05450 
05451 #ifdef HAVE_OPENR2
05452    if (p->mfcr2) {
05453       openr2_calling_party_category_t chancat;
05454       int callres = 0;
05455       char *c, *l;
05456 
05457       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05458       p->dialdest[0] = '\0';
05459 
05460       c = strchr(dest, '/');
05461       if (c) {
05462          c++;
05463       } else {
05464          c = "";
05465       }
05466       if (!p->hidecallerid) {
05467          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05468       } else {
05469          l = NULL;
05470       }
05471       if (strlen(c) < p->stripmsd) {
05472          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05473          ast_mutex_unlock(&p->lock);
05474          return -1;
05475       }
05476       p->dialing = 1;
05477       chancat = dahdi_r2_get_channel_category(ast);
05478       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05479       if (-1 == callres) {
05480          ast_mutex_unlock(&p->lock);
05481          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05482          return -1;
05483       }
05484       p->mfcr2_call_accepted = 0;
05485       p->mfcr2_progress = 0;
05486       ast_setstate(ast, AST_STATE_DIALING);
05487    }
05488 #endif /* HAVE_OPENR2 */
05489    ast_mutex_unlock(&p->lock);
05490    return 0;
05491 }
05492 
05493 /*!
05494  * \internal
05495  * \brief Insert the given chan_dahdi interface structure into the interface list.
05496  * \since 1.8
05497  *
05498  * \param pvt chan_dahdi private interface structure to insert.
05499  *
05500  * \details
05501  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05502  * Any duplicates are inserted after the existing entries.
05503  *
05504  * \note The new interface must not already be in the list.
05505  *
05506  * \return Nothing
05507  */
05508 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05509 {
05510    struct dahdi_pvt *cur;
05511 
05512    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05513 
05514    /* Find place in middle of list for the new interface. */
05515    for (cur = iflist; cur; cur = cur->next) {
05516       if (pvt->channel < cur->channel) {
05517          /* New interface goes before the current interface. */
05518          pvt->prev = cur->prev;
05519          pvt->next = cur;
05520          if (cur->prev) {
05521             /* Insert into the middle of the list. */
05522             cur->prev->next = pvt;
05523          } else {
05524             /* Insert at head of list. */
05525             iflist = pvt;
05526          }
05527          cur->prev = pvt;
05528          return;
05529       }
05530    }
05531 
05532    /* New interface goes onto the end of the list */
05533    pvt->prev = ifend;
05534    pvt->next = NULL;
05535    if (ifend) {
05536       ifend->next = pvt;
05537    }
05538    ifend = pvt;
05539    if (!iflist) {
05540       /* List was empty */
05541       iflist = pvt;
05542    }
05543 }
05544 
05545 /*!
05546  * \internal
05547  * \brief Extract the given chan_dahdi interface structure from the interface list.
05548  * \since 1.8
05549  *
05550  * \param pvt chan_dahdi private interface structure to extract.
05551  *
05552  * \note
05553  * The given interface structure can be either in the interface list or a stand alone
05554  * structure that has not been put in the list if the next and prev pointers are NULL.
05555  *
05556  * \return Nothing
05557  */
05558 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05559 {
05560    /* Extract from the forward chain. */
05561    if (pvt->prev) {
05562       pvt->prev->next = pvt->next;
05563    } else if (iflist == pvt) {
05564       /* Node is at the head of the list. */
05565       iflist = pvt->next;
05566    }
05567 
05568    /* Extract from the reverse chain. */
05569    if (pvt->next) {
05570       pvt->next->prev = pvt->prev;
05571    } else if (ifend == pvt) {
05572       /* Node is at the end of the list. */
05573       ifend = pvt->prev;
05574    }
05575 
05576    /* Node is no longer in the list. */
05577    pvt->which_iflist = DAHDI_IFLIST_NONE;
05578    pvt->prev = NULL;
05579    pvt->next = NULL;
05580 }
05581 
05582 #if defined(HAVE_PRI)
05583 /*!
05584  * \internal
05585  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05586  * \since 1.8
05587  *
05588  * \param pri sig_pri span control structure holding no B channel list.
05589  * \param pvt chan_dahdi private interface structure to insert.
05590  *
05591  * \details
05592  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05593  * Any duplicates are inserted after the existing entries.
05594  *
05595  * \note The new interface must not already be in the list.
05596  *
05597  * \return Nothing
05598  */
05599 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05600 {
05601    struct dahdi_pvt *cur;
05602 
05603    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05604 
05605    /* Find place in middle of list for the new interface. */
05606    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05607       if (pvt->channel < cur->channel) {
05608          /* New interface goes before the current interface. */
05609          pvt->prev = cur->prev;
05610          pvt->next = cur;
05611          if (cur->prev) {
05612             /* Insert into the middle of the list. */
05613             cur->prev->next = pvt;
05614          } else {
05615             /* Insert at head of list. */
05616             pri->no_b_chan_iflist = pvt;
05617          }
05618          cur->prev = pvt;
05619          return;
05620       }
05621    }
05622 
05623    /* New interface goes onto the end of the list */
05624    pvt->prev = pri->no_b_chan_end;
05625    pvt->next = NULL;
05626    if (pri->no_b_chan_end) {
05627       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05628    }
05629    pri->no_b_chan_end = pvt;
05630    if (!pri->no_b_chan_iflist) {
05631       /* List was empty */
05632       pri->no_b_chan_iflist = pvt;
05633    }
05634 }
05635 #endif   /* defined(HAVE_PRI) */
05636 
05637 #if defined(HAVE_PRI)
05638 /*!
05639  * \internal
05640  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05641  * \since 1.8
05642  *
05643  * \param pri sig_pri span control structure holding no B channel list.
05644  * \param pvt chan_dahdi private interface structure to extract.
05645  *
05646  * \note
05647  * The given interface structure can be either in the interface list or a stand alone
05648  * structure that has not been put in the list if the next and prev pointers are NULL.
05649  *
05650  * \return Nothing
05651  */
05652 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05653 {
05654    /* Extract from the forward chain. */
05655    if (pvt->prev) {
05656       pvt->prev->next = pvt->next;
05657    } else if (pri->no_b_chan_iflist == pvt) {
05658       /* Node is at the head of the list. */
05659       pri->no_b_chan_iflist = pvt->next;
05660    }
05661 
05662    /* Extract from the reverse chain. */
05663    if (pvt->next) {
05664       pvt->next->prev = pvt->prev;
05665    } else if (pri->no_b_chan_end == pvt) {
05666       /* Node is at the end of the list. */
05667       pri->no_b_chan_end = pvt->prev;
05668    }
05669 
05670    /* Node is no longer in the list. */
05671    pvt->which_iflist = DAHDI_IFLIST_NONE;
05672    pvt->prev = NULL;
05673    pvt->next = NULL;
05674 }
05675 #endif   /* defined(HAVE_PRI) */
05676 
05677 #if defined(HAVE_PRI)
05678 /*!
05679  * \internal
05680  * \brief Unlink the channel interface from the PRI private pointer array.
05681  * \since 1.8
05682  *
05683  * \param pvt chan_dahdi private interface structure to unlink.
05684  *
05685  * \return Nothing
05686  */
05687 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05688 {
05689    unsigned idx;
05690    struct sig_pri_span *pri;
05691 
05692    pri = pvt->pri;
05693    if (!pri) {
05694       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05695       return;
05696    }
05697    ast_mutex_lock(&pri->lock);
05698    for (idx = 0; idx < pri->numchans; ++idx) {
05699       if (pri->pvts[idx] == pvt->sig_pvt) {
05700          pri->pvts[idx] = NULL;
05701          ast_mutex_unlock(&pri->lock);
05702          return;
05703       }
05704    }
05705    ast_mutex_unlock(&pri->lock);
05706 }
05707 #endif   /* defined(HAVE_PRI) */
05708 
05709 #if defined(HAVE_SS7)
05710 /*!
05711  * \internal
05712  * \brief Unlink the channel interface from the SS7 private pointer array.
05713  * \since 1.8
05714  *
05715  * \param pvt chan_dahdi private interface structure to unlink.
05716  *
05717  * \return Nothing
05718  */
05719 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05720 {
05721    unsigned idx;
05722    struct sig_ss7_linkset *ss7;
05723 
05724    ss7 = pvt->ss7;
05725    if (!ss7) {
05726       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05727       return;
05728    }
05729    ast_mutex_lock(&ss7->lock);
05730    for (idx = 0; idx < ss7->numchans; ++idx) {
05731       if (ss7->pvts[idx] == pvt->sig_pvt) {
05732          ss7->pvts[idx] = NULL;
05733          ast_mutex_unlock(&ss7->lock);
05734          return;
05735       }
05736    }
05737    ast_mutex_unlock(&ss7->lock);
05738 }
05739 #endif   /* defined(HAVE_SS7) */
05740 
05741 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05742 {
05743    if (cur->next && cur->next->span == cur->span) {
05744       return cur->next;
05745    } else if (cur->prev && cur->prev->span == cur->span) {
05746       return cur->prev;
05747    }
05748 
05749    return NULL;
05750 }
05751 
05752 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05753 {
05754    struct dahdi_pvt *p = pvt;
05755 
05756    if (p->manages_span_alarms) {
05757       struct dahdi_pvt *next = find_next_iface_in_span(p);
05758       if (next) {
05759          next->manages_span_alarms = 1;
05760       }
05761    }
05762 
05763    /* Remove channel from the list */
05764 #if defined(HAVE_PRI)
05765    dahdi_unlink_pri_pvt(p);
05766 #endif   /* defined(HAVE_PRI) */
05767 #if defined(HAVE_SS7)
05768    dahdi_unlink_ss7_pvt(p);
05769 #endif   /* defined(HAVE_SS7) */
05770    switch (pvt->which_iflist) {
05771    case DAHDI_IFLIST_NONE:
05772       break;
05773    case DAHDI_IFLIST_MAIN:
05774       dahdi_iflist_extract(p);
05775       break;
05776 #if defined(HAVE_PRI)
05777    case DAHDI_IFLIST_NO_B_CHAN:
05778       if (p->pri) {
05779          dahdi_nobch_extract(p->pri, p);
05780       }
05781       break;
05782 #endif   /* defined(HAVE_PRI) */
05783    }
05784 
05785    if (p->sig_pvt) {
05786       if (analog_lib_handles(p->sig, 0, 0)) {
05787          analog_delete(p->sig_pvt);
05788       }
05789       switch (p->sig) {
05790 #if defined(HAVE_PRI)
05791       case SIG_PRI_LIB_HANDLE_CASES:
05792          sig_pri_chan_delete(p->sig_pvt);
05793          break;
05794 #endif   /* defined(HAVE_PRI) */
05795 #if defined(HAVE_SS7)
05796       case SIG_SS7:
05797          sig_ss7_chan_delete(p->sig_pvt);
05798          break;
05799 #endif   /* defined(HAVE_SS7) */
05800       default:
05801          break;
05802       }
05803    }
05804    ast_free(p->cidspill);
05805    if (p->use_smdi)
05806       ast_smdi_interface_unref(p->smdi_iface);
05807    if (p->mwi_event_sub)
05808       ast_event_unsubscribe(p->mwi_event_sub);
05809    if (p->vars) {
05810       ast_variables_destroy(p->vars);
05811    }
05812    if (p->cc_params) {
05813       ast_cc_config_params_destroy(p->cc_params);
05814    }
05815    ast_mutex_destroy(&p->lock);
05816    dahdi_close_sub(p, SUB_REAL);
05817    if (p->owner)
05818       p->owner->tech_pvt = NULL;
05819    ast_free(p);
05820 }
05821 
05822 static void destroy_channel(struct dahdi_pvt *cur, int now)
05823 {
05824    int i;
05825 
05826    if (!now) {
05827       /* Do not destroy the channel now if it is owned by someone. */
05828       if (cur->owner) {
05829          return;
05830       }
05831       for (i = 0; i < 3; i++) {
05832          if (cur->subs[i].owner) {
05833             return;
05834          }
05835       }
05836    }
05837    destroy_dahdi_pvt(cur);
05838 }
05839 
05840 static void destroy_all_channels(void)
05841 {
05842    int chan;
05843 #if defined(HAVE_PRI)
05844    unsigned span;
05845    struct sig_pri_span *pri;
05846 #endif   /* defined(HAVE_PRI) */
05847    struct dahdi_pvt *p;
05848 
05849    while (num_restart_pending) {
05850       usleep(1);
05851    }
05852 
05853    ast_mutex_lock(&iflock);
05854    /* Destroy all the interfaces and free their memory */
05855    while (iflist) {
05856       p = iflist;
05857 
05858       chan = p->channel;
05859 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05860       {
05861          char db_chan_name[20];
05862          char db_answer[5];
05863          char state;
05864          int why = -1;
05865 
05866          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05867          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05868             sscanf(db_answer, "%1c:%30d", &state, &why);
05869          }
05870          if (!why) {
05871             /* SRVST persistence is not required */
05872             ast_db_del(db_chan_name, SRVST_DBKEY);
05873          }
05874       }
05875 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05876       /* Free associated memory */
05877       destroy_dahdi_pvt(p);
05878       ast_verb(3, "Unregistered channel %d\n", chan);
05879    }
05880    ifcount = 0;
05881    ast_mutex_unlock(&iflock);
05882 
05883 #if defined(HAVE_PRI)
05884    /* Destroy all of the no B channel interface lists */
05885    for (span = 0; span < NUM_SPANS; ++span) {
05886       if (!pris[span].dchannels[0]) {
05887          break;
05888       }
05889       pri = &pris[span].pri;
05890       ast_mutex_lock(&pri->lock);
05891       while (pri->no_b_chan_iflist) {
05892          p = pri->no_b_chan_iflist;
05893 
05894          /* Free associated memory */
05895          destroy_dahdi_pvt(p);
05896       }
05897       ast_mutex_unlock(&pri->lock);
05898    }
05899 #endif   /* defined(HAVE_PRI) */
05900 }
05901 
05902 #if defined(HAVE_PRI)
05903 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05904 
05905 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05906 {
05907    /* Data will be our digit string */
05908    struct dahdi_pvt *p;
05909 
05910    if (ast_strlen_zero(digits)) {
05911       ast_debug(1, "No digit string sent to application!\n");
05912       return -1;
05913    }
05914 
05915    p = (struct dahdi_pvt *)chan->tech_pvt;
05916 
05917    if (!p) {
05918       ast_debug(1, "Unable to find technology private\n");
05919       return -1;
05920    }
05921 
05922    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05923 
05924    return 0;
05925 }
05926 #endif   /* defined(HAVE_PRI) */
05927 
05928 #if defined(HAVE_PRI)
05929 #if defined(HAVE_PRI_PROG_W_CAUSE)
05930 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05931 
05932 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05933 {
05934    /* Data will be our digit string */
05935    struct dahdi_pvt *pvt;
05936    char *parse;
05937    int res;
05938    AST_DECLARE_APP_ARGS(args,
05939       AST_APP_ARG(destination);
05940       AST_APP_ARG(original);
05941       AST_APP_ARG(reason);
05942    );
05943 
05944    if (ast_strlen_zero(data)) {
05945       ast_log(LOG_DEBUG, "No data sent to application!\n");
05946       return -1;
05947    }
05948    if (chan->tech != &dahdi_tech) {
05949       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05950       return -1;
05951    }
05952    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05953    if (!pvt) {
05954       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05955       return -1;
05956    }
05957    switch (pvt->sig) {
05958    case SIG_PRI_LIB_HANDLE_CASES:
05959       break;
05960    default:
05961       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05962          chan->name);
05963       return -1;
05964    }
05965 
05966    parse = ast_strdupa(data);
05967    AST_STANDARD_APP_ARGS(args, parse);
05968 
05969    if (ast_strlen_zero(args.destination)) {
05970       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05971       return -1;
05972    }
05973 
05974    if (ast_strlen_zero(args.original)) {
05975       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05976       args.original = NULL;
05977    }
05978 
05979    if (ast_strlen_zero(args.reason)) {
05980       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05981       args.reason = NULL;
05982    }
05983 
05984    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05985       args.destination, args.original, args.reason);
05986    if (!res) {
05987       /*
05988        * Wait up to 5 seconds for a reply before hanging up this call
05989        * leg if the peer does not disconnect first.
05990        */
05991       ast_safe_sleep(chan, 5000);
05992    }
05993 
05994    return -1;
05995 }
05996 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05997 #endif   /* defined(HAVE_PRI) */
05998 
05999 #if defined(HAVE_OPENR2)
06000 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06001 
06002 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06003 {
06004    /* data is whether to accept with charge or no charge */
06005    openr2_call_mode_t accept_mode;
06006    int res, timeout, maxloops;
06007    struct ast_frame *f;
06008    struct dahdi_pvt *p;
06009    char *parse;
06010    AST_DECLARE_APP_ARGS(args,
06011          AST_APP_ARG(charge);
06012    );
06013 
06014    if (ast_strlen_zero(data)) {
06015       ast_log(LOG_DEBUG, "No data sent to application!\n");
06016       return -1;
06017    }
06018 
06019    if (chan->tech != &dahdi_tech) {
06020       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06021       return -1;
06022    }
06023 
06024    p = (struct dahdi_pvt *)chan->tech_pvt;
06025    if (!p) {
06026       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06027       return -1;
06028    }
06029 
06030    parse = ast_strdupa(data);
06031    AST_STANDARD_APP_ARGS(args, parse);
06032 
06033    if (ast_strlen_zero(args.charge)) {
06034       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06035       return -1;
06036    }
06037 
06038    ast_mutex_lock(&p->lock);
06039    if (!p->mfcr2 || !p->mfcr2call) {
06040       ast_mutex_unlock(&p->lock);
06041       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06042       return -1;
06043    }
06044 
06045    if (p->mfcr2_call_accepted) {
06046       ast_mutex_unlock(&p->lock);
06047       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06048       return 0;
06049    }
06050    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06051    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06052       ast_mutex_unlock(&p->lock);
06053       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06054       return -1;
06055    }
06056    ast_mutex_unlock(&p->lock);
06057 
06058    res = 0;
06059    timeout = 100;
06060    maxloops = 50; /* wait up to 5 seconds */
06061    /* we need to read() until the call is accepted */
06062    while (maxloops > 0) {
06063       maxloops--;
06064       if (ast_check_hangup(chan)) {
06065          break;
06066       }
06067       res = ast_waitfor(chan, timeout);
06068       if (res < 0) {
06069          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06070          res = -1;
06071          break;
06072       }
06073       if (res == 0) {
06074          continue;
06075       }
06076       res = 0;
06077       f = ast_read(chan);
06078       if (!f) {
06079          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06080          res = -1;
06081          break;
06082       }
06083       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06084          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06085          ast_frfree(f);
06086          res = -1;
06087          break;
06088       }
06089       ast_frfree(f);
06090       ast_mutex_lock(&p->lock);
06091       if (p->mfcr2_call_accepted) {
06092          ast_mutex_unlock(&p->lock);
06093          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06094          break;
06095       }
06096       ast_mutex_unlock(&p->lock);
06097    }
06098    if (res == -1) {
06099       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06100    }
06101    return res;
06102 }
06103 
06104 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06105 {
06106    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06107    switch (cause) {
06108    case AST_CAUSE_USER_BUSY:
06109    case AST_CAUSE_CALL_REJECTED:
06110    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06111       r2cause = OR2_CAUSE_BUSY_NUMBER;
06112       break;
06113 
06114    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06115    case AST_CAUSE_SWITCH_CONGESTION:
06116       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06117       break;
06118 
06119    case AST_CAUSE_UNALLOCATED:
06120       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06121       break;
06122 
06123    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06124    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06125       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06126       break;
06127 
06128    case AST_CAUSE_NO_ANSWER:
06129    case AST_CAUSE_NO_USER_RESPONSE:
06130       r2cause = OR2_CAUSE_NO_ANSWER;
06131       break;
06132 
06133    default:
06134       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06135       break;
06136    }
06137    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06138          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06139    return r2cause;
06140 }
06141 #endif
06142 
06143 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06144 {
06145    if (p->bufferoverrideinuse) {
06146       /* faxbuffers are in use, revert them */
06147       struct dahdi_bufferinfo bi = {
06148          .txbufpolicy = p->buf_policy,
06149          .rxbufpolicy = p->buf_policy,
06150          .bufsize = p->bufsize,
06151          .numbufs = p->buf_no
06152       };
06153       int bpres;
06154 
06155       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06156          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06157       }
06158       p->bufferoverrideinuse = 0;
06159       return bpres;
06160    }
06161 
06162    return -1;
06163 }
06164 
06165 static int dahdi_hangup(struct ast_channel *ast)
06166 {
06167    int res = 0;
06168    int idx,x;
06169    int law;
06170    /*static int restore_gains(struct dahdi_pvt *p);*/
06171    struct dahdi_pvt *p = ast->tech_pvt;
06172    struct dahdi_params par;
06173 
06174    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06175    if (!ast->tech_pvt) {
06176       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06177       return 0;
06178    }
06179 
06180    ast_mutex_lock(&p->lock);
06181    p->exten[0] = '\0';
06182    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06183       dahdi_confmute(p, 0);
06184       restore_gains(p);
06185       p->ignoredtmf = 0;
06186       p->waitingfordt.tv_sec = 0;
06187 
06188       res = analog_hangup(p->sig_pvt, ast);
06189       revert_fax_buffers(p, ast);
06190 
06191       goto hangup_out;
06192    } else {
06193       p->cid_num[0] = '\0';
06194       p->cid_name[0] = '\0';
06195       p->cid_subaddr[0] = '\0';
06196    }
06197 
06198 #if defined(HAVE_PRI)
06199    if (dahdi_sig_pri_lib_handles(p->sig)) {
06200       x = 1;
06201       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06202 
06203       dahdi_confmute(p, 0);
06204       p->muting = 0;
06205       restore_gains(p);
06206       if (p->dsp) {
06207          ast_dsp_free(p->dsp);
06208          p->dsp = NULL;
06209       }
06210       p->ignoredtmf = 0;
06211 
06212       /* Real channel, do some fixup */
06213       p->subs[SUB_REAL].owner = NULL;
06214       p->subs[SUB_REAL].needbusy = 0;
06215       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06216 
06217       p->owner = NULL;
06218       p->cid_tag[0] = '\0';
06219       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06220       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06221       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06222       p->outgoing = 0;
06223       p->digital = 0;
06224       p->faxhandled = 0;
06225       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06226 
06227       revert_fax_buffers(p, ast);
06228 
06229       p->law = p->law_default;
06230       law = p->law_default;
06231       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06232       if (res < 0) {
06233          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06234             p->channel, strerror(errno));
06235       }
06236 
06237       sig_pri_hangup(p->sig_pvt, ast);
06238 
06239       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06240       dahdi_disable_ec(p);
06241 
06242       x = 0;
06243       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06244       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06245 
06246       p->rdnis[0] = '\0';
06247       update_conf(p);
06248       reset_conf(p);
06249 
06250       /* Restore data mode */
06251       x = 0;
06252       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06253 
06254       if (num_restart_pending == 0) {
06255          restart_monitor();
06256       }
06257       goto hangup_out;
06258    }
06259 #endif   /* defined(HAVE_PRI) */
06260 
06261 #if defined(HAVE_SS7)
06262    if (p->sig == SIG_SS7) {
06263       x = 1;
06264       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06265 
06266       dahdi_confmute(p, 0);
06267       p->muting = 0;
06268       restore_gains(p);
06269       if (p->dsp) {
06270          ast_dsp_free(p->dsp);
06271          p->dsp = NULL;
06272       }
06273       p->ignoredtmf = 0;
06274 
06275       /* Real channel, do some fixup */
06276       p->subs[SUB_REAL].owner = NULL;
06277       p->subs[SUB_REAL].needbusy = 0;
06278       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06279 
06280       p->owner = NULL;
06281       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06282       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06283       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06284       p->outgoing = 0;
06285       p->digital = 0;
06286       p->faxhandled = 0;
06287       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06288 
06289       revert_fax_buffers(p, ast);
06290 
06291       p->law = p->law_default;
06292       law = p->law_default;
06293       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06294       if (res < 0) {
06295          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06296             p->channel, strerror(errno));
06297       }
06298 
06299       sig_ss7_hangup(p->sig_pvt, ast);
06300 
06301       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06302       dahdi_disable_ec(p);
06303 
06304       x = 0;
06305       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06306       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06307 
06308       update_conf(p);
06309       reset_conf(p);
06310 
06311       /* Restore data mode */
06312       x = 0;
06313       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06314 
06315       if (num_restart_pending == 0) {
06316          restart_monitor();
06317       }
06318       goto hangup_out;
06319    }
06320 #endif   /* defined(HAVE_SS7) */
06321 
06322    idx = dahdi_get_index(ast, p, 1);
06323 
06324    dahdi_confmute(p, 0);
06325    p->muting = 0;
06326    restore_gains(p);
06327    if (p->origcid_num) {
06328       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06329       ast_free(p->origcid_num);
06330       p->origcid_num = NULL;
06331    }
06332    if (p->origcid_name) {
06333       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06334       ast_free(p->origcid_name);
06335       p->origcid_name = NULL;
06336    }
06337    if (p->dsp)
06338       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06339 
06340    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06341       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06342    p->ignoredtmf = 0;
06343 
06344    if (idx > -1) {
06345       /* Real channel, do some fixup */
06346       p->subs[idx].owner = NULL;
06347       p->subs[idx].needanswer = 0;
06348       p->subs[idx].needflash = 0;
06349       p->subs[idx].needringing = 0;
06350       p->subs[idx].needbusy = 0;
06351       p->subs[idx].needcongestion = 0;
06352       p->subs[idx].linear = 0;
06353       p->polarity = POLARITY_IDLE;
06354       dahdi_setlinear(p->subs[idx].dfd, 0);
06355       if (idx == SUB_REAL) {
06356          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06357             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06358             if (p->subs[SUB_CALLWAIT].inthreeway) {
06359                /* We had flipped over to answer a callwait and now it's gone */
06360                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06361                /* Move to the call-wait, but un-own us until they flip back. */
06362                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06363                unalloc_sub(p, SUB_CALLWAIT);
06364                p->owner = NULL;
06365             } else {
06366                /* The three way hung up, but we still have a call wait */
06367                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06368                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06369                unalloc_sub(p, SUB_THREEWAY);
06370                if (p->subs[SUB_REAL].inthreeway) {
06371                   /* This was part of a three way call.  Immediately make way for
06372                      another call */
06373                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06374                   p->owner = p->subs[SUB_REAL].owner;
06375                } else {
06376                   /* This call hasn't been completed yet...  Set owner to NULL */
06377                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06378                   p->owner = NULL;
06379                }
06380                p->subs[SUB_REAL].inthreeway = 0;
06381             }
06382          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06383             /* Move to the call-wait and switch back to them. */
06384             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06385             unalloc_sub(p, SUB_CALLWAIT);
06386             p->owner = p->subs[SUB_REAL].owner;
06387             if (p->owner->_state != AST_STATE_UP)
06388                p->subs[SUB_REAL].needanswer = 1;
06389             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06390                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06391          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06392             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06393             unalloc_sub(p, SUB_THREEWAY);
06394             if (p->subs[SUB_REAL].inthreeway) {
06395                /* This was part of a three way call.  Immediately make way for
06396                   another call */
06397                ast_debug(1, "Call was complete, setting owner to former third call\n");
06398                p->owner = p->subs[SUB_REAL].owner;
06399             } else {
06400                /* This call hasn't been completed yet...  Set owner to NULL */
06401                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06402                p->owner = NULL;
06403             }
06404             p->subs[SUB_REAL].inthreeway = 0;
06405          }
06406       } else if (idx == SUB_CALLWAIT) {
06407          /* Ditch the holding callwait call, and immediately make it availabe */
06408          if (p->subs[SUB_CALLWAIT].inthreeway) {
06409             /* This is actually part of a three way, placed on hold.  Place the third part
06410                on music on hold now */
06411             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06412                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06413                   S_OR(p->mohsuggest, NULL),
06414                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06415             }
06416             p->subs[SUB_THREEWAY].inthreeway = 0;
06417             /* Make it the call wait now */
06418             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06419             unalloc_sub(p, SUB_THREEWAY);
06420          } else
06421             unalloc_sub(p, SUB_CALLWAIT);
06422       } else if (idx == SUB_THREEWAY) {
06423          if (p->subs[SUB_CALLWAIT].inthreeway) {
06424             /* The other party of the three way call is currently in a call-wait state.
06425                Start music on hold for them, and take the main guy out of the third call */
06426             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06427                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06428                   S_OR(p->mohsuggest, NULL),
06429                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06430             }
06431             p->subs[SUB_CALLWAIT].inthreeway = 0;
06432          }
06433          p->subs[SUB_REAL].inthreeway = 0;
06434          /* If this was part of a three way call index, let us make
06435             another three way call */
06436          unalloc_sub(p, SUB_THREEWAY);
06437       } else {
06438          /* This wasn't any sort of call, but how are we an index? */
06439          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06440       }
06441    }
06442 
06443    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06444       p->owner = NULL;
06445       p->ringt = 0;
06446       p->distinctivering = 0;
06447       p->confirmanswer = 0;
06448       p->outgoing = 0;
06449       p->digital = 0;
06450       p->faxhandled = 0;
06451       p->pulsedial = 0;
06452       if (p->dsp) {
06453          ast_dsp_free(p->dsp);
06454          p->dsp = NULL;
06455       }
06456 
06457       revert_fax_buffers(p, ast);
06458 
06459       p->law = p->law_default;
06460       law = p->law_default;
06461       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06462       if (res < 0)
06463          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06464       /* Perform low level hangup if no owner left */
06465 #ifdef HAVE_OPENR2
06466       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06467          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06468          /* If it's an incoming call, check the mfcr2_forced_release setting */
06469          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06470             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06471          } else {
06472             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06473             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06474             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06475                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06476             dahdi_r2_disconnect_call(p, r2cause);
06477          }
06478       } else if (p->mfcr2call) {
06479          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06480          /* since ast_request() was called but not ast_call() we have not yet dialed
06481          and the openr2 stack will not call on_call_end callback, we need to unset
06482          the mfcr2call flag and bump the monitor count so the monitor thread can take
06483          care of this channel events from now on */
06484          p->mfcr2call = 0;
06485       }
06486 #endif
06487       switch (p->sig) {
06488       case SIG_SS7:
06489       case SIG_MFCR2:
06490       case SIG_PRI_LIB_HANDLE_CASES:
06491       case 0:
06492          break;
06493       default:
06494          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06495          break;
06496       }
06497       if (res < 0) {
06498          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06499       }
06500       switch (p->sig) {
06501       case SIG_FXOGS:
06502       case SIG_FXOLS:
06503       case SIG_FXOKS:
06504          memset(&par, 0, sizeof(par));
06505          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06506          if (!res) {
06507             struct analog_pvt *analog_p = p->sig_pvt;
06508 #if 0
06509             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06510 #endif
06511             /* If they're off hook, try playing congestion */
06512             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06513                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06514             else
06515                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06516             analog_p->fxsoffhookstate = par.rxisoffhook;
06517          }
06518          break;
06519       case SIG_FXSGS:
06520       case SIG_FXSLS:
06521       case SIG_FXSKS:
06522          /* Make sure we're not made available for at least two seconds assuming
06523          we were actually used for an inbound or outbound call. */
06524          if (ast->_state != AST_STATE_RESERVED) {
06525             time(&p->guardtime);
06526             p->guardtime += 2;
06527          }
06528          break;
06529       default:
06530          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06531          break;
06532       }
06533       if (p->sig)
06534          dahdi_disable_ec(p);
06535       x = 0;
06536       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06537       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06538       p->didtdd = 0;
06539       p->callwaitcas = 0;
06540       p->callwaiting = p->permcallwaiting;
06541       p->hidecallerid = p->permhidecallerid;
06542       p->waitingfordt.tv_sec = 0;
06543       p->dialing = 0;
06544       p->rdnis[0] = '\0';
06545       update_conf(p);
06546       reset_conf(p);
06547       /* Restore data mode */
06548       switch (p->sig) {
06549       case SIG_PRI_LIB_HANDLE_CASES:
06550       case SIG_SS7:
06551          x = 0;
06552          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06553          break;
06554       default:
06555          break;
06556       }
06557       if (num_restart_pending == 0)
06558          restart_monitor();
06559    }
06560 
06561    p->callwaitingrepeat = 0;
06562    p->cidcwexpire = 0;
06563    p->cid_suppress_expire = 0;
06564    p->oprmode = 0;
06565 hangup_out:
06566    ast->tech_pvt = NULL;
06567    ast_free(p->cidspill);
06568    p->cidspill = NULL;
06569 
06570    ast_mutex_unlock(&p->lock);
06571    ast_verb(3, "Hungup '%s'\n", ast->name);
06572 
06573    ast_mutex_lock(&iflock);
06574    if (p->restartpending) {
06575       num_restart_pending--;
06576    }
06577 
06578    if (p->destroy) {
06579       destroy_channel(p, 0);
06580    }
06581    ast_mutex_unlock(&iflock);
06582 
06583    ast_module_unref(ast_module_info->self);
06584    return 0;
06585 }
06586 
06587 static int dahdi_answer(struct ast_channel *ast)
06588 {
06589    struct dahdi_pvt *p = ast->tech_pvt;
06590    int res = 0;
06591    int idx;
06592    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06593    ast_mutex_lock(&p->lock);
06594    idx = dahdi_get_index(ast, p, 0);
06595    if (idx < 0)
06596       idx = SUB_REAL;
06597    /* nothing to do if a radio channel */
06598    if ((p->radio || (p->oprmode < 0))) {
06599       ast_mutex_unlock(&p->lock);
06600       return 0;
06601    }
06602 
06603    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06604       res = analog_answer(p->sig_pvt, ast);
06605       ast_mutex_unlock(&p->lock);
06606       return res;
06607    }
06608 
06609    switch (p->sig) {
06610 #if defined(HAVE_PRI)
06611    case SIG_PRI_LIB_HANDLE_CASES:
06612       res = sig_pri_answer(p->sig_pvt, ast);
06613       break;
06614 #endif   /* defined(HAVE_PRI) */
06615 #if defined(HAVE_SS7)
06616    case SIG_SS7:
06617       res = sig_ss7_answer(p->sig_pvt, ast);
06618       break;
06619 #endif   /* defined(HAVE_SS7) */
06620 #ifdef HAVE_OPENR2
06621    case SIG_MFCR2:
06622       if (!p->mfcr2_call_accepted) {
06623          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06624             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06625          p->mfcr2_answer_pending = 1;
06626          if (p->mfcr2_charge_calls) {
06627             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06628             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06629          } else {
06630             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06631             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06632          }
06633       } else {
06634          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06635          dahdi_r2_answer(p);
06636       }
06637       break;
06638 #endif
06639    case 0:
06640       ast_mutex_unlock(&p->lock);
06641       return 0;
06642    default:
06643       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06644       res = -1;
06645       break;
06646    }
06647    ast_mutex_unlock(&p->lock);
06648    return res;
06649 }
06650 
06651 static void disable_dtmf_detect(struct dahdi_pvt *p)
06652 {
06653    int val = 0;
06654 
06655    p->ignoredtmf = 1;
06656 
06657    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06658 
06659    if (!p->hardwaredtmf && p->dsp) {
06660       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06661       ast_dsp_set_features(p->dsp, p->dsp_features);
06662    }
06663 }
06664 
06665 static void enable_dtmf_detect(struct dahdi_pvt *p)
06666 {
06667    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06668 
06669    if (p->channel == CHAN_PSEUDO)
06670       return;
06671 
06672    p->ignoredtmf = 0;
06673 
06674    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06675 
06676    if (!p->hardwaredtmf && p->dsp) {
06677       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06678       ast_dsp_set_features(p->dsp, p->dsp_features);
06679    }
06680 }
06681 
06682 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06683 {
06684    char *cp;
06685    struct dahdi_pvt *p = chan->tech_pvt;
06686 
06687    /* all supported options require data */
06688    if (!p || !data || (*datalen < 1)) {
06689       errno = EINVAL;
06690       return -1;
06691    }
06692 
06693    switch (option) {
06694    case AST_OPTION_DIGIT_DETECT:
06695       cp = (char *) data;
06696       *cp = p->ignoredtmf ? 0 : 1;
06697       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06698       break;
06699    case AST_OPTION_FAX_DETECT:
06700       cp = (char *) data;
06701       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06702       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06703       break;
06704    case AST_OPTION_CC_AGENT_TYPE:
06705 #if defined(HAVE_PRI)
06706 #if defined(HAVE_PRI_CCSS)
06707       if (dahdi_sig_pri_lib_handles(p->sig)) {
06708          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06709          break;
06710       }
06711 #endif   /* defined(HAVE_PRI_CCSS) */
06712 #endif   /* defined(HAVE_PRI) */
06713       return -1;
06714    default:
06715       return -1;
06716    }
06717 
06718    errno = 0;
06719 
06720    return 0;
06721 }
06722 
06723 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06724 {
06725    char *cp;
06726    signed char *scp;
06727    int x;
06728    int idx;
06729    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06730    struct oprmode *oprmode;
06731 
06732 
06733    /* all supported options require data */
06734    if (!p || !data || (datalen < 1)) {
06735       errno = EINVAL;
06736       return -1;
06737    }
06738 
06739    switch (option) {
06740    case AST_OPTION_TXGAIN:
06741       scp = (signed char *) data;
06742       idx = dahdi_get_index(chan, p, 0);
06743       if (idx < 0) {
06744          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06745          return -1;
06746       }
06747       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06748       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06749    case AST_OPTION_RXGAIN:
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 RXGAIN?\n");
06754          return -1;
06755       }
06756       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06757       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06758    case AST_OPTION_TONE_VERIFY:
06759       if (!p->dsp)
06760          break;
06761       cp = (char *) data;
06762       switch (*cp) {
06763       case 1:
06764          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06765          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06766          break;
06767       case 2:
06768          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06769          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06770          break;
06771       default:
06772          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06773          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06774          break;
06775       }
06776       break;
06777    case AST_OPTION_TDD:
06778       /* turn on or off TDD */
06779       cp = (char *) data;
06780       p->mate = 0;
06781       if (!*cp) { /* turn it off */
06782          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06783          if (p->tdd)
06784             tdd_free(p->tdd);
06785          p->tdd = 0;
06786          break;
06787       }
06788       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06789          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06790       dahdi_disable_ec(p);
06791       /* otherwise, turn it on */
06792       if (!p->didtdd) { /* if havent done it yet */
06793          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06794          unsigned char *buf;
06795          int size, res, fd, len;
06796          struct pollfd fds[1];
06797 
06798          buf = mybuf;
06799          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06800          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06801          len = 40000;
06802          idx = dahdi_get_index(chan, p, 0);
06803          if (idx < 0) {
06804             ast_log(LOG_WARNING, "No index in TDD?\n");
06805             return -1;
06806          }
06807          fd = p->subs[idx].dfd;
06808          while (len) {
06809             if (ast_check_hangup(chan))
06810                return -1;
06811             size = len;
06812             if (size > READ_SIZE)
06813                size = READ_SIZE;
06814             fds[0].fd = fd;
06815             fds[0].events = POLLPRI | POLLOUT;
06816             fds[0].revents = 0;
06817             res = poll(fds, 1, -1);
06818             if (!res) {
06819                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06820                continue;
06821             }
06822             /* if got exception */
06823             if (fds[0].revents & POLLPRI)
06824                return -1;
06825             if (!(fds[0].revents & POLLOUT)) {
06826                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06827                continue;
06828             }
06829             res = write(fd, buf, size);
06830             if (res != size) {
06831                if (res == -1) return -1;
06832                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06833                break;
06834             }
06835             len -= size;
06836             buf += size;
06837          }
06838          p->didtdd = 1; /* set to have done it now */
06839       }
06840       if (*cp == 2) { /* Mate mode */
06841          if (p->tdd)
06842             tdd_free(p->tdd);
06843          p->tdd = 0;
06844          p->mate = 1;
06845          break;
06846       }
06847       if (!p->tdd) { /* if we don't have one yet */
06848          p->tdd = tdd_new(); /* allocate one */
06849       }
06850       break;
06851    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06852       if (!p->dsp)
06853          break;
06854       cp = (char *) data;
06855       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06856          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06857       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06858       break;
06859    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06860 #if defined(HAVE_PRI)
06861       if (dahdi_sig_pri_lib_handles(p->sig)
06862          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06863          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06864          break;
06865       }
06866 #endif   /* defined(HAVE_PRI) */
06867 
06868       cp = (char *) data;
06869       if (!*cp) {
06870          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06871          x = 0;
06872          dahdi_disable_ec(p);
06873       } else {
06874          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06875          x = 1;
06876       }
06877       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06878          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06879       break;
06880    case AST_OPTION_OPRMODE:  /* Operator services mode */
06881       oprmode = (struct oprmode *) data;
06882       /* We don't support operator mode across technologies */
06883       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06884          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06885                chan->tech->type, oprmode->peer->tech->type);
06886          errno = EINVAL;
06887          return -1;
06888       }
06889       pp = oprmode->peer->tech_pvt;
06890       p->oprmode = pp->oprmode = 0;
06891       /* setup peers */
06892       p->oprpeer = pp;
06893       pp->oprpeer = p;
06894       /* setup modes, if any */
06895       if (oprmode->mode)
06896       {
06897          pp->oprmode = oprmode->mode;
06898          p->oprmode = -oprmode->mode;
06899       }
06900       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06901          oprmode->mode, chan->name,oprmode->peer->name);
06902       break;
06903    case AST_OPTION_ECHOCAN:
06904       cp = (char *) data;
06905       if (*cp) {
06906          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06907          dahdi_enable_ec(p);
06908       } else {
06909          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06910          dahdi_disable_ec(p);
06911       }
06912       break;
06913    case AST_OPTION_DIGIT_DETECT:
06914       cp = (char *) data;
06915       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06916       if (*cp) {
06917          enable_dtmf_detect(p);
06918       } else {
06919          disable_dtmf_detect(p);
06920       }
06921       break;
06922    case AST_OPTION_FAX_DETECT:
06923       cp = (char *) data;
06924       if (p->dsp) {
06925          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06926          if (*cp) {
06927             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06928          } else {
06929             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06930          }
06931          ast_dsp_set_features(p->dsp, p->dsp_features);
06932       }
06933       break;
06934    default:
06935       return -1;
06936    }
06937    errno = 0;
06938 
06939    return 0;
06940 }
06941 
06942 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06943 {
06944    struct dahdi_pvt *p = chan->tech_pvt;
06945    int res = 0;
06946 
06947    if (!p) {
06948       /* No private structure! */
06949       *buf = '\0';
06950       return -1;
06951    }
06952 
06953    if (!strcasecmp(data, "rxgain")) {
06954       ast_mutex_lock(&p->lock);
06955       snprintf(buf, len, "%f", p->rxgain);
06956       ast_mutex_unlock(&p->lock);
06957    } else if (!strcasecmp(data, "txgain")) {
06958       ast_mutex_lock(&p->lock);
06959       snprintf(buf, len, "%f", p->txgain);
06960       ast_mutex_unlock(&p->lock);
06961    } else if (!strcasecmp(data, "dahdi_channel")) {
06962       ast_mutex_lock(&p->lock);
06963       snprintf(buf, len, "%d", p->channel);
06964       ast_mutex_unlock(&p->lock);
06965    } else if (!strcasecmp(data, "dahdi_span")) {
06966       ast_mutex_lock(&p->lock);
06967       snprintf(buf, len, "%d", p->span);
06968       ast_mutex_unlock(&p->lock);
06969    } else if (!strcasecmp(data, "dahdi_type")) {
06970       ast_mutex_lock(&p->lock);
06971       switch (p->sig) {
06972 #if defined(HAVE_OPENR2)
06973       case SIG_MFCR2:
06974          ast_copy_string(buf, "mfc/r2", len);
06975          break;
06976 #endif   /* defined(HAVE_OPENR2) */
06977 #if defined(HAVE_PRI)
06978       case SIG_PRI_LIB_HANDLE_CASES:
06979          ast_copy_string(buf, "pri", len);
06980          break;
06981 #endif   /* defined(HAVE_PRI) */
06982       case 0:
06983          ast_copy_string(buf, "pseudo", len);
06984          break;
06985 #if defined(HAVE_SS7)
06986       case SIG_SS7:
06987          ast_copy_string(buf, "ss7", len);
06988          break;
06989 #endif   /* defined(HAVE_SS7) */
06990       default:
06991          /* The only thing left is analog ports. */
06992          ast_copy_string(buf, "analog", len);
06993          break;
06994       }
06995       ast_mutex_unlock(&p->lock);
06996 #if defined(HAVE_PRI)
06997 #if defined(HAVE_PRI_REVERSE_CHARGE)
06998    } else if (!strcasecmp(data, "reversecharge")) {
06999       ast_mutex_lock(&p->lock);
07000       switch (p->sig) {
07001       case SIG_PRI_LIB_HANDLE_CASES:
07002          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07003          break;
07004       default:
07005          *buf = '\0';
07006          res = -1;
07007          break;
07008       }
07009       ast_mutex_unlock(&p->lock);
07010 #endif
07011 #if defined(HAVE_PRI_SETUP_KEYPAD)
07012    } else if (!strcasecmp(data, "keypad_digits")) {
07013       ast_mutex_lock(&p->lock);
07014       switch (p->sig) {
07015       case SIG_PRI_LIB_HANDLE_CASES:
07016          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07017             len);
07018          break;
07019       default:
07020          *buf = '\0';
07021          res = -1;
07022          break;
07023       }
07024       ast_mutex_unlock(&p->lock);
07025 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07026    } else if (!strcasecmp(data, "no_media_path")) {
07027       ast_mutex_lock(&p->lock);
07028       switch (p->sig) {
07029       case SIG_PRI_LIB_HANDLE_CASES:
07030          /*
07031           * TRUE if the call is on hold or is call waiting because
07032           * there is no media path available.
07033           */
07034          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07035          break;
07036       default:
07037          *buf = '\0';
07038          res = -1;
07039          break;
07040       }
07041       ast_mutex_unlock(&p->lock);
07042 #endif   /* defined(HAVE_PRI) */
07043    } else {
07044       *buf = '\0';
07045       res = -1;
07046    }
07047 
07048    return res;
07049 }
07050 
07051 
07052 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07053 {
07054    int res;
07055    char policy_str[21] = "";
07056 
07057    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07058       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07059       return 1;
07060    }
07061    if (*num_buffers < 0) {
07062       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07063       return -1;
07064    }
07065    if (!strcasecmp(policy_str, "full")) {
07066       *policy = DAHDI_POLICY_WHEN_FULL;
07067    } else if (!strcasecmp(policy_str, "immediate")) {
07068       *policy = DAHDI_POLICY_IMMEDIATE;
07069 #if defined(HAVE_DAHDI_HALF_FULL)
07070    } else if (!strcasecmp(policy_str, "half")) {
07071       *policy = DAHDI_POLICY_HALF_FULL;
07072 #endif
07073    } else {
07074       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07075       return -1;
07076    }
07077 
07078    return 0;
07079 }
07080 
07081 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07082 {
07083    struct dahdi_pvt *p = chan->tech_pvt;
07084    int res = 0;
07085 
07086    if (!p) {
07087       /* No private structure! */
07088       return -1;
07089    }
07090 
07091    if (!strcasecmp(data, "buffers")) {
07092       int num_bufs, policy;
07093 
07094       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07095          struct dahdi_bufferinfo bi = {
07096             .txbufpolicy = policy,
07097             .rxbufpolicy = policy,
07098             .bufsize = p->bufsize,
07099             .numbufs = num_bufs,
07100          };
07101          int bpres;
07102 
07103          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07104             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07105          } else {
07106             p->bufferoverrideinuse = 1;
07107          }
07108       } else {
07109          res = -1;
07110       }
07111    } else if (!strcasecmp(data, "echocan_mode")) {
07112       if (!strcasecmp(value, "on")) {
07113          ast_mutex_lock(&p->lock);
07114          dahdi_enable_ec(p);
07115          ast_mutex_unlock(&p->lock);
07116       } else if (!strcasecmp(value, "off")) {
07117          ast_mutex_lock(&p->lock);
07118          dahdi_disable_ec(p);
07119          ast_mutex_unlock(&p->lock);
07120 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07121       } else if (!strcasecmp(value, "fax")) {
07122          int blah = 1;
07123 
07124          ast_mutex_lock(&p->lock);
07125          if (!p->echocanon) {
07126             dahdi_enable_ec(p);
07127          }
07128          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07129             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07130          }
07131          ast_mutex_unlock(&p->lock);
07132       } else if (!strcasecmp(value, "voice")) {
07133          int blah = 0;
07134 
07135          ast_mutex_lock(&p->lock);
07136          if (!p->echocanon) {
07137             dahdi_enable_ec(p);
07138          }
07139          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07140             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07141          }
07142          ast_mutex_unlock(&p->lock);
07143 #endif
07144       } else {
07145          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07146          res = -1;
07147       }
07148    } else {
07149       res = -1;
07150    }
07151 
07152    return res;
07153 }
07154 
07155 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07156 {
07157    /* Unlink a specific slave or all slaves/masters from a given master */
07158    int x;
07159    int hasslaves;
07160    if (!master)
07161       return;
07162    if (needlock) {
07163       ast_mutex_lock(&master->lock);
07164       if (slave) {
07165          while (ast_mutex_trylock(&slave->lock)) {
07166             DEADLOCK_AVOIDANCE(&master->lock);
07167          }
07168       }
07169    }
07170    hasslaves = 0;
07171    for (x = 0; x < MAX_SLAVES; x++) {
07172       if (master->slaves[x]) {
07173          if (!slave || (master->slaves[x] == slave)) {
07174             /* Take slave out of the conference */
07175             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07176             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07177             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07178             master->slaves[x]->master = NULL;
07179             master->slaves[x] = NULL;
07180          } else
07181             hasslaves = 1;
07182       }
07183       if (!hasslaves)
07184          master->inconference = 0;
07185    }
07186    if (!slave) {
07187       if (master->master) {
07188          /* Take master out of the conference */
07189          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07190          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07191          hasslaves = 0;
07192          for (x = 0; x < MAX_SLAVES; x++) {
07193             if (master->master->slaves[x] == master)
07194                master->master->slaves[x] = NULL;
07195             else if (master->master->slaves[x])
07196                hasslaves = 1;
07197          }
07198          if (!hasslaves)
07199             master->master->inconference = 0;
07200       }
07201       master->master = NULL;
07202    }
07203    update_conf(master);
07204    if (needlock) {
07205       if (slave)
07206          ast_mutex_unlock(&slave->lock);
07207       ast_mutex_unlock(&master->lock);
07208    }
07209 }
07210 
07211 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07212    int x;
07213    if (!slave || !master) {
07214       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07215       return;
07216    }
07217    for (x = 0; x < MAX_SLAVES; x++) {
07218       if (!master->slaves[x]) {
07219          master->slaves[x] = slave;
07220          break;
07221       }
07222    }
07223    if (x >= MAX_SLAVES) {
07224       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07225       master->slaves[MAX_SLAVES - 1] = slave;
07226    }
07227    if (slave->master)
07228       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07229    slave->master = master;
07230 
07231    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07232 }
07233 
07234 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)
07235 {
07236    struct ast_channel *who;
07237    struct dahdi_pvt *p0, *p1, *op0, *op1;
07238    struct dahdi_pvt *master = NULL, *slave = NULL;
07239    struct ast_frame *f;
07240    int inconf = 0;
07241    int nothingok = 1;
07242    int ofd0, ofd1;
07243    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07244    int os0 = -1, os1 = -1;
07245    int priority = 0;
07246    struct ast_channel *oc0, *oc1;
07247    enum ast_bridge_result res;
07248    struct timeval start = ast_tvnow();
07249 #ifdef PRI_2BCT
07250    int triedtopribridge = 0;
07251    q931_call *q931c0;
07252    q931_call *q931c1;
07253 #endif
07254 
07255    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07256       There is code below to handle it properly until DTMF is actually seen,
07257       but due to currently unresolved issues it's ignored...
07258    */
07259 
07260    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07261       return AST_BRIDGE_FAILED_NOWARN;
07262 
07263    ast_channel_lock(c0);
07264    while (ast_channel_trylock(c1)) {
07265       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07266    }
07267 
07268    p0 = c0->tech_pvt;
07269    p1 = c1->tech_pvt;
07270    /* cant do pseudo-channels here */
07271    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07272       ast_channel_unlock(c0);
07273       ast_channel_unlock(c1);
07274       return AST_BRIDGE_FAILED_NOWARN;
07275    }
07276 
07277    oi0 = dahdi_get_index(c0, p0, 0);
07278    oi1 = dahdi_get_index(c1, p1, 0);
07279    if ((oi0 < 0) || (oi1 < 0)) {
07280       ast_channel_unlock(c0);
07281       ast_channel_unlock(c1);
07282       return AST_BRIDGE_FAILED;
07283    }
07284 
07285    op0 = p0 = c0->tech_pvt;
07286    op1 = p1 = c1->tech_pvt;
07287    ofd0 = c0->fds[0];
07288    ofd1 = c1->fds[0];
07289    oc0 = p0->owner;
07290    oc1 = p1->owner;
07291 
07292    if (ast_mutex_trylock(&p0->lock)) {
07293       /* Don't block, due to potential for deadlock */
07294       ast_channel_unlock(c0);
07295       ast_channel_unlock(c1);
07296       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07297       return AST_BRIDGE_RETRY;
07298    }
07299    if (ast_mutex_trylock(&p1->lock)) {
07300       /* Don't block, due to potential for deadlock */
07301       ast_mutex_unlock(&p0->lock);
07302       ast_channel_unlock(c0);
07303       ast_channel_unlock(c1);
07304       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07305       return AST_BRIDGE_RETRY;
07306    }
07307 
07308    if ((p0->callwaiting && p0->callwaitingcallerid)
07309       || (p1->callwaiting && p1->callwaitingcallerid)) {
07310       /*
07311        * Call Waiting Caller ID requires DTMF detection to know if it
07312        * can send the CID spill.
07313        *
07314        * For now, don't attempt to native bridge if either channel
07315        * needs DTMF detection.  There is code below to handle it
07316        * properly until DTMF is actually seen, but due to currently
07317        * unresolved issues it's ignored...
07318        */
07319       ast_mutex_unlock(&p0->lock);
07320       ast_mutex_unlock(&p1->lock);
07321       ast_channel_unlock(c0);
07322       ast_channel_unlock(c1);
07323       return AST_BRIDGE_FAILED_NOWARN;
07324    }
07325 
07326 #if defined(HAVE_PRI)
07327    if ((dahdi_sig_pri_lib_handles(p0->sig)
07328          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07329       || (dahdi_sig_pri_lib_handles(p1->sig)
07330          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07331       /*
07332        * PRI nobch channels (hold and call waiting) are equivalent to
07333        * pseudo channels and cannot be done here.
07334        */
07335       ast_mutex_unlock(&p0->lock);
07336       ast_mutex_unlock(&p1->lock);
07337       ast_channel_unlock(c0);
07338       ast_channel_unlock(c1);
07339       return AST_BRIDGE_FAILED_NOWARN;
07340    }
07341 #endif   /* defined(HAVE_PRI) */
07342 
07343    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07344       if (p0->owner && p1->owner) {
07345          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07346          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07347             master = p0;
07348             slave = p1;
07349             inconf = 1;
07350          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07351             master = p1;
07352             slave = p0;
07353             inconf = 1;
07354          } else {
07355             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07356             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07357                p0->channel,
07358                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07359                p0->subs[SUB_REAL].inthreeway, p0->channel,
07360                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07361                p1->subs[SUB_REAL].inthreeway);
07362          }
07363          nothingok = 0;
07364       }
07365    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07366       if (p1->subs[SUB_THREEWAY].inthreeway) {
07367          master = p1;
07368          slave = p0;
07369          nothingok = 0;
07370       }
07371    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07372       if (p0->subs[SUB_THREEWAY].inthreeway) {
07373          master = p0;
07374          slave = p1;
07375          nothingok = 0;
07376       }
07377    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07378       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07379          don't put us in anything */
07380       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07381          master = p1;
07382          slave = p0;
07383          nothingok = 0;
07384       }
07385    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07386       /* Same as previous */
07387       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07388          master = p0;
07389          slave = p1;
07390          nothingok = 0;
07391       }
07392    }
07393    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07394       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07395    if (master && slave) {
07396       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07397          in an active threeway call with a channel that is ringing, we should
07398          indicate ringing. */
07399       if ((oi1 == SUB_THREEWAY) &&
07400          p1->subs[SUB_THREEWAY].inthreeway &&
07401          p1->subs[SUB_REAL].owner &&
07402          p1->subs[SUB_REAL].inthreeway &&
07403          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07404          ast_debug(1,
07405             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07406             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07407          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07408          os1 = p1->subs[SUB_REAL].owner->_state;
07409       } else {
07410          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07411             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07412          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07413       }
07414       if ((oi0 == SUB_THREEWAY) &&
07415          p0->subs[SUB_THREEWAY].inthreeway &&
07416          p0->subs[SUB_REAL].owner &&
07417          p0->subs[SUB_REAL].inthreeway &&
07418          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07419          ast_debug(1,
07420             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07421             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07422          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07423          os0 = p0->subs[SUB_REAL].owner->_state;
07424       } else {
07425          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07426             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07427          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07428       }
07429       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07430          if (!p0->echocanbridged || !p1->echocanbridged) {
07431             /* Disable echo cancellation if appropriate */
07432             dahdi_disable_ec(p0);
07433             dahdi_disable_ec(p1);
07434          }
07435       }
07436       dahdi_link(slave, master);
07437       master->inconference = inconf;
07438    } else if (!nothingok)
07439       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07440 
07441    update_conf(p0);
07442    update_conf(p1);
07443    t0 = p0->subs[SUB_REAL].inthreeway;
07444    t1 = p1->subs[SUB_REAL].inthreeway;
07445 
07446    ast_mutex_unlock(&p0->lock);
07447    ast_mutex_unlock(&p1->lock);
07448 
07449    ast_channel_unlock(c0);
07450    ast_channel_unlock(c1);
07451 
07452    /* Native bridge failed */
07453    if ((!master || !slave) && !nothingok) {
07454       dahdi_enable_ec(p0);
07455       dahdi_enable_ec(p1);
07456       return AST_BRIDGE_FAILED;
07457    }
07458 
07459    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07460 
07461    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07462       disable_dtmf_detect(op0);
07463 
07464    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07465       disable_dtmf_detect(op1);
07466 
07467    for (;;) {
07468       struct ast_channel *c0_priority[2] = {c0, c1};
07469       struct ast_channel *c1_priority[2] = {c1, c0};
07470       int ms;
07471 
07472       /* Here's our main loop...  Start by locking things, looking for private parts,
07473          and then balking if anything is wrong */
07474 
07475       ast_channel_lock(c0);
07476       while (ast_channel_trylock(c1)) {
07477          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07478       }
07479 
07480       p0 = c0->tech_pvt;
07481       p1 = c1->tech_pvt;
07482 
07483       if (op0 == p0)
07484          i0 = dahdi_get_index(c0, p0, 1);
07485       if (op1 == p1)
07486          i1 = dahdi_get_index(c1, p1, 1);
07487 
07488       ast_channel_unlock(c0);
07489       ast_channel_unlock(c1);
07490       ms = ast_remaining_ms(start, timeoutms);
07491       if (!ms ||
07492          (op0 != p0) ||
07493          (op1 != p1) ||
07494          (ofd0 != c0->fds[0]) ||
07495          (ofd1 != c1->fds[0]) ||
07496          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07497          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07498          (oc0 != p0->owner) ||
07499          (oc1 != p1->owner) ||
07500          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07501          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07502          (oi0 != i0) ||
07503          (oi1 != i1)) {
07504          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07505             op0->channel, oi0, op1->channel, oi1);
07506          res = AST_BRIDGE_RETRY;
07507          goto return_from_bridge;
07508       }
07509 
07510 #ifdef PRI_2BCT
07511       if (!triedtopribridge) {
07512          triedtopribridge = 1;
07513          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07514             ast_mutex_lock(&p0->pri->lock);
07515             switch (p0->sig) {
07516             case SIG_PRI_LIB_HANDLE_CASES:
07517                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07518                break;
07519             default:
07520                q931c0 = NULL;
07521                break;
07522             }
07523             switch (p1->sig) {
07524             case SIG_PRI_LIB_HANDLE_CASES:
07525                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07526                break;
07527             default:
07528                q931c1 = NULL;
07529                break;
07530             }
07531             if (q931c0 && q931c1) {
07532                pri_channel_bridge(q931c0, q931c1);
07533             }
07534             ast_mutex_unlock(&p0->pri->lock);
07535          }
07536       }
07537 #endif
07538 
07539       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07540       if (!who) {
07541          ast_debug(1, "Ooh, empty read...\n");
07542          continue;
07543       }
07544       f = ast_read(who);
07545       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07546          *fo = f;
07547          *rc = who;
07548          res = AST_BRIDGE_COMPLETE;
07549          goto return_from_bridge;
07550       }
07551       if (f->frametype == AST_FRAME_DTMF) {
07552          if ((who == c0) && p0->pulsedial) {
07553             ast_write(c1, f);
07554          } else if ((who == c1) && p1->pulsedial) {
07555             ast_write(c0, f);
07556          } else {
07557             *fo = f;
07558             *rc = who;
07559             res = AST_BRIDGE_COMPLETE;
07560             goto return_from_bridge;
07561          }
07562       }
07563       ast_frfree(f);
07564 
07565       /* Swap who gets priority */
07566       priority = !priority;
07567    }
07568 
07569 return_from_bridge:
07570    if (op0 == p0)
07571       dahdi_enable_ec(p0);
07572 
07573    if (op1 == p1)
07574       dahdi_enable_ec(p1);
07575 
07576    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07577       enable_dtmf_detect(op0);
07578 
07579    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07580       enable_dtmf_detect(op1);
07581 
07582    dahdi_unlink(slave, master, 1);
07583 
07584    return res;
07585 }
07586 
07587 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07588 {
07589    struct dahdi_pvt *p = newchan->tech_pvt;
07590    int x;
07591 
07592    ast_mutex_lock(&p->lock);
07593 
07594    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07595    if (p->owner == oldchan) {
07596       p->owner = newchan;
07597    }
07598    for (x = 0; x < 3; x++) {
07599       if (p->subs[x].owner == oldchan) {
07600          if (!x) {
07601             dahdi_unlink(NULL, p, 0);
07602          }
07603          p->subs[x].owner = newchan;
07604       }
07605    }
07606    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07607       analog_fixup(oldchan, newchan, p->sig_pvt);
07608 #if defined(HAVE_PRI)
07609    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07610       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07611 #endif   /* defined(HAVE_PRI) */
07612 #if defined(HAVE_SS7)
07613    } else if (p->sig == SIG_SS7) {
07614       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07615 #endif   /* defined(HAVE_SS7) */
07616    }
07617    update_conf(p);
07618 
07619    ast_mutex_unlock(&p->lock);
07620 
07621    if (newchan->_state == AST_STATE_RINGING) {
07622       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07623    }
07624    return 0;
07625 }
07626 
07627 static int dahdi_ring_phone(struct dahdi_pvt *p)
07628 {
07629    int x;
07630    int res;
07631    /* Make sure our transmit state is on hook */
07632    x = 0;
07633    x = DAHDI_ONHOOK;
07634    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07635    do {
07636       x = DAHDI_RING;
07637       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07638       if (res) {
07639          switch (errno) {
07640          case EBUSY:
07641          case EINTR:
07642             /* Wait just in case */
07643             usleep(10000);
07644             continue;
07645          case EINPROGRESS:
07646             res = 0;
07647             break;
07648          default:
07649             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07650             res = 0;
07651          }
07652       }
07653    } while (res);
07654    return res;
07655 }
07656 
07657 static void *analog_ss_thread(void *data);
07658 
07659 static int attempt_transfer(struct dahdi_pvt *p)
07660 {
07661    /* In order to transfer, we need at least one of the channels to
07662       actually be in a call bridge.  We can't conference two applications
07663       together (but then, why would we want to?) */
07664    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07665       /* The three-way person we're about to transfer to could still be in MOH, so
07666          stop if now if appropriate */
07667       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07668          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07669       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07670          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07671       }
07672       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07673          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07674       }
07675        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07676          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07677                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07678          return -1;
07679       }
07680       /* Orphan the channel after releasing the lock */
07681       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07682       unalloc_sub(p, SUB_THREEWAY);
07683    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07684       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07685       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07686          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07687       }
07688       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07689          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07690       }
07691       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07692          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07693                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07694          return -1;
07695       }
07696       /* Three-way is now the REAL */
07697       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07698       ast_channel_unlock(p->subs[SUB_REAL].owner);
07699       unalloc_sub(p, SUB_THREEWAY);
07700       /* Tell the caller not to hangup */
07701       return 1;
07702    } else {
07703       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07704          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07705       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07706       return -1;
07707    }
07708    return 0;
07709 }
07710 
07711 static int check_for_conference(struct dahdi_pvt *p)
07712 {
07713    struct dahdi_confinfo ci;
07714    /* Fine if we already have a master, etc */
07715    if (p->master || (p->confno > -1))
07716       return 0;
07717    memset(&ci, 0, sizeof(ci));
07718    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07719       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07720       return 0;
07721    }
07722    /* If we have no master and don't have a confno, then
07723       if we're in a conference, it's probably a MeetMe room or
07724       some such, so don't let us 3-way out! */
07725    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07726       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07727       return 1;
07728    }
07729    return 0;
07730 }
07731 
07732 /*! Checks channel for alarms
07733  * \param p a channel to check for alarms.
07734  * \returns the alarms on the span to which the channel belongs, or alarms on
07735  *          the channel if no span alarms.
07736  */
07737 static int get_alarms(struct dahdi_pvt *p)
07738 {
07739    int res;
07740    struct dahdi_spaninfo zi;
07741    struct dahdi_params params;
07742 
07743    memset(&zi, 0, sizeof(zi));
07744    zi.spanno = p->span;
07745 
07746    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07747       if (zi.alarms != DAHDI_ALARM_NONE)
07748          return zi.alarms;
07749    } else {
07750       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07751       return 0;
07752    }
07753 
07754    /* No alarms on the span. Check for channel alarms. */
07755    memset(&params, 0, sizeof(params));
07756    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07757       return params.chan_alarms;
07758 
07759    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07760 
07761    return DAHDI_ALARM_NONE;
07762 }
07763 
07764 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07765 {
07766    struct dahdi_pvt *p = ast->tech_pvt;
07767    struct ast_frame *f = *dest;
07768 
07769    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07770       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07771       f->subclass.integer, f->subclass.integer, ast->name);
07772 
07773    if (p->confirmanswer) {
07774       if (f->frametype == AST_FRAME_DTMF_END) {
07775          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07776          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07777             of a DTMF digit */
07778          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07779          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07780          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07781          p->confirmanswer = 0;
07782       } else {
07783          p->subs[idx].f.frametype = AST_FRAME_NULL;
07784          p->subs[idx].f.subclass.integer = 0;
07785       }
07786       *dest = &p->subs[idx].f;
07787    } else if (p->callwaitcas) {
07788       if (f->frametype == AST_FRAME_DTMF_END) {
07789          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07790             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07791             ast_free(p->cidspill);
07792             p->cidspill = NULL;
07793             send_cwcidspill(p);
07794          }
07795          p->callwaitcas = 0;
07796       }
07797       p->subs[idx].f.frametype = AST_FRAME_NULL;
07798       p->subs[idx].f.subclass.integer = 0;
07799       *dest = &p->subs[idx].f;
07800    } else if (f->subclass.integer == 'f') {
07801       if (f->frametype == AST_FRAME_DTMF_END) {
07802          /* Fax tone -- Handle and return NULL */
07803          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07804             /* If faxbuffers are configured, use them for the fax transmission */
07805             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07806                struct dahdi_bufferinfo bi = {
07807                   .txbufpolicy = p->faxbuf_policy,
07808                   .bufsize = p->bufsize,
07809                   .numbufs = p->faxbuf_no
07810                };
07811                int res;
07812 
07813                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07814                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07815                } else {
07816                   p->bufferoverrideinuse = 1;
07817                }
07818             }
07819             p->faxhandled = 1;
07820             if (p->dsp) {
07821                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07822                ast_dsp_set_features(p->dsp, p->dsp_features);
07823                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07824             }
07825             if (strcmp(ast->exten, "fax")) {
07826                const char *target_context = S_OR(ast->macrocontext, ast->context);
07827 
07828                /* We need to unlock 'ast' here because ast_exists_extension has the
07829                 * potential to start autoservice on the channel. Such action is prone
07830                 * to deadlock.
07831                 */
07832                ast_mutex_unlock(&p->lock);
07833                ast_channel_unlock(ast);
07834                if (ast_exists_extension(ast, target_context, "fax", 1,
07835                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07836                   ast_channel_lock(ast);
07837                   ast_mutex_lock(&p->lock);
07838                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07839                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07840                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07841                   if (ast_async_goto(ast, target_context, "fax", 1))
07842                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07843                } else {
07844                   ast_channel_lock(ast);
07845                   ast_mutex_lock(&p->lock);
07846                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07847                }
07848             } else {
07849                ast_debug(1, "Already in a fax extension, not redirecting\n");
07850             }
07851          } else {
07852             ast_debug(1, "Fax already handled\n");
07853          }
07854          dahdi_confmute(p, 0);
07855       }
07856       p->subs[idx].f.frametype = AST_FRAME_NULL;
07857       p->subs[idx].f.subclass.integer = 0;
07858       *dest = &p->subs[idx].f;
07859    }
07860 }
07861 
07862 static void handle_alarms(struct dahdi_pvt *p, int alms)
07863 {
07864    const char *alarm_str;
07865 
07866 #if defined(HAVE_PRI)
07867    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07868       return;
07869    }
07870 #endif   /* defined(HAVE_PRI) */
07871 
07872    alarm_str = alarm2str(alms);
07873    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07874       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07875       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07876                  "Alarm: %s\r\n"
07877                  "Channel: %d\r\n",
07878                  alarm_str, p->channel);
07879    }
07880 
07881    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07882       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07883       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07884                  "Alarm: %s\r\n"
07885                  "Span: %d\r\n",
07886                  alarm_str, p->span);
07887    }
07888 }
07889 
07890 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07891 {
07892    int res, x;
07893    int idx, mysig;
07894    char *c;
07895    struct dahdi_pvt *p = ast->tech_pvt;
07896    pthread_t threadid;
07897    struct ast_channel *chan;
07898    struct ast_frame *f;
07899 
07900    idx = dahdi_get_index(ast, p, 0);
07901    if (idx < 0) {
07902       return &ast_null_frame;
07903    }
07904    mysig = p->sig;
07905    if (p->outsigmod > -1)
07906       mysig = p->outsigmod;
07907    p->subs[idx].f.frametype = AST_FRAME_NULL;
07908    p->subs[idx].f.subclass.integer = 0;
07909    p->subs[idx].f.datalen = 0;
07910    p->subs[idx].f.samples = 0;
07911    p->subs[idx].f.mallocd = 0;
07912    p->subs[idx].f.offset = 0;
07913    p->subs[idx].f.src = "dahdi_handle_event";
07914    p->subs[idx].f.data.ptr = NULL;
07915    f = &p->subs[idx].f;
07916 
07917    if (p->fake_event) {
07918       res = p->fake_event;
07919       p->fake_event = 0;
07920    } else
07921       res = dahdi_get_event(p->subs[idx].dfd);
07922 
07923    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07924 
07925    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07926       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07927       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07928 #if defined(HAVE_PRI)
07929       if (dahdi_sig_pri_lib_handles(p->sig)
07930          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07931          && p->pri
07932          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07933          /* absorb event */
07934       } else
07935 #endif   /* defined(HAVE_PRI) */
07936       {
07937          /* Unmute conference */
07938          dahdi_confmute(p, 0);
07939          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07940          p->subs[idx].f.subclass.integer = res & 0xff;
07941          dahdi_handle_dtmf(ast, idx, &f);
07942       }
07943       return f;
07944    }
07945 
07946    if (res & DAHDI_EVENT_DTMFDOWN) {
07947       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07948 #if defined(HAVE_PRI)
07949       if (dahdi_sig_pri_lib_handles(p->sig)
07950          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07951          && p->pri
07952          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07953          /* absorb event */
07954       } else
07955 #endif   /* defined(HAVE_PRI) */
07956       {
07957          /* Mute conference */
07958          dahdi_confmute(p, 1);
07959          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07960          p->subs[idx].f.subclass.integer = res & 0xff;
07961          dahdi_handle_dtmf(ast, idx, &f);
07962       }
07963       return &p->subs[idx].f;
07964    }
07965 
07966    switch (res) {
07967    case DAHDI_EVENT_EC_DISABLED:
07968       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07969       p->echocanon = 0;
07970       break;
07971 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07972    case DAHDI_EVENT_TX_CED_DETECTED:
07973       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07974       break;
07975    case DAHDI_EVENT_RX_CED_DETECTED:
07976       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07977       break;
07978    case DAHDI_EVENT_EC_NLP_DISABLED:
07979       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07980       break;
07981    case DAHDI_EVENT_EC_NLP_ENABLED:
07982       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07983       break;
07984 #endif
07985    case DAHDI_EVENT_BITSCHANGED:
07986 #ifdef HAVE_OPENR2
07987       if (p->sig != SIG_MFCR2) {
07988          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07989       } else {
07990          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07991          openr2_chan_handle_cas(p->r2chan);
07992       }
07993 #else
07994       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07995 #endif
07996       break;
07997    case DAHDI_EVENT_PULSE_START:
07998       /* Stop tone if there's a pulse start and the PBX isn't started */
07999       if (!ast->pbx)
08000          tone_zone_play_tone(p->subs[idx].dfd, -1);
08001       break;
08002    case DAHDI_EVENT_DIALCOMPLETE:
08003       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08004 #if defined(HAVE_PRI)
08005       if (dahdi_sig_pri_lib_handles(p->sig)) {
08006          if (p->inalarm) {
08007             break;
08008          }
08009          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08010             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08011                strerror(errno));
08012             return NULL;
08013          }
08014          if (x) {
08015             /* Still dialing in DAHDI driver */
08016             break;
08017          }
08018          /*
08019           * The ast channel is locked and the private may be locked more
08020           * than once.
08021           */
08022          sig_pri_dial_complete(p->sig_pvt, ast);
08023          break;
08024       }
08025 #endif   /* defined(HAVE_PRI) */
08026 #ifdef HAVE_OPENR2
08027       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08028          /* we don't need to do anything for this event for R2 signaling
08029             if the call is being setup */
08030          break;
08031       }
08032 #endif
08033       if (p->inalarm) break;
08034       if ((p->radio || (p->oprmode < 0))) break;
08035       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08036          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08037          return NULL;
08038       }
08039       if (!x) { /* if not still dialing in driver */
08040          dahdi_enable_ec(p);
08041          if (p->echobreak) {
08042             dahdi_train_ec(p);
08043             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08044             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08045             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08046             p->echobreak = 0;
08047          } else {
08048             p->dialing = 0;
08049             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08050                /* if thru with dialing after offhook */
08051                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08052                   ast_setstate(ast, AST_STATE_UP);
08053                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08054                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08055                   break;
08056                } else { /* if to state wait for offhook to dial rest */
08057                   /* we now wait for off hook */
08058                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08059                }
08060             }
08061             if (ast->_state == AST_STATE_DIALING) {
08062                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08063                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08064                } else if (p->confirmanswer || (!p->dialednone
08065                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08066                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08067                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08068                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08069                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08070                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08071                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08072                      || (mysig == SIG_SF_FEATB)))) {
08073                   ast_setstate(ast, AST_STATE_RINGING);
08074                } else if (!p->answeronpolarityswitch) {
08075                   ast_setstate(ast, AST_STATE_UP);
08076                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08077                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08078                   /* If aops=0 and hops=1, this is necessary */
08079                   p->polarity = POLARITY_REV;
08080                } else {
08081                   /* Start clean, so we can catch the change to REV polarity when party answers */
08082                   p->polarity = POLARITY_IDLE;
08083                }
08084             }
08085          }
08086       }
08087       break;
08088    case DAHDI_EVENT_ALARM:
08089       switch (p->sig) {
08090 #if defined(HAVE_PRI)
08091       case SIG_PRI_LIB_HANDLE_CASES:
08092          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08093          break;
08094 #endif   /* defined(HAVE_PRI) */
08095 #if defined(HAVE_SS7)
08096       case SIG_SS7:
08097          sig_ss7_set_alarm(p->sig_pvt, 1);
08098          break;
08099 #endif   /* defined(HAVE_SS7) */
08100       default:
08101          p->inalarm = 1;
08102          break;
08103       }
08104       res = get_alarms(p);
08105       handle_alarms(p, res);
08106 #ifdef HAVE_PRI
08107       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08108          /* fall through intentionally */
08109       } else {
08110          break;
08111       }
08112 #endif
08113 #if defined(HAVE_SS7)
08114       if (p->sig == SIG_SS7)
08115          break;
08116 #endif   /* defined(HAVE_SS7) */
08117 #ifdef HAVE_OPENR2
08118       if (p->sig == SIG_MFCR2)
08119          break;
08120 #endif
08121    case DAHDI_EVENT_ONHOOK:
08122       if (p->radio) {
08123          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08124          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08125          break;
08126       }
08127       if (p->oprmode < 0)
08128       {
08129          if (p->oprmode != -1) break;
08130          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08131          {
08132             /* Make sure it starts ringing */
08133             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08134             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08135             save_conference(p->oprpeer);
08136             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08137          }
08138          break;
08139       }
08140       switch (p->sig) {
08141       case SIG_FXOLS:
08142       case SIG_FXOGS:
08143       case SIG_FXOKS:
08144          /* Check for some special conditions regarding call waiting */
08145          if (idx == SUB_REAL) {
08146             /* The normal line was hung up */
08147             if (p->subs[SUB_CALLWAIT].owner) {
08148                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08149                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08150                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08151                unalloc_sub(p, SUB_CALLWAIT);
08152 #if 0
08153                p->subs[idx].needanswer = 0;
08154                p->subs[idx].needringing = 0;
08155 #endif
08156                p->callwaitingrepeat = 0;
08157                p->cidcwexpire = 0;
08158                p->cid_suppress_expire = 0;
08159                p->owner = NULL;
08160                /* Don't start streaming audio yet if the incoming call isn't up yet */
08161                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08162                   p->dialing = 1;
08163                dahdi_ring_phone(p);
08164             } else if (p->subs[SUB_THREEWAY].owner) {
08165                unsigned int mssinceflash;
08166                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08167                   the private structure -- not especially easy or clean */
08168                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08169                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08170                   DLA_UNLOCK(&p->lock);
08171                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08172                   /* We can grab ast and p in that order, without worry.  We should make sure
08173                      nothing seriously bad has happened though like some sort of bizarre double
08174                      masquerade! */
08175                   DLA_LOCK(&p->lock);
08176                   if (p->owner != ast) {
08177                      ast_log(LOG_WARNING, "This isn't good...\n");
08178                      return NULL;
08179                   }
08180                }
08181                if (!p->subs[SUB_THREEWAY].owner) {
08182                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08183                   return NULL;
08184                }
08185                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08186                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08187                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08188                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08189                      hanging up.  Hangup both channels now */
08190                   if (p->subs[SUB_THREEWAY].owner)
08191                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08192                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08193                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08194                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08195                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08196                   if (p->transfer) {
08197                      /* In any case this isn't a threeway call anymore */
08198                      p->subs[SUB_REAL].inthreeway = 0;
08199                      p->subs[SUB_THREEWAY].inthreeway = 0;
08200                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08201                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08202                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08203                         /* Swap subs and dis-own channel */
08204                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08205                         p->owner = NULL;
08206                         /* Ring the phone */
08207                         dahdi_ring_phone(p);
08208                      } else {
08209                         if ((res = attempt_transfer(p)) < 0) {
08210                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08211                            if (p->subs[SUB_THREEWAY].owner)
08212                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08213                         } else if (res) {
08214                            /* Don't actually hang up at this point */
08215                            if (p->subs[SUB_THREEWAY].owner)
08216                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08217                            break;
08218                         }
08219                      }
08220                   } else {
08221                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08222                      if (p->subs[SUB_THREEWAY].owner)
08223                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08224                   }
08225                } else {
08226                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08227                   /* Swap subs and dis-own channel */
08228                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08229                   p->owner = NULL;
08230                   /* Ring the phone */
08231                   dahdi_ring_phone(p);
08232                }
08233             }
08234          } else {
08235             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08236          }
08237          /* Fall through */
08238       default:
08239          dahdi_disable_ec(p);
08240          return NULL;
08241       }
08242       break;
08243    case DAHDI_EVENT_RINGOFFHOOK:
08244       if (p->inalarm) break;
08245       if (p->oprmode < 0)
08246       {
08247          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08248          {
08249             /* Make sure it stops ringing */
08250             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08251             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08252             restore_conference(p->oprpeer);
08253          }
08254          break;
08255       }
08256       if (p->radio)
08257       {
08258          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08259          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08260          break;
08261       }
08262       /* for E911, its supposed to wait for offhook then dial
08263          the second half of the dial string */
08264       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08265          c = strchr(p->dialdest, '/');
08266          if (c)
08267             c++;
08268          else
08269             c = p->dialdest;
08270          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08271          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08272          if (strlen(p->dop.dialstr) > 4) {
08273             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08274             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08275             p->echorest[sizeof(p->echorest) - 1] = '\0';
08276             p->echobreak = 1;
08277             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08278          } else
08279             p->echobreak = 0;
08280          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08281             int saveerr = errno;
08282 
08283             x = DAHDI_ONHOOK;
08284             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08285             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08286             return NULL;
08287             }
08288          p->dialing = 1;
08289          return &p->subs[idx].f;
08290       }
08291       switch (p->sig) {
08292       case SIG_FXOLS:
08293       case SIG_FXOGS:
08294       case SIG_FXOKS:
08295          switch (ast->_state) {
08296          case AST_STATE_RINGING:
08297             dahdi_enable_ec(p);
08298             dahdi_train_ec(p);
08299             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08300             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08301             /* Make sure it stops ringing */
08302             p->subs[SUB_REAL].needringing = 0;
08303             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08304             ast_debug(1, "channel %d answered\n", p->channel);
08305 
08306             /* Cancel any running CallerID spill */
08307             ast_free(p->cidspill);
08308             p->cidspill = NULL;
08309             restore_conference(p);
08310 
08311             p->dialing = 0;
08312             p->callwaitcas = 0;
08313             if (p->confirmanswer) {
08314                /* Ignore answer if "confirm answer" is enabled */
08315                p->subs[idx].f.frametype = AST_FRAME_NULL;
08316                p->subs[idx].f.subclass.integer = 0;
08317             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08318                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08319                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08320                if (res < 0) {
08321                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08322                   p->dop.dialstr[0] = '\0';
08323                   return NULL;
08324                } else {
08325                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08326                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08327                   p->subs[idx].f.subclass.integer = 0;
08328                   p->dialing = 1;
08329                }
08330                p->dop.dialstr[0] = '\0';
08331                ast_setstate(ast, AST_STATE_DIALING);
08332             } else
08333                ast_setstate(ast, AST_STATE_UP);
08334             return &p->subs[idx].f;
08335          case AST_STATE_DOWN:
08336             ast_setstate(ast, AST_STATE_RING);
08337             ast->rings = 1;
08338             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08339             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08340             ast_debug(1, "channel %d picked up\n", p->channel);
08341             return &p->subs[idx].f;
08342          case AST_STATE_UP:
08343             /* Make sure it stops ringing */
08344             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08345             /* Okay -- probably call waiting*/
08346             if (ast_bridged_channel(p->owner))
08347                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08348             p->subs[idx].needunhold = 1;
08349             break;
08350          case AST_STATE_RESERVED:
08351             /* Start up dialtone */
08352             if (has_voicemail(p))
08353                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08354             else
08355                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08356             break;
08357          default:
08358             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08359          }
08360          break;
08361       case SIG_FXSLS:
08362       case SIG_FXSGS:
08363       case SIG_FXSKS:
08364          if (ast->_state == AST_STATE_RING) {
08365             p->ringt = p->ringt_base;
08366          }
08367 
08368          /* If we get a ring then we cannot be in
08369           * reversed polarity. So we reset to idle */
08370          ast_debug(1, "Setting IDLE polarity due "
08371             "to ring. Old polarity was %d\n",
08372             p->polarity);
08373          p->polarity = POLARITY_IDLE;
08374 
08375          /* Fall through */
08376       case SIG_EM:
08377       case SIG_EM_E1:
08378       case SIG_EMWINK:
08379       case SIG_FEATD:
08380       case SIG_FEATDMF:
08381       case SIG_FEATDMF_TA:
08382       case SIG_E911:
08383       case SIG_FGC_CAMA:
08384       case SIG_FGC_CAMAMF:
08385       case SIG_FEATB:
08386       case SIG_SF:
08387       case SIG_SFWINK:
08388       case SIG_SF_FEATD:
08389       case SIG_SF_FEATDMF:
08390       case SIG_SF_FEATB:
08391          if (ast->_state == AST_STATE_PRERING)
08392             ast_setstate(ast, AST_STATE_RING);
08393          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08394             ast_debug(1, "Ring detected\n");
08395             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08396             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08397          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08398             ast_debug(1, "Line answered\n");
08399             if (p->confirmanswer) {
08400                p->subs[idx].f.frametype = AST_FRAME_NULL;
08401                p->subs[idx].f.subclass.integer = 0;
08402             } else {
08403                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08404                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08405                ast_setstate(ast, AST_STATE_UP);
08406             }
08407          } else if (ast->_state != AST_STATE_RING)
08408             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08409          break;
08410       default:
08411          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08412       }
08413       break;
08414    case DAHDI_EVENT_RINGBEGIN:
08415       switch (p->sig) {
08416       case SIG_FXSLS:
08417       case SIG_FXSGS:
08418       case SIG_FXSKS:
08419          if (ast->_state == AST_STATE_RING) {
08420             p->ringt = p->ringt_base;
08421          }
08422          break;
08423       }
08424       break;
08425    case DAHDI_EVENT_RINGERON:
08426       break;
08427    case DAHDI_EVENT_NOALARM:
08428       switch (p->sig) {
08429 #if defined(HAVE_PRI)
08430       case SIG_PRI_LIB_HANDLE_CASES:
08431          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08432          break;
08433 #endif   /* defined(HAVE_PRI) */
08434 #if defined(HAVE_SS7)
08435       case SIG_SS7:
08436          sig_ss7_set_alarm(p->sig_pvt, 0);
08437          break;
08438 #endif   /* defined(HAVE_SS7) */
08439       default:
08440          p->inalarm = 0;
08441          break;
08442       }
08443       handle_clear_alarms(p);
08444       break;
08445    case DAHDI_EVENT_WINKFLASH:
08446       if (p->inalarm) break;
08447       if (p->radio) break;
08448       if (p->oprmode < 0) break;
08449       if (p->oprmode > 1)
08450       {
08451          struct dahdi_params par;
08452 
08453          memset(&par, 0, sizeof(par));
08454          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08455          {
08456             if (!par.rxisoffhook)
08457             {
08458                /* Make sure it stops ringing */
08459                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08460                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08461                save_conference(p);
08462                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08463             }
08464          }
08465          break;
08466       }
08467       /* Remember last time we got a flash-hook */
08468       p->flashtime = ast_tvnow();
08469       switch (mysig) {
08470       case SIG_FXOLS:
08471       case SIG_FXOGS:
08472       case SIG_FXOKS:
08473          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08474             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08475 
08476          /* Cancel any running CallerID spill */
08477          ast_free(p->cidspill);
08478          p->cidspill = NULL;
08479          restore_conference(p);
08480          p->callwaitcas = 0;
08481 
08482          if (idx != SUB_REAL) {
08483             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08484             goto winkflashdone;
08485          }
08486 
08487          if (p->subs[SUB_CALLWAIT].owner) {
08488             /* Swap to call-wait */
08489             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08490             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08491             p->owner = p->subs[SUB_REAL].owner;
08492             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08493             if (p->owner->_state == AST_STATE_RINGING) {
08494                ast_setstate(p->owner, AST_STATE_UP);
08495                p->subs[SUB_REAL].needanswer = 1;
08496             }
08497             p->callwaitingrepeat = 0;
08498             p->cidcwexpire = 0;
08499             p->cid_suppress_expire = 0;
08500             /* Start music on hold if appropriate */
08501             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08502                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08503                   S_OR(p->mohsuggest, NULL),
08504                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08505             }
08506             p->subs[SUB_CALLWAIT].needhold = 1;
08507             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08508                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08509                   S_OR(p->mohsuggest, NULL),
08510                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08511             }
08512             p->subs[SUB_REAL].needunhold = 1;
08513          } else if (!p->subs[SUB_THREEWAY].owner) {
08514             if (!p->threewaycalling) {
08515                /* Just send a flash if no 3-way calling */
08516                p->subs[SUB_REAL].needflash = 1;
08517                goto winkflashdone;
08518             } else if (!check_for_conference(p)) {
08519                char cid_num[256];
08520                char cid_name[256];
08521 
08522                cid_num[0] = 0;
08523                cid_name[0] = 0;
08524                if (p->dahditrcallerid && p->owner) {
08525                   if (p->owner->caller.id.number.valid
08526                      && p->owner->caller.id.number.str) {
08527                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08528                         sizeof(cid_num));
08529                   }
08530                   if (p->owner->caller.id.name.valid
08531                      && p->owner->caller.id.name.str) {
08532                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08533                         sizeof(cid_name));
08534                   }
08535                }
08536                /* XXX This section needs much more error checking!!! XXX */
08537                /* Start a 3-way call if feasible */
08538                if (!((ast->pbx) ||
08539                   (ast->_state == AST_STATE_UP) ||
08540                   (ast->_state == AST_STATE_RING))) {
08541                   ast_debug(1, "Flash when call not up or ringing\n");
08542                   goto winkflashdone;
08543                }
08544                if (alloc_sub(p, SUB_THREEWAY)) {
08545                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08546                   goto winkflashdone;
08547                }
08548 
08549                /*
08550                 * Make new channel
08551                 *
08552                 * We cannot hold the p or ast locks while creating a new
08553                 * channel.
08554                 */
08555                ast_mutex_unlock(&p->lock);
08556                ast_channel_unlock(ast);
08557                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08558                ast_channel_lock(ast);
08559                ast_mutex_lock(&p->lock);
08560                if (p->dahditrcallerid) {
08561                   if (!p->origcid_num)
08562                      p->origcid_num = ast_strdup(p->cid_num);
08563                   if (!p->origcid_name)
08564                      p->origcid_name = ast_strdup(p->cid_name);
08565                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08566                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08567                }
08568                /* Swap things around between the three-way and real call */
08569                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08570                /* Disable echo canceller for better dialing */
08571                dahdi_disable_ec(p);
08572                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08573                if (res)
08574                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08575                p->owner = chan;
08576                if (!chan) {
08577                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08578                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08579                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08580                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08581                   dahdi_enable_ec(p);
08582                   ast_hangup(chan);
08583                } else {
08584                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08585 
08586                   /* Start music on hold if appropriate */
08587                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08588                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08589                         S_OR(p->mohsuggest, NULL),
08590                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08591                   }
08592                   p->subs[SUB_THREEWAY].needhold = 1;
08593                }
08594             }
08595          } else {
08596             /* Already have a 3 way call */
08597             if (p->subs[SUB_THREEWAY].inthreeway) {
08598                /* Call is already up, drop the last person */
08599                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08600                /* If the primary call isn't answered yet, use it */
08601                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08602                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08603                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08604                   p->owner = p->subs[SUB_REAL].owner;
08605                }
08606                /* Drop the last call and stop the conference */
08607                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08608                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08609                p->subs[SUB_REAL].inthreeway = 0;
08610                p->subs[SUB_THREEWAY].inthreeway = 0;
08611             } else {
08612                /* Lets see what we're up to */
08613                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08614                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08615                   int otherindex = SUB_THREEWAY;
08616 
08617                   ast_verb(3, "Building conference call with %s and %s\n",
08618                      p->subs[SUB_THREEWAY].owner->name,
08619                      p->subs[SUB_REAL].owner->name);
08620                   /* Put them in the threeway, and flip */
08621                   p->subs[SUB_THREEWAY].inthreeway = 1;
08622                   p->subs[SUB_REAL].inthreeway = 1;
08623                   if (ast->_state == AST_STATE_UP) {
08624                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08625                      otherindex = SUB_REAL;
08626                   }
08627                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08628                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08629                   p->subs[otherindex].needunhold = 1;
08630                   p->owner = p->subs[SUB_REAL].owner;
08631                } else {
08632                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08633                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08634                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08635                   p->owner = p->subs[SUB_REAL].owner;
08636                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08637                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08638                   p->subs[SUB_REAL].needunhold = 1;
08639                   dahdi_enable_ec(p);
08640                }
08641             }
08642          }
08643 winkflashdone:
08644          update_conf(p);
08645          break;
08646       case SIG_EM:
08647       case SIG_EM_E1:
08648       case SIG_FEATD:
08649       case SIG_SF:
08650       case SIG_SFWINK:
08651       case SIG_SF_FEATD:
08652       case SIG_FXSLS:
08653       case SIG_FXSGS:
08654          if (p->dialing)
08655             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08656          else
08657             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08658          break;
08659       case SIG_FEATDMF_TA:
08660          switch (p->whichwink) {
08661          case 0:
08662             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08663                S_COR(p->owner->caller.ani.number.valid,
08664                   p->owner->caller.ani.number.str, ""));
08665             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08666                p->owner->caller.ani2,
08667                S_COR(p->owner->caller.ani.number.valid,
08668                   p->owner->caller.ani.number.str, ""));
08669             break;
08670          case 1:
08671             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08672             break;
08673          case 2:
08674             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08675             return NULL;
08676          }
08677          p->whichwink++;
08678          /* Fall through */
08679       case SIG_FEATDMF:
08680       case SIG_E911:
08681       case SIG_FGC_CAMAMF:
08682       case SIG_FGC_CAMA:
08683       case SIG_FEATB:
08684       case SIG_SF_FEATDMF:
08685       case SIG_SF_FEATB:
08686       case SIG_EMWINK:
08687          /* FGD MF and EMWINK *Must* wait for wink */
08688          if (!ast_strlen_zero(p->dop.dialstr)) {
08689             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08690             if (res < 0) {
08691                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08692                p->dop.dialstr[0] = '\0';
08693                return NULL;
08694             } else
08695                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08696          }
08697          p->dop.dialstr[0] = '\0';
08698          break;
08699       default:
08700          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08701       }
08702       break;
08703    case DAHDI_EVENT_HOOKCOMPLETE:
08704       if (p->inalarm) break;
08705       if ((p->radio || (p->oprmode < 0))) break;
08706       if (p->waitingfordt.tv_sec) break;
08707       switch (mysig) {
08708       case SIG_FXSLS:  /* only interesting for FXS */
08709       case SIG_FXSGS:
08710       case SIG_FXSKS:
08711       case SIG_EM:
08712       case SIG_EM_E1:
08713       case SIG_EMWINK:
08714       case SIG_FEATD:
08715       case SIG_SF:
08716       case SIG_SFWINK:
08717       case SIG_SF_FEATD:
08718          if (!ast_strlen_zero(p->dop.dialstr)) {
08719             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08720             if (res < 0) {
08721                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08722                p->dop.dialstr[0] = '\0';
08723                return NULL;
08724             } else
08725                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08726          }
08727          p->dop.dialstr[0] = '\0';
08728          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08729          break;
08730       case SIG_FEATDMF:
08731       case SIG_FEATDMF_TA:
08732       case SIG_E911:
08733       case SIG_FGC_CAMA:
08734       case SIG_FGC_CAMAMF:
08735       case SIG_FEATB:
08736       case SIG_SF_FEATDMF:
08737       case SIG_SF_FEATB:
08738          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08739          break;
08740       default:
08741          break;
08742       }
08743       break;
08744    case DAHDI_EVENT_POLARITY:
08745       /*
08746        * If we get a Polarity Switch event, check to see
08747        * if we should change the polarity state and
08748        * mark the channel as UP or if this is an indication
08749        * of remote end disconnect.
08750        */
08751       if (p->polarity == POLARITY_IDLE) {
08752          p->polarity = POLARITY_REV;
08753          if (p->answeronpolarityswitch &&
08754             ((ast->_state == AST_STATE_DIALING) ||
08755             (ast->_state == AST_STATE_RINGING))) {
08756             ast_debug(1, "Answering on polarity switch!\n");
08757             ast_setstate(p->owner, AST_STATE_UP);
08758             if (p->hanguponpolarityswitch) {
08759                p->polaritydelaytv = ast_tvnow();
08760             }
08761          } else
08762             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08763       }
08764       /* Removed else statement from here as it was preventing hangups from ever happening*/
08765       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08766       if (p->hanguponpolarityswitch &&
08767          (p->polarityonanswerdelay > 0) &&
08768          (p->polarity == POLARITY_REV) &&
08769          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08770          /* Added log_debug information below to provide a better indication of what is going on */
08771          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) );
08772 
08773          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08774             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08775             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08776             p->polarity = POLARITY_IDLE;
08777          } else
08778             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);
08779 
08780       } else {
08781          p->polarity = POLARITY_IDLE;
08782          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08783       }
08784       /* Added more log_debug information below to provide a better indication of what is going on */
08785       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) );
08786       break;
08787    default:
08788       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08789    }
08790    return &p->subs[idx].f;
08791 }
08792 
08793 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08794 {
08795    int res;
08796    int idx;
08797    struct ast_frame *f;
08798    int usedindex = -1;
08799    struct dahdi_pvt *p = ast->tech_pvt;
08800 
08801    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08802       idx = SUB_REAL;
08803    }
08804 
08805    p->subs[idx].f.frametype = AST_FRAME_NULL;
08806    p->subs[idx].f.datalen = 0;
08807    p->subs[idx].f.samples = 0;
08808    p->subs[idx].f.mallocd = 0;
08809    p->subs[idx].f.offset = 0;
08810    p->subs[idx].f.subclass.integer = 0;
08811    p->subs[idx].f.delivery = ast_tv(0,0);
08812    p->subs[idx].f.src = "dahdi_exception";
08813    p->subs[idx].f.data.ptr = NULL;
08814 
08815 
08816    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08817       /* If nobody owns us, absorb the event appropriately, otherwise
08818          we loop indefinitely.  This occurs when, during call waiting, the
08819          other end hangs up our channel so that it no longer exists, but we
08820          have neither FLASH'd nor ONHOOK'd to signify our desire to
08821          change to the other channel. */
08822       if (p->fake_event) {
08823          res = p->fake_event;
08824          p->fake_event = 0;
08825       } else
08826          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08827       /* Switch to real if there is one and this isn't something really silly... */
08828       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08829          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08830          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08831          p->owner = p->subs[SUB_REAL].owner;
08832          if (p->owner && ast_bridged_channel(p->owner))
08833             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08834          p->subs[SUB_REAL].needunhold = 1;
08835       }
08836       switch (res) {
08837       case DAHDI_EVENT_ONHOOK:
08838          dahdi_disable_ec(p);
08839          if (p->owner) {
08840             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08841             dahdi_ring_phone(p);
08842             p->callwaitingrepeat = 0;
08843             p->cidcwexpire = 0;
08844             p->cid_suppress_expire = 0;
08845          } else
08846             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08847          update_conf(p);
08848          break;
08849       case DAHDI_EVENT_RINGOFFHOOK:
08850          dahdi_enable_ec(p);
08851          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08852          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08853             p->subs[SUB_REAL].needanswer = 1;
08854             p->dialing = 0;
08855          }
08856          break;
08857       case DAHDI_EVENT_HOOKCOMPLETE:
08858       case DAHDI_EVENT_RINGERON:
08859       case DAHDI_EVENT_RINGEROFF:
08860          /* Do nothing */
08861          break;
08862       case DAHDI_EVENT_WINKFLASH:
08863          p->flashtime = ast_tvnow();
08864          if (p->owner) {
08865             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08866             if (p->owner->_state != AST_STATE_UP) {
08867                /* Answer if necessary */
08868                usedindex = dahdi_get_index(p->owner, p, 0);
08869                if (usedindex > -1) {
08870                   p->subs[usedindex].needanswer = 1;
08871                }
08872                ast_setstate(p->owner, AST_STATE_UP);
08873             }
08874             p->callwaitingrepeat = 0;
08875             p->cidcwexpire = 0;
08876             p->cid_suppress_expire = 0;
08877             if (ast_bridged_channel(p->owner))
08878                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08879             p->subs[SUB_REAL].needunhold = 1;
08880          } else
08881             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08882          update_conf(p);
08883          break;
08884       default:
08885          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08886       }
08887       f = &p->subs[idx].f;
08888       return f;
08889    }
08890    if (!(p->radio || (p->oprmode < 0)))
08891       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08892    /* If it's not us, return NULL immediately */
08893    if (ast != p->owner) {
08894       if (p->owner) {
08895          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08896       }
08897       f = &p->subs[idx].f;
08898       return f;
08899    }
08900 
08901    f = dahdi_handle_event(ast);
08902    if (!f) {
08903       const char *name = ast_strdupa(ast->name);
08904 
08905       /* Tell the CDR this DAHDI device hung up */
08906       ast_mutex_unlock(&p->lock);
08907       ast_channel_unlock(ast);
08908       ast_set_hangupsource(ast, name, 0);
08909       ast_channel_lock(ast);
08910       ast_mutex_lock(&p->lock);
08911    }
08912    return f;
08913 }
08914 
08915 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08916 {
08917    struct dahdi_pvt *p = ast->tech_pvt;
08918    struct ast_frame *f;
08919    ast_mutex_lock(&p->lock);
08920    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08921       struct analog_pvt *analog_p = p->sig_pvt;
08922       f = analog_exception(analog_p, ast);
08923    } else {
08924       f = __dahdi_exception(ast);
08925    }
08926    ast_mutex_unlock(&p->lock);
08927    return f;
08928 }
08929 
08930 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08931 {
08932    struct dahdi_pvt *p;
08933    int res;
08934    int idx;
08935    void *readbuf;
08936    struct ast_frame *f;
08937 
08938    /*
08939     * For analog channels, we must do deadlock avoidance because
08940     * analog ports can have more than one Asterisk channel using
08941     * the same private structure.
08942     */
08943    p = ast->tech_pvt;
08944    while (ast_mutex_trylock(&p->lock)) {
08945       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08946 
08947       /*
08948        * Check to see if the channel is still associated with the same
08949        * private structure.  While the Asterisk channel was unlocked
08950        * the following events may have occured:
08951        *
08952        * 1) A masquerade may have associated the channel with another
08953        * technology or private structure.
08954        *
08955        * 2) For PRI calls, call signaling could change the channel
08956        * association to another B channel (private structure).
08957        */
08958       if (ast->tech_pvt != p) {
08959          /* The channel is no longer associated.  Quit gracefully. */
08960          return &ast_null_frame;
08961       }
08962    }
08963 
08964    idx = dahdi_get_index(ast, p, 0);
08965 
08966    /* Hang up if we don't really exist */
08967    if (idx < 0)   {
08968       ast_log(LOG_WARNING, "We don't exist?\n");
08969       ast_mutex_unlock(&p->lock);
08970       return NULL;
08971    }
08972 
08973    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08974       ast_mutex_unlock(&p->lock);
08975       return NULL;
08976    }
08977 
08978    p->subs[idx].f.frametype = AST_FRAME_NULL;
08979    p->subs[idx].f.datalen = 0;
08980    p->subs[idx].f.samples = 0;
08981    p->subs[idx].f.mallocd = 0;
08982    p->subs[idx].f.offset = 0;
08983    p->subs[idx].f.subclass.integer = 0;
08984    p->subs[idx].f.delivery = ast_tv(0,0);
08985    p->subs[idx].f.src = "dahdi_read";
08986    p->subs[idx].f.data.ptr = NULL;
08987 
08988    /* make sure it sends initial key state as first frame */
08989    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08990    {
08991       struct dahdi_params ps;
08992 
08993       memset(&ps, 0, sizeof(ps));
08994       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08995          ast_mutex_unlock(&p->lock);
08996          return NULL;
08997       }
08998       p->firstradio = 1;
08999       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09000       if (ps.rxisoffhook)
09001       {
09002          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09003       }
09004       else
09005       {
09006          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09007       }
09008       ast_mutex_unlock(&p->lock);
09009       return &p->subs[idx].f;
09010    }
09011    if (p->ringt > 0) {
09012       if (!(--p->ringt)) {
09013          ast_mutex_unlock(&p->lock);
09014          return NULL;
09015       }
09016    }
09017 
09018 #ifdef HAVE_OPENR2
09019    if (p->mfcr2) {
09020       openr2_chan_process_event(p->r2chan);
09021       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09022          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09023          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09024           * now enqueue a progress frame to bridge the media up */
09025          if (p->mfcr2_call_accepted &&
09026              !p->mfcr2_progress && 
09027              ast->_state == AST_STATE_RINGING) {
09028             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09029             ast_queue_frame(p->owner, &f);
09030             p->mfcr2_progress = 1;
09031          }
09032       }
09033    }
09034 #endif
09035 
09036    if (p->subs[idx].needringing) {
09037       /* Send ringing frame if requested */
09038       p->subs[idx].needringing = 0;
09039       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09040       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09041       ast_setstate(ast, AST_STATE_RINGING);
09042       ast_mutex_unlock(&p->lock);
09043       return &p->subs[idx].f;
09044    }
09045 
09046    if (p->subs[idx].needbusy) {
09047       /* Send busy frame if requested */
09048       p->subs[idx].needbusy = 0;
09049       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09050       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09051       ast_mutex_unlock(&p->lock);
09052       return &p->subs[idx].f;
09053    }
09054 
09055    if (p->subs[idx].needcongestion) {
09056       /* Send congestion frame if requested */
09057       p->subs[idx].needcongestion = 0;
09058       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09059       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09060       ast_mutex_unlock(&p->lock);
09061       return &p->subs[idx].f;
09062    }
09063 
09064    if (p->subs[idx].needanswer) {
09065       /* Send answer frame if requested */
09066       p->subs[idx].needanswer = 0;
09067       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09069       ast_mutex_unlock(&p->lock);
09070       return &p->subs[idx].f;
09071    }
09072 #ifdef HAVE_OPENR2
09073    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09074       /* openr2 took care of reading and handling any event
09075         (needanswer, needbusy etc), if we continue we will read()
09076         twice, lets just return a null frame. This should only
09077         happen when openr2 is dialing out */
09078       ast_mutex_unlock(&p->lock);
09079       return &ast_null_frame;
09080    }
09081 #endif
09082 
09083    if (p->subs[idx].needflash) {
09084       /* Send answer frame if requested */
09085       p->subs[idx].needflash = 0;
09086       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09087       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09088       ast_mutex_unlock(&p->lock);
09089       return &p->subs[idx].f;
09090    }
09091 
09092    if (p->subs[idx].needhold) {
09093       /* Send answer frame if requested */
09094       p->subs[idx].needhold = 0;
09095       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09096       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09097       ast_mutex_unlock(&p->lock);
09098       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09099       return &p->subs[idx].f;
09100    }
09101 
09102    if (p->subs[idx].needunhold) {
09103       /* Send answer frame if requested */
09104       p->subs[idx].needunhold = 0;
09105       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09106       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09107       ast_mutex_unlock(&p->lock);
09108       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09109       return &p->subs[idx].f;
09110    }
09111 
09112    /*
09113     * If we have a fake_event, fake an exception to handle it only
09114     * if this channel owns the private.
09115     */
09116    if (p->fake_event && p->owner == ast) {
09117       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09118          struct analog_pvt *analog_p = p->sig_pvt;
09119 
09120          f = analog_exception(analog_p, ast);
09121       } else {
09122          f = __dahdi_exception(ast);
09123       }
09124       ast_mutex_unlock(&p->lock);
09125       return f;
09126    }
09127 
09128    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09129       if (!p->subs[idx].linear) {
09130          p->subs[idx].linear = 1;
09131          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09132          if (res)
09133             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09134       }
09135    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09136       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09137       if (p->subs[idx].linear) {
09138          p->subs[idx].linear = 0;
09139          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09140          if (res)
09141             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09142       }
09143    } else {
09144       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09145       ast_mutex_unlock(&p->lock);
09146       return NULL;
09147    }
09148    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09149    CHECK_BLOCKING(ast);
09150    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09151    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09152    /* Check for hangup */
09153    if (res < 0) {
09154       f = NULL;
09155       if (res == -1) {
09156          if (errno == EAGAIN) {
09157             /* Return "NULL" frame if there is nobody there */
09158             ast_mutex_unlock(&p->lock);
09159             return &p->subs[idx].f;
09160          } else if (errno == ELAST) {
09161             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09162                struct analog_pvt *analog_p = p->sig_pvt;
09163                f = analog_exception(analog_p, ast);
09164             } else {
09165                f = __dahdi_exception(ast);
09166             }
09167          } else
09168             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09169       }
09170       ast_mutex_unlock(&p->lock);
09171       return f;
09172    }
09173    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09174       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09175       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09176          struct analog_pvt *analog_p = p->sig_pvt;
09177          f = analog_exception(analog_p, ast);
09178       } else {
09179          f = __dahdi_exception(ast);
09180       }
09181       ast_mutex_unlock(&p->lock);
09182       return f;
09183    }
09184    if (p->tdd) { /* if in TDD mode, see if we receive that */
09185       int c;
09186 
09187       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09188       if (c < 0) {
09189          ast_debug(1,"tdd_feed failed\n");
09190          ast_mutex_unlock(&p->lock);
09191          return NULL;
09192       }
09193       if (c) { /* if a char to return */
09194          p->subs[idx].f.subclass.integer = 0;
09195          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09196          p->subs[idx].f.mallocd = 0;
09197          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09198          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09199          p->subs[idx].f.datalen = 1;
09200          *((char *) p->subs[idx].f.data.ptr) = c;
09201          ast_mutex_unlock(&p->lock);
09202          return &p->subs[idx].f;
09203       }
09204    }
09205    if (idx == SUB_REAL) {
09206       /* Ensure the CW timers decrement only on a single subchannel */
09207       if (p->cidcwexpire) {
09208          if (!--p->cidcwexpire) {
09209             /* Expired CID/CW */
09210             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09211             restore_conference(p);
09212          }
09213       }
09214       if (p->cid_suppress_expire) {
09215          --p->cid_suppress_expire;
09216       }
09217       if (p->callwaitingrepeat) {
09218          if (!--p->callwaitingrepeat) {
09219             /* Expired, Repeat callwaiting tone */
09220             ++p->callwaitrings;
09221             dahdi_callwait(ast);
09222          }
09223       }
09224    }
09225    if (p->subs[idx].linear) {
09226       p->subs[idx].f.datalen = READ_SIZE * 2;
09227    } else
09228       p->subs[idx].f.datalen = READ_SIZE;
09229 
09230    /* Handle CallerID Transmission */
09231    if ((p->owner == ast) && p->cidspill) {
09232       send_callerid(p);
09233    }
09234 
09235    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09236    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09237    p->subs[idx].f.samples = READ_SIZE;
09238    p->subs[idx].f.mallocd = 0;
09239    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09240    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09241 #if 0
09242    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09243 #endif
09244    if (p->dialing ||  p->radio || /* Transmitting something */
09245       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09246       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09247       ) {
09248       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09249          don't send anything */
09250       p->subs[idx].f.frametype = AST_FRAME_NULL;
09251       p->subs[idx].f.subclass.integer = 0;
09252       p->subs[idx].f.samples = 0;
09253       p->subs[idx].f.mallocd = 0;
09254       p->subs[idx].f.offset = 0;
09255       p->subs[idx].f.data.ptr = NULL;
09256       p->subs[idx].f.datalen= 0;
09257    }
09258    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09259       /* Perform busy detection etc on the dahdi line */
09260       int mute;
09261 
09262       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09263 
09264       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09265       mute = ast_dsp_was_muted(p->dsp);
09266       if (p->muting != mute) {
09267          p->muting = mute;
09268          dahdi_confmute(p, mute);
09269       }
09270 
09271       if (f) {
09272          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09273             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09274                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09275                   a busy */
09276                ast_frfree(f);
09277                f = NULL;
09278             }
09279          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09280             || f->frametype == AST_FRAME_DTMF_END) {
09281 #ifdef HAVE_PRI
09282             if (dahdi_sig_pri_lib_handles(p->sig)
09283                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09284                && p->pri
09285                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09286                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09287                /* Don't accept in-band DTMF when in overlap dial mode */
09288                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09289                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09290                   f->subclass.integer, f->subclass.integer, ast->name);
09291 
09292                f->frametype = AST_FRAME_NULL;
09293                f->subclass.integer = 0;
09294             }
09295 #endif
09296             /* DSP clears us of being pulse */
09297             p->pulsedial = 0;
09298          } else if (p->waitingfordt.tv_sec) {
09299             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09300                p->waitingfordt.tv_sec = 0;
09301                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09302                ast_frfree(f);
09303                f = NULL;
09304             } else if (f->frametype == AST_FRAME_VOICE) {
09305                f->frametype = AST_FRAME_NULL;
09306                f->subclass.integer = 0;
09307                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) {
09308                   p->waitingfordt.tv_sec = 0;
09309                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09310                   ast_dsp_set_features(p->dsp, p->dsp_features);
09311                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09312                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09313                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09314                      if (res < 0) {
09315                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09316                         p->dop.dialstr[0] = '\0';
09317                         ast_mutex_unlock(&p->lock);
09318                         ast_frfree(f);
09319                         return NULL;
09320                      } else {
09321                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09322                         p->dialing = 1;
09323                         p->dop.dialstr[0] = '\0';
09324                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09325                         ast_setstate(ast, AST_STATE_DIALING);
09326                      }
09327                   }
09328                }
09329             }
09330          }
09331       }
09332    } else
09333       f = &p->subs[idx].f;
09334 
09335    if (f) {
09336       switch (f->frametype) {
09337       case AST_FRAME_DTMF_BEGIN:
09338       case AST_FRAME_DTMF_END:
09339          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09340             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09341          } else {
09342             dahdi_handle_dtmf(ast, idx, &f);
09343          }
09344          break;
09345       case AST_FRAME_VOICE:
09346          if (p->cidspill || p->cid_suppress_expire) {
09347             /* We are/were sending a caller id spill.  Suppress any echo. */
09348             p->subs[idx].f.frametype = AST_FRAME_NULL;
09349             p->subs[idx].f.subclass.integer = 0;
09350             p->subs[idx].f.samples = 0;
09351             p->subs[idx].f.mallocd = 0;
09352             p->subs[idx].f.offset = 0;
09353             p->subs[idx].f.data.ptr = NULL;
09354             p->subs[idx].f.datalen= 0;
09355          }
09356          break;
09357       default:
09358          break;
09359       }
09360    }
09361 
09362    ast_mutex_unlock(&p->lock);
09363    return f;
09364 }
09365 
09366 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09367 {
09368    int sent=0;
09369    int size;
09370    int res;
09371    int fd;
09372    fd = p->subs[idx].dfd;
09373    while (len) {
09374       size = len;
09375       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09376          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09377       res = write(fd, buf, size);
09378       if (res != size) {
09379          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09380          return sent;
09381       }
09382       len -= size;
09383       buf += size;
09384    }
09385    return sent;
09386 }
09387 
09388 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09389 {
09390    struct dahdi_pvt *p = ast->tech_pvt;
09391    int res;
09392    int idx;
09393    idx = dahdi_get_index(ast, p, 0);
09394    if (idx < 0) {
09395       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09396       return -1;
09397    }
09398 
09399    /* Write a frame of (presumably voice) data */
09400    if (frame->frametype != AST_FRAME_VOICE) {
09401       if (frame->frametype != AST_FRAME_IMAGE)
09402          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09403       return 0;
09404    }
09405    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09406       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09407       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09408       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09409       return -1;
09410    }
09411    if (p->dialing) {
09412       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09413       return 0;
09414    }
09415    if (!p->owner) {
09416       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09417       return 0;
09418    }
09419    if (p->cidspill) {
09420       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09421          ast->name);
09422       return 0;
09423    }
09424    /* Return if it's not valid data */
09425    if (!frame->data.ptr || !frame->datalen)
09426       return 0;
09427 
09428    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09429       if (!p->subs[idx].linear) {
09430          p->subs[idx].linear = 1;
09431          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09432          if (res)
09433             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09434       }
09435       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09436    } else {
09437       /* x-law already */
09438       if (p->subs[idx].linear) {
09439          p->subs[idx].linear = 0;
09440          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09441          if (res)
09442             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09443       }
09444       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09445    }
09446    if (res < 0) {
09447       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09448       return -1;
09449    }
09450    return 0;
09451 }
09452 
09453 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09454 {
09455    struct dahdi_pvt *p = chan->tech_pvt;
09456    int res=-1;
09457    int idx;
09458    int func = DAHDI_FLASH;
09459 
09460    ast_mutex_lock(&p->lock);
09461    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09462    switch (p->sig) {
09463 #if defined(HAVE_PRI)
09464    case SIG_PRI_LIB_HANDLE_CASES:
09465       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09466       ast_mutex_unlock(&p->lock);
09467       return res;
09468 #endif   /* defined(HAVE_PRI) */
09469 #if defined(HAVE_SS7)
09470    case SIG_SS7:
09471       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09472       ast_mutex_unlock(&p->lock);
09473       return res;
09474 #endif   /* defined(HAVE_SS7) */
09475    default:
09476       break;
09477    }
09478 #ifdef HAVE_OPENR2
09479    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09480       ast_mutex_unlock(&p->lock);
09481       /* if this is an R2 call and the call is not yet accepted, we don't want the
09482          tone indications to mess up with the MF tones */
09483       return 0;
09484    }
09485 #endif
09486    idx = dahdi_get_index(chan, p, 0);
09487    if (idx == SUB_REAL) {
09488       switch (condition) {
09489       case AST_CONTROL_BUSY:
09490          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09491          break;
09492       case AST_CONTROL_RINGING:
09493          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09494 
09495          if (chan->_state != AST_STATE_UP) {
09496             if ((chan->_state != AST_STATE_RING) ||
09497                ((p->sig != SIG_FXSKS) &&
09498              (p->sig != SIG_FXSLS) &&
09499              (p->sig != SIG_FXSGS)))
09500             ast_setstate(chan, AST_STATE_RINGING);
09501          }
09502          break;
09503       case AST_CONTROL_INCOMPLETE:
09504          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09505          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09506          res = 0;
09507          break;
09508       case AST_CONTROL_PROCEEDING:
09509          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09510          /* don't continue in ast_indicate */
09511          res = 0;
09512          break;
09513       case AST_CONTROL_PROGRESS:
09514          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09515          /* don't continue in ast_indicate */
09516          res = 0;
09517          break;
09518       case AST_CONTROL_CONGESTION:
09519          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09520          switch (chan->hangupcause) {
09521          case AST_CAUSE_USER_BUSY:
09522          case AST_CAUSE_NORMAL_CLEARING:
09523          case 0:/* Cause has not been set. */
09524             /* Supply a more appropriate cause. */
09525             chan->hangupcause = AST_CAUSE_CONGESTION;
09526             break;
09527          default:
09528             break;
09529          }
09530          break;
09531       case AST_CONTROL_HOLD:
09532          ast_moh_start(chan, data, p->mohinterpret);
09533          break;
09534       case AST_CONTROL_UNHOLD:
09535          ast_moh_stop(chan);
09536          break;
09537       case AST_CONTROL_RADIO_KEY:
09538          if (p->radio)
09539             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09540          res = 0;
09541          break;
09542       case AST_CONTROL_RADIO_UNKEY:
09543          if (p->radio)
09544             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09545          res = 0;
09546          break;
09547       case AST_CONTROL_FLASH:
09548          /* flash hookswitch */
09549          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09550             /* Clear out the dial buffer */
09551             p->dop.dialstr[0] = '\0';
09552             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09553                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09554                   chan->name, strerror(errno));
09555             } else
09556                res = 0;
09557          } else
09558             res = 0;
09559          break;
09560       case AST_CONTROL_SRCUPDATE:
09561          res = 0;
09562          break;
09563       case -1:
09564          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09565          break;
09566       }
09567    } else {
09568       res = 0;
09569    }
09570    ast_mutex_unlock(&p->lock);
09571    return res;
09572 }
09573 
09574 #if defined(HAVE_PRI)
09575 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09576 #else
09577 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09578 #endif   /* defined(HAVE_PRI) */
09579 {
09580    struct ast_str *chan_name;
09581    int x, y;
09582 
09583    /* Create the new channel name tail. */
09584    if (!(chan_name = ast_str_create(32))) {
09585       return NULL;
09586    }
09587    if (i->channel == CHAN_PSEUDO) {
09588       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09589 #if defined(HAVE_PRI)
09590    } else if (i->pri) {
09591       ast_mutex_lock(&i->pri->lock);
09592       y = ++i->pri->new_chan_seq;
09593       if (is_outgoing) {
09594          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09595          address[0] = '\0';
09596       } else if (ast_strlen_zero(i->cid_subaddr)) {
09597          /* Put in caller-id number only since there is no subaddress. */
09598          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09599       } else {
09600          /* Put in caller-id number and subaddress. */
09601          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09602             i->cid_subaddr, y);
09603       }
09604       ast_mutex_unlock(&i->pri->lock);
09605 #endif   /* defined(HAVE_PRI) */
09606    } else {
09607       y = 1;
09608       do {
09609          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09610          for (x = 0; x < 3; ++x) {
09611             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09612                i->subs[x].owner->name + 6)) {
09613                break;
09614             }
09615          }
09616          ++y;
09617       } while (x < 3);
09618    }
09619    return chan_name;
09620 }
09621 
09622 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09623 {
09624    struct ast_channel *tmp;
09625    format_t deflaw;
09626    int x;
09627    int features;
09628    struct ast_str *chan_name;
09629    struct ast_variable *v;
09630    char *dashptr;
09631    char device_name[AST_CHANNEL_NAME];
09632 
09633    if (i->subs[idx].owner) {
09634       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09635       return NULL;
09636    }
09637 
09638 #if defined(HAVE_PRI)
09639    /*
09640     * The dnid has been stuffed with the called-number[:subaddress]
09641     * by dahdi_request() for outgoing calls.
09642     */
09643    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09644 #else
09645    chan_name = create_channel_name(i);
09646 #endif   /* defined(HAVE_PRI) */
09647    if (!chan_name) {
09648       return NULL;
09649    }
09650 
09651    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));
09652    ast_free(chan_name);
09653    if (!tmp)
09654       return NULL;
09655    tmp->tech = &dahdi_tech;
09656 #if defined(HAVE_PRI)
09657    if (i->pri) {
09658       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09659    }
09660 #endif   /* defined(HAVE_PRI) */
09661    ast_channel_cc_params_init(tmp, i->cc_params);
09662    if (law) {
09663       i->law = law;
09664       if (law == DAHDI_LAW_ALAW) {
09665          deflaw = AST_FORMAT_ALAW;
09666       } else {
09667          deflaw = AST_FORMAT_ULAW;
09668       }
09669    } else {
09670       switch (i->sig) {
09671       case SIG_PRI_LIB_HANDLE_CASES:
09672          /* Make sure companding law is known. */
09673          i->law = (i->law_default == DAHDI_LAW_ALAW)
09674             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09675          break;
09676       default:
09677          i->law = i->law_default;
09678          break;
09679       }
09680       if (i->law_default == DAHDI_LAW_ALAW) {
09681          deflaw = AST_FORMAT_ALAW;
09682       } else {
09683          deflaw = AST_FORMAT_ULAW;
09684       }
09685    }
09686    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09687    tmp->nativeformats = deflaw;
09688    /* Start out assuming ulaw since it's smaller :) */
09689    tmp->rawreadformat = deflaw;
09690    tmp->readformat = deflaw;
09691    tmp->rawwriteformat = deflaw;
09692    tmp->writeformat = deflaw;
09693    i->subs[idx].linear = 0;
09694    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09695    features = 0;
09696    if (idx == SUB_REAL) {
09697       if (i->busydetect && CANBUSYDETECT(i))
09698          features |= DSP_FEATURE_BUSY_DETECT;
09699       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09700          features |= DSP_FEATURE_CALL_PROGRESS;
09701       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09702          features |= DSP_FEATURE_WAITDIALTONE;
09703       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09704          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09705          features |= DSP_FEATURE_FAX_DETECT;
09706       }
09707       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09708       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09709          i->hardwaredtmf = 0;
09710          features |= DSP_FEATURE_DIGIT_DETECT;
09711       } else if (NEED_MFDETECT(i)) {
09712          i->hardwaredtmf = 1;
09713          features |= DSP_FEATURE_DIGIT_DETECT;
09714       }
09715    }
09716    if (features) {
09717       if (i->dsp) {
09718          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09719       } else {
09720          if (i->channel != CHAN_PSEUDO)
09721             i->dsp = ast_dsp_new();
09722          else
09723             i->dsp = NULL;
09724          if (i->dsp) {
09725             i->dsp_features = features;
09726 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09727             /* We cannot do progress detection until receive PROGRESS message */
09728             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09729                /* Remember requested DSP features, don't treat
09730                   talking as ANSWER */
09731                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09732                features = 0;
09733             }
09734 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09735             ast_dsp_set_features(i->dsp, features);
09736             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09737             if (!ast_strlen_zero(progzone))
09738                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09739             if (i->busydetect && CANBUSYDETECT(i)) {
09740                ast_dsp_set_busy_count(i->dsp, i->busycount);
09741                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09742             }
09743          }
09744       }
09745    }
09746 
09747    if (state == AST_STATE_RING)
09748       tmp->rings = 1;
09749    tmp->tech_pvt = i;
09750    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09751       /* Only FXO signalled stuff can be picked up */
09752       tmp->callgroup = i->callgroup;
09753       tmp->pickupgroup = i->pickupgroup;
09754    }
09755    if (!ast_strlen_zero(i->parkinglot))
09756       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09757    if (!ast_strlen_zero(i->language))
09758       ast_string_field_set(tmp, language, i->language);
09759    if (!i->owner)
09760       i->owner = tmp;
09761    if (!ast_strlen_zero(i->accountcode))
09762       ast_string_field_set(tmp, accountcode, i->accountcode);
09763    if (i->amaflags)
09764       tmp->amaflags = i->amaflags;
09765    i->subs[idx].owner = tmp;
09766    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09767    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09768       ast_string_field_set(tmp, call_forward, i->call_forward);
09769    }
09770    /* If we've been told "no ADSI" then enforce it */
09771    if (!i->adsi)
09772       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09773    if (!ast_strlen_zero(i->exten))
09774       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09775    if (!ast_strlen_zero(i->rdnis)) {
09776       tmp->redirecting.from.number.valid = 1;
09777       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09778    }
09779    if (!ast_strlen_zero(i->dnid)) {
09780       tmp->dialed.number.str = ast_strdup(i->dnid);
09781    }
09782 
09783    /* Don't use ast_set_callerid() here because it will
09784     * generate a needless NewCallerID event */
09785 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09786    if (!ast_strlen_zero(i->cid_ani)) {
09787       tmp->caller.ani.number.valid = 1;
09788       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09789    } else if (!ast_strlen_zero(i->cid_num)) {
09790       tmp->caller.ani.number.valid = 1;
09791       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09792    }
09793 #else
09794    if (!ast_strlen_zero(i->cid_num)) {
09795       tmp->caller.ani.number.valid = 1;
09796       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09797    }
09798 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09799    tmp->caller.id.name.presentation = i->callingpres;
09800    tmp->caller.id.number.presentation = i->callingpres;
09801    tmp->caller.id.number.plan = i->cid_ton;
09802    tmp->caller.ani2 = i->cid_ani2;
09803    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09804    /* clear the fake event in case we posted one before we had ast_channel */
09805    i->fake_event = 0;
09806    /* Assure there is no confmute on this channel */
09807    dahdi_confmute(i, 0);
09808    i->muting = 0;
09809    /* Configure the new channel jb */
09810    ast_jb_configure(tmp, &global_jbconf);
09811 
09812    /* Set initial device state */
09813    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09814    dashptr = strrchr(device_name, '-');
09815    if (dashptr) {
09816       *dashptr = '\0';
09817    }
09818    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09819    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09820 
09821    for (v = i->vars ; v ; v = v->next)
09822       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09823 
09824    ast_module_ref(ast_module_info->self);
09825 
09826    dahdi_ami_channel_event(i, tmp);
09827    if (startpbx) {
09828 #ifdef HAVE_OPENR2
09829       if (i->mfcr2call) {
09830          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09831       }
09832 #endif
09833       if (ast_pbx_start(tmp)) {
09834          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09835          ast_hangup(tmp);
09836          return NULL;
09837       }
09838    }
09839    return tmp;
09840 }
09841 
09842 
09843 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09844 {
09845    char c;
09846 
09847    *str = 0; /* start with empty output buffer */
09848    for (;;)
09849    {
09850       /* Wait for the first digit (up to specified ms). */
09851       c = ast_waitfordigit(chan, ms);
09852       /* if timeout, hangup or error, return as such */
09853       if (c < 1)
09854          return c;
09855       *str++ = c;
09856       *str = 0;
09857       if (strchr(term, c))
09858          return 1;
09859    }
09860 }
09861 
09862 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09863 {
09864    int j;
09865    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09866    for (;;)
09867    {
09868       /* set bits of interest */
09869       j = DAHDI_IOMUX_SIGEVENT;
09870       /* wait for some happening */
09871       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09872       /* exit loop if we have it */
09873       if (j & DAHDI_IOMUX_SIGEVENT) break;
09874    }
09875    /* get the event info */
09876    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09877    return 0;
09878 }
09879 
09880 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09881  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09882  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09883  *
09884  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09885  * DAHDI channel). Use this to enable or disable it.
09886  *
09887  * \bug the use of the word "channel" for those dahdichans is really confusing.
09888  */
09889 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09890 {
09891    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09892       return analog_dnd(dahdichan->sig_pvt, flag);
09893    }
09894 
09895    if (flag == -1) {
09896       return dahdichan->dnd;
09897    }
09898 
09899    /* Do not disturb */
09900    dahdichan->dnd = flag;
09901    ast_verb(3, "%s DND on channel %d\n",
09902          flag? "Enabled" : "Disabled",
09903          dahdichan->channel);
09904    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09905          "Channel: DAHDI/%d\r\n"
09906          "Status: %s\r\n", dahdichan->channel,
09907          flag? "enabled" : "disabled");
09908 
09909    return 0;
09910 }
09911 
09912 static int canmatch_featurecode(const char *exten)
09913 {
09914    int extlen = strlen(exten);
09915    const char *pickup_ext;
09916    if (!extlen) {
09917       return 1;
09918    }
09919    pickup_ext = ast_pickup_ext();
09920    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09921       return 1;
09922    }
09923    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09924    if (exten[0] == '*' && extlen < 3) {
09925       if (extlen == 1) {
09926          return 1;
09927       }
09928       /* "*0" should be processed before it gets here */
09929       switch (exten[1]) {
09930       case '6':
09931       case '7':
09932       case '8':
09933          return 1;
09934       }
09935    }
09936    return 0;
09937 }
09938 
09939 static void *analog_ss_thread(void *data)
09940 {
09941    struct ast_channel *chan = data;
09942    struct dahdi_pvt *p = chan->tech_pvt;
09943    char exten[AST_MAX_EXTENSION] = "";
09944    char exten2[AST_MAX_EXTENSION] = "";
09945    unsigned char buf[256];
09946    char dtmfcid[300];
09947    char dtmfbuf[300];
09948    struct callerid_state *cs = NULL;
09949    char *name = NULL, *number = NULL;
09950    int distMatches;
09951    int curRingData[3];
09952    int receivedRingT;
09953    int counter1;
09954    int counter;
09955    int samples = 0;
09956    struct ast_smdi_md_message *smdi_msg = NULL;
09957    int flags = 0;
09958    int i;
09959    int timeout;
09960    int getforward = 0;
09961    char *s1, *s2;
09962    int len = 0;
09963    int res;
09964    int idx;
09965 
09966    ast_mutex_lock(&ss_thread_lock);
09967    ss_thread_count++;
09968    ast_mutex_unlock(&ss_thread_lock);
09969    /* in the bizarre case where the channel has become a zombie before we
09970       even get started here, abort safely
09971    */
09972    if (!p) {
09973       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09974       ast_hangup(chan);
09975       goto quit;
09976    }
09977    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09978    idx = dahdi_get_index(chan, p, 1);
09979    if (idx < 0) {
09980       ast_log(LOG_WARNING, "Huh?\n");
09981       ast_hangup(chan);
09982       goto quit;
09983    }
09984    if (p->dsp)
09985       ast_dsp_digitreset(p->dsp);
09986    switch (p->sig) {
09987    case SIG_FEATD:
09988    case SIG_FEATDMF:
09989    case SIG_FEATDMF_TA:
09990    case SIG_E911:
09991    case SIG_FGC_CAMAMF:
09992    case SIG_FEATB:
09993    case SIG_EMWINK:
09994    case SIG_SF_FEATD:
09995    case SIG_SF_FEATDMF:
09996    case SIG_SF_FEATB:
09997    case SIG_SFWINK:
09998       if (dahdi_wink(p, idx))
09999          goto quit;
10000       /* Fall through */
10001    case SIG_EM:
10002    case SIG_EM_E1:
10003    case SIG_SF:
10004    case SIG_FGC_CAMA:
10005       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10006       if (p->dsp)
10007          ast_dsp_digitreset(p->dsp);
10008       /* set digit mode appropriately */
10009       if (p->dsp) {
10010          if (NEED_MFDETECT(p))
10011             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10012          else
10013             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10014       }
10015       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10016       /* Wait for the first digit only if immediate=no */
10017       if (!p->immediate)
10018          /* Wait for the first digit (up to 5 seconds). */
10019          res = ast_waitfordigit(chan, 5000);
10020       else
10021          res = 0;
10022       if (res > 0) {
10023          /* save first char */
10024          dtmfbuf[0] = res;
10025          switch (p->sig) {
10026          case SIG_FEATD:
10027          case SIG_SF_FEATD:
10028             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10029             if (res > 0)
10030                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10031             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10032             break;
10033          case SIG_FEATDMF_TA:
10034             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10035             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10036             if (dahdi_wink(p, idx)) goto quit;
10037             dtmfbuf[0] = 0;
10038             /* Wait for the first digit (up to 5 seconds). */
10039             res = ast_waitfordigit(chan, 5000);
10040             if (res <= 0) break;
10041             dtmfbuf[0] = res;
10042             /* fall through intentionally */
10043          case SIG_FEATDMF:
10044          case SIG_E911:
10045          case SIG_FGC_CAMAMF:
10046          case SIG_SF_FEATDMF:
10047             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10048             /* if international caca, do it again to get real ANO */
10049             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10050             {
10051                if (dahdi_wink(p, idx)) goto quit;
10052                dtmfbuf[0] = 0;
10053                /* Wait for the first digit (up to 5 seconds). */
10054                res = ast_waitfordigit(chan, 5000);
10055                if (res <= 0) break;
10056                dtmfbuf[0] = res;
10057                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10058             }
10059             if (res > 0) {
10060                /* if E911, take off hook */
10061                if (p->sig == SIG_E911)
10062                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10063                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10064             }
10065             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10066             break;
10067          case SIG_FEATB:
10068          case SIG_SF_FEATB:
10069             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10070             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10071             break;
10072          case SIG_EMWINK:
10073             /* if we received a '*', we are actually receiving Feature Group D
10074                dial syntax, so use that mode; otherwise, fall through to normal
10075                mode
10076             */
10077             if (res == '*') {
10078                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10079                if (res > 0)
10080                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10081                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10082                break;
10083             }
10084          default:
10085             /* If we got the first digit, get the rest */
10086             len = 1;
10087             dtmfbuf[len] = '\0';
10088             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10089                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10090                   timeout = matchdigittimeout;
10091                } else {
10092                   timeout = gendigittimeout;
10093                }
10094                res = ast_waitfordigit(chan, timeout);
10095                if (res < 0) {
10096                   ast_debug(1, "waitfordigit returned < 0...\n");
10097                   ast_hangup(chan);
10098                   goto quit;
10099                } else if (res) {
10100                   dtmfbuf[len++] = res;
10101                   dtmfbuf[len] = '\0';
10102                } else {
10103                   break;
10104                }
10105             }
10106             break;
10107          }
10108       }
10109       if (res == -1) {
10110          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10111          ast_hangup(chan);
10112          goto quit;
10113       } else if (res < 0) {
10114          ast_debug(1, "Got hung up before digits finished\n");
10115          ast_hangup(chan);
10116          goto quit;
10117       }
10118 
10119       if (p->sig == SIG_FGC_CAMA) {
10120          char anibuf[100];
10121 
10122          if (ast_safe_sleep(chan,1000) == -1) {
10123             ast_hangup(chan);
10124             goto quit;
10125          }
10126          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10127          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10128          res = my_getsigstr(chan, anibuf, "#", 10000);
10129          if ((res > 0) && (strlen(anibuf) > 2)) {
10130             if (anibuf[strlen(anibuf) - 1] == '#')
10131                anibuf[strlen(anibuf) - 1] = 0;
10132             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10133          }
10134          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10135       }
10136 
10137       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10138       if (ast_strlen_zero(exten))
10139          ast_copy_string(exten, "s", sizeof(exten));
10140       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10141          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10142          if (exten[0] == '*') {
10143             char *stringp=NULL;
10144             ast_copy_string(exten2, exten, sizeof(exten2));
10145             /* Parse out extension and callerid */
10146             stringp=exten2 +1;
10147             s1 = strsep(&stringp, "*");
10148             s2 = strsep(&stringp, "*");
10149             if (s2) {
10150                if (!ast_strlen_zero(p->cid_num))
10151                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10152                else
10153                   ast_set_callerid(chan, s1, NULL, s1);
10154                ast_copy_string(exten, s2, sizeof(exten));
10155             } else
10156                ast_copy_string(exten, s1, sizeof(exten));
10157          } else if (p->sig == SIG_FEATD)
10158             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10159       }
10160       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10161          if (exten[0] == '*') {
10162             char *stringp=NULL;
10163             ast_copy_string(exten2, exten, sizeof(exten2));
10164             /* Parse out extension and callerid */
10165             stringp=exten2 +1;
10166             s1 = strsep(&stringp, "#");
10167             s2 = strsep(&stringp, "#");
10168             if (s2) {
10169                if (!ast_strlen_zero(p->cid_num))
10170                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10171                else
10172                   if (*(s1 + 2))
10173                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10174                ast_copy_string(exten, s2 + 1, sizeof(exten));
10175             } else
10176                ast_copy_string(exten, s1 + 2, sizeof(exten));
10177          } else
10178             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10179       }
10180       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10181          if (exten[0] == '*') {
10182             char *stringp=NULL;
10183             ast_copy_string(exten2, exten, sizeof(exten2));
10184             /* Parse out extension and callerid */
10185             stringp=exten2 +1;
10186             s1 = strsep(&stringp, "#");
10187             s2 = strsep(&stringp, "#");
10188             if (s2 && (*(s2 + 1) == '0')) {
10189                if (*(s2 + 2))
10190                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10191             }
10192             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10193             else ast_copy_string(exten, "911", sizeof(exten));
10194          } else
10195             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10196       }
10197       if (p->sig == SIG_FEATB) {
10198          if (exten[0] == '*') {
10199             char *stringp=NULL;
10200             ast_copy_string(exten2, exten, sizeof(exten2));
10201             /* Parse out extension and callerid */
10202             stringp=exten2 +1;
10203             s1 = strsep(&stringp, "#");
10204             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10205          } else
10206             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10207       }
10208       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10209          dahdi_wink(p, idx);
10210          /* some switches require a minimum guard time between
10211             the last FGD wink and something that answers
10212             immediately. This ensures it */
10213          if (ast_safe_sleep(chan, 100)) {
10214             ast_hangup(chan);
10215             goto quit;
10216          }
10217       }
10218       dahdi_enable_ec(p);
10219       if (NEED_MFDETECT(p)) {
10220          if (p->dsp) {
10221             if (!p->hardwaredtmf)
10222                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10223             else {
10224                ast_dsp_free(p->dsp);
10225                p->dsp = NULL;
10226             }
10227          }
10228       }
10229 
10230       if (ast_exists_extension(chan, chan->context, exten, 1,
10231          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10232          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10233          if (p->dsp) ast_dsp_digitreset(p->dsp);
10234          res = ast_pbx_run(chan);
10235          if (res) {
10236             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10237             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10238          }
10239          goto quit;
10240       } else {
10241          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10242          sleep(2);
10243          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10244          if (res < 0)
10245             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10246          else
10247             sleep(1);
10248          res = ast_streamfile(chan, "ss-noservice", chan->language);
10249          if (res >= 0)
10250             ast_waitstream(chan, "");
10251          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10252          ast_hangup(chan);
10253          goto quit;
10254       }
10255       break;
10256    case SIG_FXOLS:
10257    case SIG_FXOGS:
10258    case SIG_FXOKS:
10259       /* Read the first digit */
10260       timeout = firstdigittimeout;
10261       /* If starting a threeway call, never timeout on the first digit so someone
10262          can use flash-hook as a "hold" feature */
10263       if (p->subs[SUB_THREEWAY].owner)
10264          timeout = 999999;
10265       while (len < AST_MAX_EXTENSION-1) {
10266          /* Read digit unless it's supposed to be immediate, in which case the
10267             only answer is 's' */
10268          if (p->immediate)
10269             res = 's';
10270          else
10271             res = ast_waitfordigit(chan, timeout);
10272          timeout = 0;
10273          if (res < 0) {
10274             ast_debug(1, "waitfordigit returned < 0...\n");
10275             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10276             ast_hangup(chan);
10277             goto quit;
10278          } else if (res) {
10279             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10280             exten[len++]=res;
10281             exten[len] = '\0';
10282          }
10283          if (!ast_ignore_pattern(chan->context, exten))
10284             tone_zone_play_tone(p->subs[idx].dfd, -1);
10285          else
10286             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10287          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10288             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10289                if (getforward) {
10290                   /* Record this as the forwarding extension */
10291                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10292                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10293                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10294                   if (res)
10295                      break;
10296                   usleep(500000);
10297                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10298                   sleep(1);
10299                   memset(exten, 0, sizeof(exten));
10300                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10301                   len = 0;
10302                   getforward = 0;
10303                } else {
10304                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10305                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10306                   if (!ast_strlen_zero(p->cid_num)) {
10307                      if (!p->hidecallerid)
10308                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10309                      else
10310                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10311                   }
10312                   if (!ast_strlen_zero(p->cid_name)) {
10313                      if (!p->hidecallerid)
10314                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10315                   }
10316                   ast_setstate(chan, AST_STATE_RING);
10317                   dahdi_enable_ec(p);
10318                   res = ast_pbx_run(chan);
10319                   if (res) {
10320                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10321                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10322                   }
10323                   goto quit;
10324                }
10325             } else {
10326                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10327                   so just set the timeout to matchdigittimeout and wait some more */
10328                timeout = matchdigittimeout;
10329             }
10330          } else if (res == 0) {
10331             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10332             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10333             dahdi_wait_event(p->subs[idx].dfd);
10334             ast_hangup(chan);
10335             goto quit;
10336          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10337             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10338             /* Disable call waiting if enabled */
10339             p->callwaiting = 0;
10340             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10341             if (res) {
10342                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10343                   chan->name, strerror(errno));
10344             }
10345             len = 0;
10346             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10347             memset(exten, 0, sizeof(exten));
10348             timeout = firstdigittimeout;
10349 
10350          } else if (!strcmp(exten,ast_pickup_ext())) {
10351             /* Scan all channels and see if there are any
10352              * ringing channels that have call groups
10353              * that equal this channels pickup group
10354              */
10355             if (idx == SUB_REAL) {
10356                /* Switch us from Third call to Call Wait */
10357                if (p->subs[SUB_THREEWAY].owner) {
10358                   /* If you make a threeway call and the *8# a call, it should actually
10359                      look like a callwait */
10360                   alloc_sub(p, SUB_CALLWAIT);
10361                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10362                   unalloc_sub(p, SUB_THREEWAY);
10363                }
10364                dahdi_enable_ec(p);
10365                if (ast_pickup_call(chan)) {
10366                   ast_debug(1, "No call pickup possible...\n");
10367                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10368                   dahdi_wait_event(p->subs[idx].dfd);
10369                }
10370                ast_hangup(chan);
10371                goto quit;
10372             } else {
10373                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10374                ast_hangup(chan);
10375                goto quit;
10376             }
10377 
10378          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10379             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10380             /* Disable Caller*ID if enabled */
10381             p->hidecallerid = 1;
10382             ast_party_number_free(&chan->caller.id.number);
10383             ast_party_number_init(&chan->caller.id.number);
10384             ast_party_name_free(&chan->caller.id.name);
10385             ast_party_name_init(&chan->caller.id.name);
10386             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10387             if (res) {
10388                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10389                   chan->name, strerror(errno));
10390             }
10391             len = 0;
10392             memset(exten, 0, sizeof(exten));
10393             timeout = firstdigittimeout;
10394          } else if (p->callreturn && !strcmp(exten, "*69")) {
10395             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10396             break;
10397          } else if (!strcmp(exten, "*78")) {
10398             dahdi_dnd(p, 1);
10399             /* Do not disturb */
10400             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401             getforward = 0;
10402             memset(exten, 0, sizeof(exten));
10403             len = 0;
10404          } else if (!strcmp(exten, "*79")) {
10405             dahdi_dnd(p, 0);
10406             /* Do not disturb */
10407             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10408             getforward = 0;
10409             memset(exten, 0, sizeof(exten));
10410             len = 0;
10411          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10412             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10413             getforward = 1;
10414             memset(exten, 0, sizeof(exten));
10415             len = 0;
10416          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10417             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10418             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10419             memset(p->call_forward, 0, sizeof(p->call_forward));
10420             getforward = 0;
10421             memset(exten, 0, sizeof(exten));
10422             len = 0;
10423          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10424                   p->subs[SUB_THREEWAY].owner &&
10425                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10426             /* This is a three way call, the main call being a real channel,
10427                and we're parking the first call. */
10428             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10429                chan, exten, chan->context, 0, NULL);
10430             ast_verb(3, "Parking call to '%s'\n", chan->name);
10431             break;
10432          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10433             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10434             /* Enable Caller*ID if enabled */
10435             p->hidecallerid = 0;
10436             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10437             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10438             if (res) {
10439                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10440                   chan->name, strerror(errno));
10441             }
10442             len = 0;
10443             memset(exten, 0, sizeof(exten));
10444             timeout = firstdigittimeout;
10445          } else if (!strcmp(exten, "*0")) {
10446             struct ast_channel *nbridge =
10447                p->subs[SUB_THREEWAY].owner;
10448             struct dahdi_pvt *pbridge = NULL;
10449             /* set up the private struct of the bridged one, if any */
10450             if (nbridge && ast_bridged_channel(nbridge))
10451                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10452             if (nbridge && pbridge &&
10453                (nbridge->tech == &dahdi_tech) &&
10454                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10455                ISTRUNK(pbridge)) {
10456                int func = DAHDI_FLASH;
10457                /* Clear out the dial buffer */
10458                p->dop.dialstr[0] = '\0';
10459                /* flash hookswitch */
10460                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10461                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10462                      nbridge->name, strerror(errno));
10463                }
10464                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10465                unalloc_sub(p, SUB_THREEWAY);
10466                p->owner = p->subs[SUB_REAL].owner;
10467                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10468                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10469                ast_hangup(chan);
10470                goto quit;
10471             } else {
10472                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10473                dahdi_wait_event(p->subs[idx].dfd);
10474                tone_zone_play_tone(p->subs[idx].dfd, -1);
10475                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10476                unalloc_sub(p, SUB_THREEWAY);
10477                p->owner = p->subs[SUB_REAL].owner;
10478                ast_hangup(chan);
10479                goto quit;
10480             }
10481          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10482             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10483             && !canmatch_featurecode(exten)) {
10484             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10485                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10486                chan->context);
10487             break;
10488          }
10489          if (!timeout)
10490             timeout = gendigittimeout;
10491          if (len && !ast_ignore_pattern(chan->context, exten))
10492             tone_zone_play_tone(p->subs[idx].dfd, -1);
10493       }
10494       break;
10495    case SIG_FXSLS:
10496    case SIG_FXSGS:
10497    case SIG_FXSKS:
10498       /* check for SMDI messages */
10499       if (p->use_smdi && p->smdi_iface) {
10500          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10501 
10502          if (smdi_msg != NULL) {
10503             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10504 
10505             if (smdi_msg->type == 'B')
10506                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10507             else if (smdi_msg->type == 'N')
10508                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10509 
10510             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10511          } else {
10512             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10513          }
10514       }
10515 
10516       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10517          number = smdi_msg->calling_st;
10518 
10519       /* If we want caller id, we're in a prering state due to a polarity reversal
10520        * and we're set to use a polarity reversal to trigger the start of caller id,
10521        * grab the caller id and wait for ringing to start... */
10522       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10523                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10524          /* If set to use DTMF CID signalling, listen for DTMF */
10525          if (p->cid_signalling == CID_SIG_DTMF) {
10526             int k = 0;
10527             int off_ms;
10528             struct timeval start = ast_tvnow();
10529             int ms;
10530             cs = NULL;
10531             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10532             dahdi_setlinear(p->subs[idx].dfd, 0);
10533             /*
10534              * We are the only party interested in the Rx stream since
10535              * we have not answered yet.  We don't need or even want DTMF
10536              * emulation.  The DTMF digits can come so fast that emulation
10537              * can drop some of them.
10538              */
10539             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10540             off_ms = 4000;/* This is a typical OFF time between rings. */
10541             for (;;) {
10542                struct ast_frame *f;
10543 
10544                ms = ast_remaining_ms(start, off_ms);
10545                res = ast_waitfor(chan, ms);
10546                if (res <= 0) {
10547                   /*
10548                    * We do not need to restore the dahdi_setlinear()
10549                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10550                    * are hanging up the channel.
10551                    */
10552                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10553                      "Exiting simple switch\n");
10554                   ast_hangup(chan);
10555                   goto quit;
10556                }
10557                f = ast_read(chan);
10558                if (!f)
10559                   break;
10560                if (f->frametype == AST_FRAME_DTMF) {
10561                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10562                      dtmfbuf[k++] = f->subclass.integer;
10563                   }
10564                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10565                   start = ast_tvnow();
10566                }
10567                ast_frfree(f);
10568                if (chan->_state == AST_STATE_RING ||
10569                   chan->_state == AST_STATE_RINGING)
10570                   break; /* Got ring */
10571             }
10572             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10573             dtmfbuf[k] = '\0';
10574             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10575             /* Got cid and ring. */
10576             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10577             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10578             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10579             /* If first byte is NULL, we have no cid */
10580             if (!ast_strlen_zero(dtmfcid))
10581                number = dtmfcid;
10582             else
10583                number = NULL;
10584          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10585          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10586             cs = callerid_new(p->cid_signalling);
10587             if (cs) {
10588                int off_ms;
10589                struct timeval start;
10590                int ms;
10591                samples = 0;
10592 #if 1
10593                bump_gains(p);
10594 #endif
10595                /* Take out of linear mode for Caller*ID processing */
10596                dahdi_setlinear(p->subs[idx].dfd, 0);
10597 
10598                /* First we wait and listen for the Caller*ID */
10599                for (;;) {
10600                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10601                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10602                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10603                      callerid_free(cs);
10604                      ast_hangup(chan);
10605                      goto quit;
10606                   }
10607                   if (i & DAHDI_IOMUX_SIGEVENT) {
10608                      res = dahdi_get_event(p->subs[idx].dfd);
10609                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10610                      if (res == DAHDI_EVENT_NOALARM) {
10611                         p->inalarm = 0;
10612                      }
10613 
10614                      if (p->cid_signalling == CID_SIG_V23_JP) {
10615                         if (res == DAHDI_EVENT_RINGBEGIN) {
10616                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10617                            usleep(1);
10618                         }
10619                      } else {
10620                         res = 0;
10621                         break;
10622                      }
10623                   } else if (i & DAHDI_IOMUX_READ) {
10624                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10625                      if (res < 0) {
10626                         if (errno != ELAST) {
10627                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10628                            callerid_free(cs);
10629                            ast_hangup(chan);
10630                            goto quit;
10631                         }
10632                         break;
10633                      }
10634                      samples += res;
10635 
10636                      if (p->cid_signalling == CID_SIG_V23_JP) {
10637                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10638                      } else {
10639                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10640                      }
10641                      if (res < 0) {
10642                         /*
10643                          * The previous diagnostic message output likely
10644                          * explains why it failed.
10645                          */
10646                         ast_log(LOG_WARNING,
10647                            "Failed to decode CallerID on channel '%s'\n",
10648                            chan->name);
10649                         break;
10650                      } else if (res)
10651                         break;
10652                      else if (samples > (8000 * 10))
10653                         break;
10654                   }
10655                }
10656                if (res == 1) {
10657                   callerid_get(cs, &name, &number, &flags);
10658                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10659                }
10660 
10661                if (p->cid_signalling == CID_SIG_V23_JP) {
10662                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10663                   usleep(1);
10664                }
10665 
10666                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10667                start = ast_tvnow();
10668                off_ms = 4000;/* This is a typical OFF time between rings. */
10669                for (;;) {
10670                   struct ast_frame *f;
10671 
10672                   ms = ast_remaining_ms(start, off_ms);
10673                   res = ast_waitfor(chan, ms);
10674                   if (res <= 0) {
10675                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10676                         "Exiting simple switch\n");
10677                      ast_hangup(chan);
10678                      goto quit;
10679                   }
10680                   if (!(f = ast_read(chan))) {
10681                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10682                      ast_hangup(chan);
10683                      goto quit;
10684                   }
10685                   ast_frfree(f);
10686                   if (chan->_state == AST_STATE_RING ||
10687                      chan->_state == AST_STATE_RINGING)
10688                      break; /* Got ring */
10689                }
10690 
10691                /* We must have a ring by now, so, if configured, lets try to listen for
10692                 * distinctive ringing */
10693                if (p->usedistinctiveringdetection) {
10694                   len = 0;
10695                   distMatches = 0;
10696                   /* Clear the current ring data array so we don't have old data in it. */
10697                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10698                      curRingData[receivedRingT] = 0;
10699                   receivedRingT = 0;
10700                   counter = 0;
10701                   counter1 = 0;
10702                   /* Check to see if context is what it should be, if not set to be. */
10703                   if (strcmp(p->context,p->defcontext) != 0) {
10704                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10705                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10706                   }
10707 
10708                   for (;;) {
10709                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10710                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10711                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10712                         callerid_free(cs);
10713                         ast_hangup(chan);
10714                         goto quit;
10715                      }
10716                      if (i & DAHDI_IOMUX_SIGEVENT) {
10717                         res = dahdi_get_event(p->subs[idx].dfd);
10718                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10719                         if (res == DAHDI_EVENT_NOALARM) {
10720                            p->inalarm = 0;
10721                         }
10722                         res = 0;
10723                         /* Let us detect distinctive ring */
10724 
10725                         curRingData[receivedRingT] = p->ringt;
10726 
10727                         if (p->ringt < p->ringt_base/2)
10728                            break;
10729                         /* Increment the ringT counter so we can match it against
10730                            values in chan_dahdi.conf for distinctive ring */
10731                         if (++receivedRingT == ARRAY_LEN(curRingData))
10732                            break;
10733                      } else if (i & DAHDI_IOMUX_READ) {
10734                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10735                         if (res < 0) {
10736                            if (errno != ELAST) {
10737                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10738                               callerid_free(cs);
10739                               ast_hangup(chan);
10740                               goto quit;
10741                            }
10742                            break;
10743                         }
10744                         if (p->ringt > 0) {
10745                            if (!(--p->ringt)) {
10746                               res = -1;
10747                               break;
10748                            }
10749                         }
10750                      }
10751                   }
10752                      /* this only shows up if you have n of the dring patterns filled in */
10753                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10754                   for (counter = 0; counter < 3; counter++) {
10755                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10756                      channel */
10757                      distMatches = 0;
10758                      for (counter1 = 0; counter1 < 3; counter1++) {
10759                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10760                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10761                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10762                            curRingData[counter1]);
10763                            distMatches++;
10764                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10765                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10766                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10767                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10768                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10769                            distMatches++;
10770                         }
10771                      }
10772 
10773                      if (distMatches == 3) {
10774                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10775                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10776                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10777                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10778                         break;
10779                      }
10780                   }
10781                }
10782                /* Restore linear mode (if appropriate) for Caller*ID processing */
10783                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10784 #if 1
10785                restore_gains(p);
10786 #endif
10787             } else
10788                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10789          } else {
10790             ast_log(LOG_WARNING, "Channel %s in prering "
10791                "state, but I have nothing to do. "
10792                "Terminating simple switch, should be "
10793                "restarted by the actual ring.\n",
10794                chan->name);
10795             ast_hangup(chan);
10796             goto quit;
10797          }
10798       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10799          if (p->cid_signalling == CID_SIG_DTMF) {
10800             int k = 0;
10801             int off_ms;
10802             struct timeval start;
10803             int ms;
10804             cs = NULL;
10805             dahdi_setlinear(p->subs[idx].dfd, 0);
10806             off_ms = 2000;
10807             start = ast_tvnow();
10808             for (;;) {
10809                struct ast_frame *f;
10810 
10811                ms = ast_remaining_ms(start, off_ms);
10812                res = ast_waitfor(chan, ms);
10813                if (res <= 0) {
10814                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10815                      "Exiting simple switch\n");
10816                   ast_hangup(chan);
10817                   goto quit;
10818                }
10819                f = ast_read(chan);
10820                if (!f) {
10821                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10822                   ast_hangup(chan);
10823                   goto quit;
10824                }
10825                if (f->frametype == AST_FRAME_DTMF) {
10826                   dtmfbuf[k++] = f->subclass.integer;
10827                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10828                   start = ast_tvnow();
10829                }
10830                ast_frfree(f);
10831 
10832                if (p->ringt_base == p->ringt)
10833                   break;
10834             }
10835             dtmfbuf[k] = '\0';
10836             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10837             /* Got cid and ring. */
10838             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10839             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10840                dtmfcid, flags);
10841             /* If first byte is NULL, we have no cid */
10842             if (!ast_strlen_zero(dtmfcid))
10843                number = dtmfcid;
10844             else
10845                number = NULL;
10846             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10847          } else {
10848             /* FSK Bell202 callerID */
10849             cs = callerid_new(p->cid_signalling);
10850             if (cs) {
10851 #if 1
10852                bump_gains(p);
10853 #endif
10854                samples = 0;
10855                len = 0;
10856                distMatches = 0;
10857                /* Clear the current ring data array so we don't have old data in it. */
10858                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10859                   curRingData[receivedRingT] = 0;
10860                receivedRingT = 0;
10861                counter = 0;
10862                counter1 = 0;
10863                /* Check to see if context is what it should be, if not set to be. */
10864                if (strcmp(p->context,p->defcontext) != 0) {
10865                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10866                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10867                }
10868 
10869                /* Take out of linear mode for Caller*ID processing */
10870                dahdi_setlinear(p->subs[idx].dfd, 0);
10871                for (;;) {
10872                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10873                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10874                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10875                      callerid_free(cs);
10876                      ast_hangup(chan);
10877                      goto quit;
10878                   }
10879                   if (i & DAHDI_IOMUX_SIGEVENT) {
10880                      res = dahdi_get_event(p->subs[idx].dfd);
10881                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10882                      if (res == DAHDI_EVENT_NOALARM) {
10883                         p->inalarm = 0;
10884                      }
10885                      /* If we get a PR event, they hung up while processing calerid */
10886                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10887                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10888                         p->polarity = POLARITY_IDLE;
10889                         callerid_free(cs);
10890                         ast_hangup(chan);
10891                         goto quit;
10892                      }
10893                      res = 0;
10894                      /* Let us detect callerid when the telco uses distinctive ring */
10895 
10896                      curRingData[receivedRingT] = p->ringt;
10897 
10898                      if (p->ringt < p->ringt_base/2)
10899                         break;
10900                      /* Increment the ringT counter so we can match it against
10901                         values in chan_dahdi.conf for distinctive ring */
10902                      if (++receivedRingT == ARRAY_LEN(curRingData))
10903                         break;
10904                   } else if (i & DAHDI_IOMUX_READ) {
10905                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10906                      if (res < 0) {
10907                         if (errno != ELAST) {
10908                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10909                            callerid_free(cs);
10910                            ast_hangup(chan);
10911                            goto quit;
10912                         }
10913                         break;
10914                      }
10915                      if (p->ringt > 0) {
10916                         if (!(--p->ringt)) {
10917                            res = -1;
10918                            break;
10919                         }
10920                      }
10921                      samples += res;
10922                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10923                      if (res < 0) {
10924                         /*
10925                          * The previous diagnostic message output likely
10926                          * explains why it failed.
10927                          */
10928                         ast_log(LOG_WARNING,
10929                            "Failed to decode CallerID on channel '%s'\n",
10930                            chan->name);
10931                         break;
10932                      } else if (res)
10933                         break;
10934                      else if (samples > (8000 * 10))
10935                         break;
10936                   }
10937                }
10938                if (res == 1) {
10939                   callerid_get(cs, &name, &number, &flags);
10940                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10941                }
10942                if (distinctiveringaftercid == 1) {
10943                   /* Clear the current ring data array so we don't have old data in it. */
10944                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10945                      curRingData[receivedRingT] = 0;
10946                   }
10947                   receivedRingT = 0;
10948                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10949                   for (;;) {
10950                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10951                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10952                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10953                         callerid_free(cs);
10954                         ast_hangup(chan);
10955                         goto quit;
10956                      }
10957                      if (i & DAHDI_IOMUX_SIGEVENT) {
10958                         res = dahdi_get_event(p->subs[idx].dfd);
10959                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10960                         if (res == DAHDI_EVENT_NOALARM) {
10961                            p->inalarm = 0;
10962                         }
10963                         res = 0;
10964                         /* Let us detect callerid when the telco uses distinctive ring */
10965 
10966                         curRingData[receivedRingT] = p->ringt;
10967 
10968                         if (p->ringt < p->ringt_base/2)
10969                            break;
10970                         /* Increment the ringT counter so we can match it against
10971                            values in chan_dahdi.conf for distinctive ring */
10972                         if (++receivedRingT == ARRAY_LEN(curRingData))
10973                            break;
10974                      } else if (i & DAHDI_IOMUX_READ) {
10975                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10976                         if (res < 0) {
10977                            if (errno != ELAST) {
10978                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10979                               callerid_free(cs);
10980                               ast_hangup(chan);
10981                               goto quit;
10982                            }
10983                            break;
10984                         }
10985                         if (p->ringt > 0) {
10986                            if (!(--p->ringt)) {
10987                               res = -1;
10988                               break;
10989                            }
10990                         }
10991                      }
10992                   }
10993                }
10994                if (p->usedistinctiveringdetection) {
10995                   /* this only shows up if you have n of the dring patterns filled in */
10996                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10997 
10998                   for (counter = 0; counter < 3; counter++) {
10999                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11000                      channel */
11001                      /* this only shows up if you have n of the dring patterns filled in */
11002                      ast_verb(3, "Checking %d,%d,%d\n",
11003                            p->drings.ringnum[counter].ring[0],
11004                            p->drings.ringnum[counter].ring[1],
11005                            p->drings.ringnum[counter].ring[2]);
11006                      distMatches = 0;
11007                      for (counter1 = 0; counter1 < 3; counter1++) {
11008                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11009                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11010                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11011                            curRingData[counter1]);
11012                            distMatches++;
11013                         }
11014                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11015                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11016                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11017                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11018                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11019                            distMatches++;
11020                         }
11021                      }
11022                      if (distMatches == 3) {
11023                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11024                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11025                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11026                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11027                         break;
11028                      }
11029                   }
11030                }
11031                /* Restore linear mode (if appropriate) for Caller*ID processing */
11032                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11033 #if 1
11034                restore_gains(p);
11035 #endif
11036                if (res < 0) {
11037                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11038                }
11039             } else
11040                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11041          }
11042       } else
11043          cs = NULL;
11044 
11045       if (number)
11046          ast_shrink_phone_number(number);
11047       ast_set_callerid(chan, number, name, number);
11048 
11049       if (smdi_msg)
11050          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11051 
11052       if (cs)
11053          callerid_free(cs);
11054 
11055       my_handle_notify_message(chan, p, flags, -1);
11056 
11057       ast_setstate(chan, AST_STATE_RING);
11058       chan->rings = 1;
11059       p->ringt = p->ringt_base;
11060       res = ast_pbx_run(chan);
11061       if (res) {
11062          ast_hangup(chan);
11063          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11064       }
11065       goto quit;
11066    default:
11067       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11068       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11069       if (res < 0)
11070             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11071    }
11072    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11073    if (res < 0)
11074          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11075    ast_hangup(chan);
11076 quit:
11077    ast_mutex_lock(&ss_thread_lock);
11078    ss_thread_count--;
11079    ast_cond_signal(&ss_thread_complete);
11080    ast_mutex_unlock(&ss_thread_lock);
11081    return NULL;
11082 }
11083 
11084 struct mwi_thread_data {
11085    struct dahdi_pvt *pvt;
11086    unsigned char buf[READ_SIZE];
11087    size_t len;
11088 };
11089 
11090 static int calc_energy(const unsigned char *buf, int len, format_t law)
11091 {
11092    int x;
11093    int sum = 0;
11094 
11095    if (!len)
11096       return 0;
11097 
11098    for (x = 0; x < len; x++)
11099       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11100 
11101    return sum / len;
11102 }
11103 
11104 static void *mwi_thread(void *data)
11105 {
11106    struct mwi_thread_data *mtd = data;
11107    struct callerid_state *cs;
11108    pthread_t threadid;
11109    int samples = 0;
11110    char *name, *number;
11111    int flags;
11112    int i, res;
11113    unsigned int spill_done = 0;
11114    int spill_result = -1;
11115 
11116    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11117       goto quit_no_clean;
11118    }
11119 
11120    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11121 
11122    bump_gains(mtd->pvt);
11123 
11124    for (;;) {
11125       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11126       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11127          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11128          goto quit;
11129       }
11130 
11131       if (i & DAHDI_IOMUX_SIGEVENT) {
11132          struct ast_channel *chan;
11133 
11134          /* If we get an event, screen out events that we do not act on.
11135           * Otherwise, cancel and go to the simple switch to let it deal with it.
11136           */
11137          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11138 
11139          switch (res) {
11140          case DAHDI_EVENT_NEONMWI_ACTIVE:
11141          case DAHDI_EVENT_NEONMWI_INACTIVE:
11142          case DAHDI_EVENT_NONE:
11143          case DAHDI_EVENT_BITSCHANGED:
11144             break;
11145          case DAHDI_EVENT_NOALARM:
11146             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11147                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11148 
11149                analog_p->inalarm = 0;
11150             }
11151             mtd->pvt->inalarm = 0;
11152             handle_clear_alarms(mtd->pvt);
11153             break;
11154          case DAHDI_EVENT_ALARM:
11155             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11156                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11157 
11158                analog_p->inalarm = 1;
11159             }
11160             mtd->pvt->inalarm = 1;
11161             res = get_alarms(mtd->pvt);
11162             handle_alarms(mtd->pvt, res);
11163             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11164          default:
11165             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11166             callerid_free(cs);
11167 
11168             restore_gains(mtd->pvt);
11169             mtd->pvt->ringt = mtd->pvt->ringt_base;
11170 
11171             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11172                int result;
11173 
11174                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11175                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11176                } else {
11177                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11178                }
11179                if (result) {
11180                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11181                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11182                   if (res < 0)
11183                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11184                   ast_hangup(chan);
11185                }
11186             } else {
11187                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11188             }
11189             goto quit_no_clean;
11190          }
11191       } else if (i & DAHDI_IOMUX_READ) {
11192          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11193             if (errno != ELAST) {
11194                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11195                goto quit;
11196             }
11197             break;
11198          }
11199          samples += res;
11200          if (!spill_done) {
11201             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11202                /*
11203                 * The previous diagnostic message output likely
11204                 * explains why it failed.
11205                 */
11206                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11207                break;
11208             } else if (spill_result) {
11209                spill_done = 1;
11210             }
11211          } else {
11212             /* keep reading data until the energy level drops below the threshold
11213                so we don't get another 'trigger' on the remaining carrier signal
11214             */
11215             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11216                break;
11217          }
11218          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11219             break;
11220       }
11221    }
11222 
11223    if (spill_result == 1) {
11224       callerid_get(cs, &name, &number, &flags);
11225       if (flags & CID_MSGWAITING) {
11226          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11227          notify_message(mtd->pvt->mailbox, 1);
11228       } else if (flags & CID_NOMSGWAITING) {
11229          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11230          notify_message(mtd->pvt->mailbox, 0);
11231       } else {
11232          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11233       }
11234    }
11235 
11236 
11237 quit:
11238    callerid_free(cs);
11239 
11240    restore_gains(mtd->pvt);
11241 
11242 quit_no_clean:
11243    mtd->pvt->mwimonitoractive = 0;
11244    ast_free(mtd);
11245 
11246    return NULL;
11247 }
11248 
11249 /*
11250 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11251 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11252 * that are sent out via FXS port on voicemail state change.  The execution of
11253 * the mwi send is state driven and can either generate a ring pulse prior to
11254 * sending the fsk spill or simply send an fsk spill.
11255 */
11256 static int mwi_send_init(struct dahdi_pvt * pvt)
11257 {
11258    int x;
11259 
11260 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11261    /* Determine how this spill is to be sent */
11262    if (pvt->mwisend_rpas) {
11263       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11264       pvt->mwisendactive = 1;
11265    } else if (pvt->mwisend_fsk) {
11266       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11267       pvt->mwisendactive = 1;
11268    } else {
11269       pvt->mwisendactive = 0;
11270       return 0;
11271    }
11272 #else
11273    if (mwisend_rpas) {
11274       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11275    } else {
11276       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11277    }
11278    pvt->mwisendactive = 1;
11279 #endif
11280 
11281    if (pvt->cidspill) {
11282       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11283       ast_free(pvt->cidspill);
11284       pvt->cidspill = NULL;
11285       pvt->cidpos = 0;
11286       pvt->cidlen = 0;
11287    }
11288    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11289    if (!pvt->cidspill) {
11290       pvt->mwisendactive = 0;
11291       return -1;
11292    }
11293    x = DAHDI_FLUSH_BOTH;
11294    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11295    x = 3000;
11296    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11297 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11298    if (pvt->mwisend_fsk) {
11299 #endif
11300       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11301                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11302       pvt->cidpos = 0;
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304    }
11305 #endif
11306    return 0;
11307 }
11308 
11309 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11310 {
11311    struct timeval    now;
11312    int         res;
11313 
11314    /* sanity check to catch if this had been interrupted previously
11315    *  i.e. state says there is more to do but there is no spill allocated
11316    */
11317    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11318       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11319    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11320       /* Normal processing -- Perform mwi send action */
11321       switch ( pvt->mwisend_data.mwisend_current) {
11322       case MWI_SEND_SA:
11323          /* Send the Ring Pulse Signal Alert */
11324          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11325          if (res) {
11326             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11327             goto quit;
11328          }
11329          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11330          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11331          break;
11332       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11333          break;
11334       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11335 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11336          if (pvt->mwisend_fsk) {
11337 #endif
11338             gettimeofday(&now, NULL);
11339             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11340                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11341             }
11342 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11343          } else { /* support for mwisendtype=nofsk */
11344             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11345          }
11346 #endif
11347          break;
11348       case MWI_SEND_SPILL:
11349          /* We read some number of bytes.  Write an equal amount of data */
11350          if(0 < num_read) {
11351             if (num_read > pvt->cidlen - pvt->cidpos)
11352                num_read = pvt->cidlen - pvt->cidpos;
11353             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11354             if (res > 0) {
11355                pvt->cidpos += res;
11356                if (pvt->cidpos >= pvt->cidlen) {
11357                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11358                }
11359             } else {
11360                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11361                goto quit;
11362             }
11363          }
11364          break;
11365       case MWI_SEND_CLEANUP:
11366          /* For now, do nothing */
11367          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11368          break;
11369       default:
11370          /* Should not get here, punt*/
11371          goto quit;
11372       }
11373    }
11374 
11375    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11376       if (pvt->cidspill) {
11377          ast_free(pvt->cidspill);
11378          pvt->cidspill = NULL;
11379          pvt->cidpos = 0;
11380          pvt->cidlen = 0;
11381       }
11382       pvt->mwisendactive = 0;
11383    }
11384    return 0;
11385 quit:
11386    if (pvt->cidspill) {
11387       ast_free(pvt->cidspill);
11388       pvt->cidspill = NULL;
11389       pvt->cidpos = 0;
11390       pvt->cidlen = 0;
11391    }
11392    pvt->mwisendactive = 0;
11393    return -1;
11394 }
11395 
11396 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11397 {
11398    int handled = 0;
11399 
11400    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11401       switch (event) {
11402       case DAHDI_EVENT_RINGEROFF:
11403          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11404             handled = 1;
11405 
11406             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11407                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11408                ast_free(pvt->cidspill);
11409                pvt->cidspill = NULL;
11410                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11411                pvt->mwisendactive = 0;
11412             } else {
11413                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11414                gettimeofday(&pvt->mwisend_data.pause, NULL);
11415             }
11416          }
11417          break;
11418       /* Going off hook, I need to punt this spill */
11419       case DAHDI_EVENT_RINGOFFHOOK:
11420          if (pvt->cidspill) {
11421             ast_free(pvt->cidspill);
11422             pvt->cidspill = NULL;
11423             pvt->cidpos = 0;
11424             pvt->cidlen = 0;
11425          }
11426          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11427          pvt->mwisendactive = 0;
11428          break;
11429       case DAHDI_EVENT_RINGERON:
11430       case DAHDI_EVENT_HOOKCOMPLETE:
11431          break;
11432       default:
11433          break;
11434       }
11435    }
11436    return handled;
11437 }
11438 
11439 /* destroy a DAHDI channel, identified by its number */
11440 static int dahdi_destroy_channel_bynum(int channel)
11441 {
11442    struct dahdi_pvt *cur;
11443 
11444    ast_mutex_lock(&iflock);
11445    for (cur = iflist; cur; cur = cur->next) {
11446       if (cur->channel == channel) {
11447          int x = DAHDI_FLASH;
11448 
11449          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11450          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11451 
11452          destroy_channel(cur, 1);
11453          ast_mutex_unlock(&iflock);
11454          ast_module_unref(ast_module_info->self);
11455          return RESULT_SUCCESS;
11456       }
11457    }
11458    ast_mutex_unlock(&iflock);
11459    return RESULT_FAILURE;
11460 }
11461 
11462 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11463 {
11464    int res;
11465    pthread_t threadid;
11466    struct ast_channel *chan;
11467 
11468    /* Handle an event on a given channel for the monitor thread. */
11469 
11470    switch (event) {
11471    case DAHDI_EVENT_NONE:
11472    case DAHDI_EVENT_BITSCHANGED:
11473       break;
11474    case DAHDI_EVENT_WINKFLASH:
11475    case DAHDI_EVENT_RINGOFFHOOK:
11476       if (i->inalarm) break;
11477       if (i->radio) break;
11478       /* Got a ring/answer.  What kind of channel are we? */
11479       switch (i->sig) {
11480       case SIG_FXOLS:
11481       case SIG_FXOGS:
11482       case SIG_FXOKS:
11483          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11484          if (res && (errno == EBUSY))
11485             break;
11486 
11487          /* Cancel VMWI spill */
11488          ast_free(i->cidspill);
11489          i->cidspill = NULL;
11490          restore_conference(i);
11491 
11492          if (i->immediate) {
11493             dahdi_enable_ec(i);
11494             /* The channel is immediately up.  Start right away */
11495             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11496             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11497             if (!chan) {
11498                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11499                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11500                if (res < 0)
11501                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11502             }
11503          } else {
11504             /* Check for callerid, digits, etc */
11505             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11506             if (chan) {
11507                if (has_voicemail(i))
11508                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11509                else
11510                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11511                if (res < 0)
11512                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11513                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11514                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11515                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11516                   if (res < 0)
11517                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11518                   ast_hangup(chan);
11519                }
11520             } else
11521                ast_log(LOG_WARNING, "Unable to create channel\n");
11522          }
11523          break;
11524       case SIG_FXSLS:
11525       case SIG_FXSGS:
11526       case SIG_FXSKS:
11527             i->ringt = i->ringt_base;
11528             /* Fall through */
11529       case SIG_EMWINK:
11530       case SIG_FEATD:
11531       case SIG_FEATDMF:
11532       case SIG_FEATDMF_TA:
11533       case SIG_E911:
11534       case SIG_FGC_CAMA:
11535       case SIG_FGC_CAMAMF:
11536       case SIG_FEATB:
11537       case SIG_EM:
11538       case SIG_EM_E1:
11539       case SIG_SFWINK:
11540       case SIG_SF_FEATD:
11541       case SIG_SF_FEATDMF:
11542       case SIG_SF_FEATB:
11543       case SIG_SF:
11544          /* Check for callerid, digits, etc */
11545          if (i->cid_start == CID_START_POLARITY_IN) {
11546             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11547          } else {
11548             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11549          }
11550 
11551          if (!chan) {
11552             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11553          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11554             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11555             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11556             if (res < 0) {
11557                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11558             }
11559             ast_hangup(chan);
11560          }
11561          break;
11562       default:
11563          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11564          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11565          if (res < 0)
11566             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11567          return NULL;
11568       }
11569       break;
11570    case DAHDI_EVENT_NOALARM:
11571       switch (i->sig) {
11572 #if defined(HAVE_PRI)
11573       case SIG_PRI_LIB_HANDLE_CASES:
11574          ast_mutex_lock(&i->lock);
11575          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11576          ast_mutex_unlock(&i->lock);
11577          break;
11578 #endif   /* defined(HAVE_PRI) */
11579 #if defined(HAVE_SS7)
11580       case SIG_SS7:
11581          sig_ss7_set_alarm(i->sig_pvt, 0);
11582          break;
11583 #endif   /* defined(HAVE_SS7) */
11584       default:
11585          i->inalarm = 0;
11586          break;
11587       }
11588       handle_clear_alarms(i);
11589       break;
11590    case DAHDI_EVENT_ALARM:
11591       switch (i->sig) {
11592 #if defined(HAVE_PRI)
11593       case SIG_PRI_LIB_HANDLE_CASES:
11594          ast_mutex_lock(&i->lock);
11595          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11596          ast_mutex_unlock(&i->lock);
11597          break;
11598 #endif   /* defined(HAVE_PRI) */
11599 #if defined(HAVE_SS7)
11600       case SIG_SS7:
11601          sig_ss7_set_alarm(i->sig_pvt, 1);
11602          break;
11603 #endif   /* defined(HAVE_SS7) */
11604       default:
11605          i->inalarm = 1;
11606          break;
11607       }
11608       res = get_alarms(i);
11609       handle_alarms(i, res);
11610       /* fall thru intentionally */
11611    case DAHDI_EVENT_ONHOOK:
11612       if (i->radio)
11613          break;
11614       /* Back on hook.  Hang up. */
11615       switch (i->sig) {
11616       case SIG_FXOLS:
11617       case SIG_FXOGS:
11618       case SIG_FEATD:
11619       case SIG_FEATDMF:
11620       case SIG_FEATDMF_TA:
11621       case SIG_E911:
11622       case SIG_FGC_CAMA:
11623       case SIG_FGC_CAMAMF:
11624       case SIG_FEATB:
11625       case SIG_EM:
11626       case SIG_EM_E1:
11627       case SIG_EMWINK:
11628       case SIG_SF_FEATD:
11629       case SIG_SF_FEATDMF:
11630       case SIG_SF_FEATB:
11631       case SIG_SF:
11632       case SIG_SFWINK:
11633       case SIG_FXSLS:
11634       case SIG_FXSGS:
11635       case SIG_FXSKS:
11636       case SIG_FXOKS:
11637          dahdi_disable_ec(i);
11638          /* Diddle the battery for the zhone */
11639 #ifdef ZHONE_HACK
11640          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11641          usleep(1);
11642 #endif
11643          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11644          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11645          break;
11646       case SIG_SS7:
11647       case SIG_PRI_LIB_HANDLE_CASES:
11648          dahdi_disable_ec(i);
11649          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11650          break;
11651       default:
11652          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11653          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11654          return NULL;
11655       }
11656       break;
11657    case DAHDI_EVENT_POLARITY:
11658       switch (i->sig) {
11659       case SIG_FXSLS:
11660       case SIG_FXSKS:
11661       case SIG_FXSGS:
11662          /* We have already got a PR before the channel was
11663             created, but it wasn't handled. We need polarity
11664             to be REV for remote hangup detection to work.
11665             At least in Spain */
11666          if (i->hanguponpolarityswitch)
11667             i->polarity = POLARITY_REV;
11668          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11669             i->polarity = POLARITY_REV;
11670             ast_verb(2, "Starting post polarity "
11671                "CID detection on channel %d\n",
11672                i->channel);
11673             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11674             if (!chan) {
11675                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11676             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11677                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11678                ast_hangup(chan);
11679             }
11680          }
11681          break;
11682       default:
11683          ast_log(LOG_WARNING, "handle_init_event detected "
11684             "polarity reversal on non-FXO (SIG_FXS) "
11685             "interface %d\n", i->channel);
11686       }
11687       break;
11688    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11689       ast_log(LOG_NOTICE,
11690             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11691             i->channel);
11692       return i;
11693    case DAHDI_EVENT_NEONMWI_ACTIVE:
11694       if (i->mwimonitor_neon) {
11695          notify_message(i->mailbox, 1);
11696          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11697       }
11698       break;
11699    case DAHDI_EVENT_NEONMWI_INACTIVE:
11700       if (i->mwimonitor_neon) {
11701          notify_message(i->mailbox, 0);
11702          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11703       }
11704       break;
11705    }
11706    return NULL;
11707 }
11708 
11709 static void monitor_pfds_clean(void *arg) {
11710    struct pollfd **pfds = arg;
11711    ast_free(*pfds);
11712 }
11713 
11714 static void *do_monitor(void *data)
11715 {
11716    int count, res, res2, spoint, pollres=0;
11717    struct dahdi_pvt *i;
11718    struct dahdi_pvt *last = NULL;
11719    struct dahdi_pvt *doomed;
11720    time_t thispass = 0, lastpass = 0;
11721    int found;
11722    char buf[1024];
11723    struct pollfd *pfds=NULL;
11724    int lastalloc = -1;
11725    /* This thread monitors all the frame relay interfaces which are not yet in use
11726       (and thus do not have a separate thread) indefinitely */
11727    /* From here on out, we die whenever asked */
11728 #if 0
11729    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11730       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11731       return NULL;
11732    }
11733    ast_debug(1, "Monitor starting...\n");
11734 #endif
11735    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11736 
11737    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11738    for (;;) {
11739       /* Lock the interface list */
11740       ast_mutex_lock(&iflock);
11741       if (!pfds || (lastalloc != ifcount)) {
11742          if (pfds) {
11743             ast_free(pfds);
11744             pfds = NULL;
11745          }
11746          if (ifcount) {
11747             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11748                ast_mutex_unlock(&iflock);
11749                return NULL;
11750             }
11751          }
11752          lastalloc = ifcount;
11753       }
11754       /* Build the stuff we're going to poll on, that is the socket of every
11755          dahdi_pvt that does not have an associated owner channel */
11756       count = 0;
11757       for (i = iflist; i; i = i->next) {
11758          ast_mutex_lock(&i->lock);
11759          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11760             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11761                struct analog_pvt *p = i->sig_pvt;
11762 
11763                if (!p) {
11764                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11765                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11766                   /* This needs to be watched, as it lacks an owner */
11767                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11768                   pfds[count].events = POLLPRI;
11769                   pfds[count].revents = 0;
11770                   /* Message waiting or r2 channels also get watched for reading */
11771                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11772                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11773                      pfds[count].events |= POLLIN;
11774                   }
11775                   count++;
11776                }
11777             } else {
11778                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11779                   /* This needs to be watched, as it lacks an owner */
11780                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11781                   pfds[count].events = POLLPRI;
11782                   pfds[count].revents = 0;
11783                   /* If we are monitoring for VMWI or sending CID, we need to
11784                      read from the channel as well */
11785                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11786                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11787                      pfds[count].events |= POLLIN;
11788                   }
11789                   count++;
11790                }
11791             }
11792          }
11793          ast_mutex_unlock(&i->lock);
11794       }
11795       /* Okay, now that we know what to do, release the interface lock */
11796       ast_mutex_unlock(&iflock);
11797 
11798       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11799       pthread_testcancel();
11800       /* Wait at least a second for something to happen */
11801       res = poll(pfds, count, 1000);
11802       pthread_testcancel();
11803       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11804 
11805       /* Okay, poll has finished.  Let's see what happened.  */
11806       if (res < 0) {
11807          if ((errno != EAGAIN) && (errno != EINTR))
11808             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11809          continue;
11810       }
11811       /* Alright, lock the interface list again, and let's look and see what has
11812          happened */
11813       ast_mutex_lock(&iflock);
11814       found = 0;
11815       spoint = 0;
11816       lastpass = thispass;
11817       thispass = time(NULL);
11818       doomed = NULL;
11819       for (i = iflist;; i = i->next) {
11820          if (doomed) {
11821             int res;
11822             res = dahdi_destroy_channel_bynum(doomed->channel);
11823             if (res != RESULT_SUCCESS) {
11824                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11825             }
11826             doomed = NULL;
11827          }
11828          if (!i) {
11829             break;
11830          }
11831 
11832          if (thispass != lastpass) {
11833             if (!found && ((i == last) || ((i == iflist) && !last))) {
11834                last = i;
11835                if (last) {
11836                   struct analog_pvt *analog_p = last->sig_pvt;
11837                   /* Only allow MWI to be initiated on a quiescent fxs port */
11838                   if (analog_p
11839                      && !last->mwisendactive
11840                      && (last->sig & __DAHDI_SIG_FXO)
11841                      && !analog_p->fxsoffhookstate
11842                      && !last->owner
11843                      && !ast_strlen_zero(last->mailbox)
11844                      && (thispass - analog_p->onhooktime > 3)) {
11845                      res = has_voicemail(last);
11846                      if (analog_p->msgstate != res) {
11847                         /* Set driver resources for signalling VMWI */
11848                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11849                         if (res2) {
11850                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11851                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11852                         }
11853                         /* If enabled for FSK spill then initiate it */
11854                         if (mwi_send_init(last)) {
11855                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11856                         }
11857                         analog_p->msgstate = res;
11858                         found ++;
11859                      }
11860                   }
11861                   last = last->next;
11862                }
11863             }
11864          }
11865          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11866             if (i->radio && !i->owner)
11867             {
11868                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11869                if (res)
11870                {
11871                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11872                   /* Don't hold iflock while handling init events */
11873                   ast_mutex_unlock(&iflock);
11874                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11875                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11876                   else
11877                      doomed = handle_init_event(i, res);
11878                   ast_mutex_lock(&iflock);
11879                }
11880                continue;
11881             }
11882             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11883             if (pollres & POLLIN) {
11884                if (i->owner || i->subs[SUB_REAL].owner) {
11885 #ifdef HAVE_PRI
11886                   if (!i->pri)
11887 #endif
11888                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11889                   continue;
11890                }
11891                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11892                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11893                   continue;
11894                }
11895                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11896                if (res > 0) {
11897                   if (i->mwimonitor_fsk) {
11898                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11899                         pthread_attr_t attr;
11900                         pthread_t threadid;
11901                         struct mwi_thread_data *mtd;
11902 
11903                         pthread_attr_init(&attr);
11904                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11905 
11906                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11907                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11908                            mtd->pvt = i;
11909                            memcpy(mtd->buf, buf, res);
11910                            mtd->len = res;
11911                            i->mwimonitoractive = 1;
11912                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11913                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11914                               i->mwimonitoractive = 0;
11915                               ast_free(mtd);
11916                            }
11917                         }
11918                      }
11919                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11920                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11921                      int energy;
11922                      struct timeval now;
11923                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11924                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11925                      */
11926                      if (1 == i->dtmfcid_holdoff_state) {
11927                         gettimeofday(&i->dtmfcid_delay, NULL);
11928                         i->dtmfcid_holdoff_state = 2;
11929                      } else if (2 == i->dtmfcid_holdoff_state) {
11930                         gettimeofday(&now, NULL);
11931                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11932                            i->dtmfcid_holdoff_state = 0;
11933                         }
11934                      } else {
11935                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11936                         if (!i->mwisendactive && energy > dtmfcid_level) {
11937                            pthread_t threadid;
11938                            struct ast_channel *chan;
11939                            ast_mutex_unlock(&iflock);
11940                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11941                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11942                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11943                               i->dtmfcid_holdoff_state = 1;
11944                            } else {
11945                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11946                               if (!chan) {
11947                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11948                               } else {
11949                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11950                                  if (res) {
11951                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11952                                     ast_hangup(chan);
11953                                  } else {
11954                                     i->dtmfcid_holdoff_state = 1;
11955                                  }
11956                               }
11957                            }
11958                            ast_mutex_lock(&iflock);
11959                         }
11960                      }
11961                   }
11962                   if (i->mwisendactive) {
11963                      mwi_send_process_buffer(i, res);
11964                   }
11965                } else {
11966                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11967                }
11968             }
11969             if (pollres & POLLPRI) {
11970                if (i->owner || i->subs[SUB_REAL].owner) {
11971 #ifdef HAVE_PRI
11972                   if (!i->pri)
11973 #endif
11974                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11975                   continue;
11976                }
11977                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11978                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11979                /* Don't hold iflock while handling init events */
11980                ast_mutex_unlock(&iflock);
11981                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11982                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11983                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11984                   else
11985                      doomed = handle_init_event(i, res);
11986                }
11987                ast_mutex_lock(&iflock);
11988             }
11989          }
11990       }
11991       ast_mutex_unlock(&iflock);
11992    }
11993    /* Never reached */
11994    pthread_cleanup_pop(1);
11995    return NULL;
11996 
11997 }
11998 
11999 static int restart_monitor(void)
12000 {
12001    /* If we're supposed to be stopped -- stay stopped */
12002    if (monitor_thread == AST_PTHREADT_STOP)
12003       return 0;
12004    ast_mutex_lock(&monlock);
12005    if (monitor_thread == pthread_self()) {
12006       ast_mutex_unlock(&monlock);
12007       ast_log(LOG_WARNING, "Cannot kill myself\n");
12008       return -1;
12009    }
12010    if (monitor_thread != AST_PTHREADT_NULL) {
12011       /* Wake up the thread */
12012       pthread_kill(monitor_thread, SIGURG);
12013    } else {
12014       /* Start a new monitor */
12015       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12016          ast_mutex_unlock(&monlock);
12017          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12018          return -1;
12019       }
12020    }
12021    ast_mutex_unlock(&monlock);
12022    return 0;
12023 }
12024 
12025 #if defined(HAVE_PRI)
12026 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12027 {
12028    int x;
12029    int trunkgroup;
12030    /* Get appropriate trunk group if there is one */
12031    trunkgroup = pris[*span].mastertrunkgroup;
12032    if (trunkgroup) {
12033       /* Select a specific trunk group */
12034       for (x = 0; x < NUM_SPANS; x++) {
12035          if (pris[x].pri.trunkgroup == trunkgroup) {
12036             *span = x;
12037             return 0;
12038          }
12039       }
12040       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12041       *span = -1;
12042    } else {
12043       if (pris[*span].pri.trunkgroup) {
12044          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);
12045          *span = -1;
12046       } else if (pris[*span].mastertrunkgroup) {
12047          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12048          *span = -1;
12049       } else {
12050          if (si->totalchans == 31) {
12051             /* E1 */
12052             pris[*span].dchannels[0] = 16 + offset;
12053          } else if (si->totalchans == 24) {
12054             /* T1 or J1 */
12055             pris[*span].dchannels[0] = 24 + offset;
12056          } else if (si->totalchans == 3) {
12057             /* BRI */
12058             pris[*span].dchannels[0] = 3 + offset;
12059          } else {
12060             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);
12061             *span = -1;
12062             return 0;
12063          }
12064          pris[*span].pri.span = *span + 1;
12065       }
12066    }
12067    return 0;
12068 }
12069 #endif   /* defined(HAVE_PRI) */
12070 
12071 #if defined(HAVE_PRI)
12072 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12073 {
12074    struct dahdi_spaninfo si;
12075    struct dahdi_params p;
12076    int fd;
12077    int span;
12078    int ospan=0;
12079    int x,y;
12080    for (x = 0; x < NUM_SPANS; x++) {
12081       if (pris[x].pri.trunkgroup == trunkgroup) {
12082          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12083          return -1;
12084       }
12085    }
12086    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12087       if (!channels[y])
12088          break;
12089       memset(&si, 0, sizeof(si));
12090       memset(&p, 0, sizeof(p));
12091       fd = open("/dev/dahdi/channel", O_RDWR);
12092       if (fd < 0) {
12093          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12094          return -1;
12095       }
12096       x = channels[y];
12097       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12098          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12099          close(fd);
12100          return -1;
12101       }
12102       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12103          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12104          return -1;
12105       }
12106       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12107          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12108          close(fd);
12109          return -1;
12110       }
12111       span = p.spanno - 1;
12112       if (pris[span].pri.trunkgroup) {
12113          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12114          close(fd);
12115          return -1;
12116       }
12117       if (pris[span].pri.pvts[0]) {
12118          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12119          close(fd);
12120          return -1;
12121       }
12122       if (!y) {
12123          pris[span].pri.trunkgroup = trunkgroup;
12124          ospan = span;
12125       }
12126       pris[ospan].dchannels[y] = channels[y];
12127       pris[span].pri.span = span + 1;
12128       close(fd);
12129    }
12130    return 0;
12131 }
12132 #endif   /* defined(HAVE_PRI) */
12133 
12134 #if defined(HAVE_PRI)
12135 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12136 {
12137    if (pris[span].mastertrunkgroup) {
12138       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);
12139       return -1;
12140    }
12141    pris[span].mastertrunkgroup = trunkgroup;
12142    pris[span].prilogicalspan = logicalspan;
12143    return 0;
12144 }
12145 #endif   /* defined(HAVE_PRI) */
12146 
12147 #if defined(HAVE_SS7)
12148 static unsigned int parse_pointcode(const char *pcstring)
12149 {
12150    unsigned int code1, code2, code3;
12151    int numvals;
12152 
12153    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12154    if (numvals == 1)
12155       return code1;
12156    if (numvals == 3)
12157       return (code1 << 16) | (code2 << 8) | code3;
12158 
12159    return 0;
12160 }
12161 #endif   /* defined(HAVE_SS7) */
12162 
12163 #if defined(HAVE_SS7)
12164 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12165 {
12166    if ((linkset < 0) || (linkset >= NUM_SPANS))
12167       return NULL;
12168    else
12169       return &linksets[linkset - 1];
12170 }
12171 #endif   /* defined(HAVE_SS7) */
12172 
12173 #ifdef HAVE_OPENR2
12174 static void dahdi_r2_destroy_links(void)
12175 {
12176    int i = 0;
12177    if (!r2links) {
12178       return;
12179    }
12180    for (; i < r2links_count; i++) {
12181       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12182          pthread_cancel(r2links[i]->r2master);
12183          pthread_join(r2links[i]->r2master, NULL);
12184          openr2_context_delete(r2links[i]->protocol_context);
12185       }
12186       ast_free(r2links[i]);
12187    }
12188    ast_free(r2links);
12189    r2links = NULL;
12190    r2links_count = 0;
12191 }
12192 
12193 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12194 #define R2_LINK_CAPACITY 30
12195 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12196 {
12197    struct dahdi_mfcr2 *new_r2link = NULL;
12198    struct dahdi_mfcr2 **new_r2links = NULL;
12199 
12200    /* Only create a new R2 link if 
12201       1. This is the first link requested
12202       2. Configuration changed 
12203       3. We got more channels than supported per link */
12204    if (!r2links_count ||
12205        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12206       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12207       new_r2link = ast_calloc(1, sizeof(**r2links));
12208       if (!new_r2link) {
12209          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12210          return NULL;
12211       }
12212       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12213       if (!new_r2links) {
12214          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12215          ast_free(new_r2link);
12216          return NULL;
12217       }
12218       r2links = new_r2links;
12219       new_r2link->r2master = AST_PTHREADT_NULL;
12220       r2links[r2links_count] = new_r2link;
12221       r2links_count++;
12222       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12223    }
12224    return r2links[r2links_count - 1];
12225 }
12226 
12227 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12228 {
12229    char tmplogdir[] = "/tmp";
12230    char logdir[OR2_MAX_PATH];
12231    int threshold = 0;
12232    int snres = 0;
12233    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12234          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12235          conf->mfcr2.max_dnis);
12236    if (!r2_link->protocol_context) {
12237       return -1;
12238    }
12239    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12240    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12241 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12242    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12243 #endif
12244    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12245    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12246    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12247    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12248    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12249    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12250       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12251          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12252       }
12253    } else {
12254       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12255       if (snres >= sizeof(logdir)) {
12256          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12257          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12258             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12259          }
12260       } else {
12261          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12262             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12263          }
12264       }
12265    }
12266    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12267       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12268          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12269       }
12270    }
12271    /* Save the configuration used to setup this link */
12272    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
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(conf);
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          }
12547 #endif
12548 #ifdef HAVE_PRI
12549          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12550             int offset;
12551             int matchesdchan;
12552             int x,y;
12553             int myswitchtype = 0;
12554 
12555             offset = 0;
12556             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12557                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12558                destroy_dahdi_pvt(tmp);
12559                return NULL;
12560             }
12561             if (span >= NUM_SPANS) {
12562                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12563                destroy_dahdi_pvt(tmp);
12564                return NULL;
12565             } else {
12566                si.spanno = 0;
12567                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12568                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12569                   destroy_dahdi_pvt(tmp);
12570                   return NULL;
12571                }
12572                /* Store the logical span first based upon the real span */
12573                tmp->logicalspan = pris[span].prilogicalspan;
12574                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12575                if (span < 0) {
12576                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12577                   destroy_dahdi_pvt(tmp);
12578                   return NULL;
12579                }
12580                myswitchtype = conf->pri.pri.switchtype;
12581                /* Make sure this isn't a d-channel */
12582                matchesdchan=0;
12583                for (x = 0; x < NUM_SPANS; x++) {
12584                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12585                      if (pris[x].dchannels[y] == tmp->channel) {
12586                         matchesdchan = 1;
12587                         break;
12588                      }
12589                   }
12590                }
12591                if (!matchesdchan) {
12592                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12593                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12594                      destroy_dahdi_pvt(tmp);
12595                      return NULL;
12596                   }
12597                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12598                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12599                      destroy_dahdi_pvt(tmp);
12600                      return NULL;
12601                   }
12602                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12603                      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));
12604                      destroy_dahdi_pvt(tmp);
12605                      return NULL;
12606                   }
12607                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12608                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12609                      destroy_dahdi_pvt(tmp);
12610                      return NULL;
12611                   }
12612                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12613                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12614                      destroy_dahdi_pvt(tmp);
12615                      return NULL;
12616                   }
12617                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12618                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12619                      destroy_dahdi_pvt(tmp);
12620                      return NULL;
12621                   }
12622                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12623                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12624                      destroy_dahdi_pvt(tmp);
12625                      return NULL;
12626                   }
12627                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12628                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12629                         pris[span].pri.trunkgroup);
12630                      destroy_dahdi_pvt(tmp);
12631                      return NULL;
12632                   }
12633 
12634                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12635                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12636                   if (!pri_chan) {
12637                      destroy_dahdi_pvt(tmp);
12638                      return NULL;
12639                   }
12640                   tmp->sig_pvt = pri_chan;
12641                   tmp->pri = &pris[span].pri;
12642 
12643                   tmp->priexclusive = conf->chan.priexclusive;
12644 
12645                   if (!tmp->pri->cc_params) {
12646                      tmp->pri->cc_params = ast_cc_config_params_init();
12647                      if (!tmp->pri->cc_params) {
12648                         destroy_dahdi_pvt(tmp);
12649                         return NULL;
12650                      }
12651                   }
12652                   ast_cc_copy_config_params(tmp->pri->cc_params,
12653                      conf->chan.cc_params);
12654 
12655                   pris[span].pri.sig = chan_sig;
12656                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12657                   pris[span].pri.switchtype = myswitchtype;
12658                   pris[span].pri.nsf = conf->pri.pri.nsf;
12659                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12660                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12661                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12662                   pris[span].pri.minunused = conf->pri.pri.minunused;
12663                   pris[span].pri.minidle = conf->pri.pri.minidle;
12664                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12665                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12666                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12667 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12668                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12669 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12670 #ifdef HAVE_PRI_INBANDDISCONNECT
12671                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12672 #endif
12673 #if defined(HAVE_PRI_CALL_HOLD)
12674                   pris[span].pri.hold_disconnect_transfer =
12675                      conf->pri.pri.hold_disconnect_transfer;
12676 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12677 #if defined(HAVE_PRI_CCSS)
12678                   pris[span].pri.cc_ptmp_recall_mode =
12679                      conf->pri.pri.cc_ptmp_recall_mode;
12680                   pris[span].pri.cc_qsig_signaling_link_req =
12681                      conf->pri.pri.cc_qsig_signaling_link_req;
12682                   pris[span].pri.cc_qsig_signaling_link_rsp =
12683                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12684 #endif   /* defined(HAVE_PRI_CCSS) */
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686                   pris[span].pri.max_call_waiting_calls =
12687                      conf->pri.pri.max_call_waiting_calls;
12688                   pris[span].pri.allow_call_waiting_calls =
12689                      conf->pri.pri.allow_call_waiting_calls;
12690 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12691                   pris[span].pri.transfer = conf->chan.transfer;
12692                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12693 #if defined(HAVE_PRI_L2_PERSISTENCE)
12694                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12695 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12696 #if defined(HAVE_PRI_AOC_EVENTS)
12697                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12698                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12699 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12700                   if (chan_sig == SIG_BRI_PTMP) {
12701                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12702                   } else {
12703                      /* Option does not apply to this line type. */
12704                      pris[span].pri.layer1_ignored = 0;
12705                   }
12706                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12707                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
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->busy_tonelength = conf->chan.busy_tonelength;
12892       tmp->busy_quietlength = conf->chan.busy_quietlength;
12893       tmp->callprogress = conf->chan.callprogress;
12894       tmp->waitfordialtone = conf->chan.waitfordialtone;
12895       tmp->cancallforward = conf->chan.cancallforward;
12896       tmp->dtmfrelax = conf->chan.dtmfrelax;
12897       tmp->callwaiting = tmp->permcallwaiting;
12898       tmp->hidecallerid = tmp->permhidecallerid;
12899       tmp->channel = channel;
12900       tmp->stripmsd = conf->chan.stripmsd;
12901       tmp->use_callerid = conf->chan.use_callerid;
12902       tmp->cid_signalling = conf->chan.cid_signalling;
12903       tmp->cid_start = conf->chan.cid_start;
12904       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12905       tmp->restrictcid = conf->chan.restrictcid;
12906       tmp->use_callingpres = conf->chan.use_callingpres;
12907       if (tmp->usedistinctiveringdetection) {
12908          if (!tmp->use_callerid) {
12909             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12910             tmp->use_callerid = 1;
12911          }
12912       }
12913 
12914       if (tmp->cid_signalling == CID_SIG_SMDI) {
12915          if (!tmp->use_smdi) {
12916             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12917             tmp->use_smdi = 1;
12918          }
12919       }
12920       if (tmp->use_smdi) {
12921          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12922          if (!(tmp->smdi_iface)) {
12923             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12924             tmp->use_smdi = 0;
12925          }
12926       }
12927 
12928       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12929       tmp->amaflags = conf->chan.amaflags;
12930       if (!here) {
12931          tmp->confno = -1;
12932          tmp->propconfno = -1;
12933       }
12934       tmp->canpark = conf->chan.canpark;
12935       tmp->transfer = conf->chan.transfer;
12936       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12937       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12938       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12939       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12940       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12941       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12942       tmp->cid_ton = 0;
12943       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12944          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12945          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12946       } else {
12947          tmp->cid_num[0] = '\0';
12948          tmp->cid_name[0] = '\0';
12949       }
12950 #if defined(HAVE_PRI)
12951       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12952          tmp->cid_tag[0] = '\0';
12953       } else
12954 #endif   /* defined(HAVE_PRI) */
12955       {
12956          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12957       }
12958       tmp->cid_subaddr[0] = '\0';
12959       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12960       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12961          char *mailbox, *context;
12962          mailbox = context = ast_strdupa(tmp->mailbox);
12963          strsep(&context, "@");
12964          if (ast_strlen_zero(context))
12965             context = "default";
12966          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12967             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12968             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12969             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12970             AST_EVENT_IE_END);
12971       }
12972 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12973       tmp->mwisend_setting = conf->chan.mwisend_setting;
12974       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12975       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12976 #endif
12977 
12978       tmp->group = conf->chan.group;
12979       tmp->callgroup = conf->chan.callgroup;
12980       tmp->pickupgroup= conf->chan.pickupgroup;
12981       if (conf->chan.vars) {
12982          struct ast_variable *v, *tmpvar;
12983                    for (v = conf->chan.vars ; v ; v = v->next) {
12984                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12985                                   tmpvar->next = tmp->vars;
12986                                    tmp->vars = tmpvar;
12987                            }
12988                   }
12989       }
12990       tmp->cid_rxgain = conf->chan.cid_rxgain;
12991       tmp->rxgain = conf->chan.rxgain;
12992       tmp->txgain = conf->chan.txgain;
12993       tmp->txdrc = conf->chan.txdrc;
12994       tmp->rxdrc = conf->chan.rxdrc;
12995       tmp->tonezone = conf->chan.tonezone;
12996       if (tmp->subs[SUB_REAL].dfd > -1) {
12997          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12998          if (tmp->dsp)
12999             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13000          update_conf(tmp);
13001          if (!here) {
13002             switch (chan_sig) {
13003             case SIG_PRI_LIB_HANDLE_CASES:
13004             case SIG_SS7:
13005             case SIG_MFCR2:
13006                break;
13007             default:
13008                /* Hang it up to be sure it's good */
13009                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13010                break;
13011             }
13012          }
13013          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13014          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13015             /* the dchannel is down so put the channel in alarm */
13016             switch (tmp->sig) {
13017 #ifdef HAVE_PRI
13018             case SIG_PRI_LIB_HANDLE_CASES:
13019                sig_pri_set_alarm(tmp->sig_pvt, 1);
13020                break;
13021 #endif
13022 #if defined(HAVE_SS7)
13023             case SIG_SS7:
13024                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13025                break;
13026 #endif   /* defined(HAVE_SS7) */
13027             default:
13028                /* The only sig submodule left should be sig_analog. */
13029                analog_p = tmp->sig_pvt;
13030                if (analog_p) {
13031                   analog_p->inalarm = 1;
13032                }
13033                tmp->inalarm = 1;
13034                break;
13035             }
13036             handle_alarms(tmp, res);
13037          }
13038       }
13039 
13040       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13041       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13042       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13043       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13044       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13045 
13046       if (!here) {
13047          tmp->locallyblocked = 0;
13048          tmp->remotelyblocked = 0;
13049          switch (tmp->sig) {
13050 #if defined(HAVE_PRI)
13051          case SIG_PRI_LIB_HANDLE_CASES:
13052             tmp->inservice = 1;/* Inservice until actually implemented. */
13053 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13054             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13055             if (chan_sig == SIG_PRI) {
13056                char db_chan_name[20];
13057                char db_answer[5];
13058 
13059                /*
13060                 * Initialize the active out-of-service status
13061                 * and delete any record if the feature is not enabled.
13062                 */
13063                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13064                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13065                   unsigned *why;
13066 
13067                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13068                   if (tmp->pri->enable_service_message_support) {
13069                      char state;
13070 
13071                      sscanf(db_answer, "%1c:%30u", &state, why);
13072 
13073                      /* Ensure that only the implemented bits could be set.*/
13074                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13075                   }
13076                   if (!*why) {
13077                      ast_db_del(db_chan_name, SRVST_DBKEY);
13078                   }
13079                }
13080             }
13081 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13082             break;
13083 #endif   /* defined(HAVE_PRI) */
13084 #if defined(HAVE_SS7)
13085          case SIG_SS7:
13086             tmp->inservice = 0;
13087             break;
13088 #endif   /* defined(HAVE_SS7) */
13089          default:
13090              /* We default to in service on protocols that don't have a reset */
13091             tmp->inservice = 1;
13092             break;
13093          }
13094       }
13095 
13096       switch (tmp->sig) {
13097 #if defined(HAVE_PRI)
13098       case SIG_PRI_LIB_HANDLE_CASES:
13099          if (pri_chan) {
13100             pri_chan->channel = tmp->channel;
13101             pri_chan->hidecallerid = tmp->hidecallerid;
13102             pri_chan->hidecalleridname = tmp->hidecalleridname;
13103             pri_chan->immediate = tmp->immediate;
13104             pri_chan->inalarm = tmp->inalarm;
13105             pri_chan->priexclusive = tmp->priexclusive;
13106             pri_chan->priindication_oob = tmp->priindication_oob;
13107             pri_chan->use_callerid = tmp->use_callerid;
13108             pri_chan->use_callingpres = tmp->use_callingpres;
13109             ast_copy_string(pri_chan->context, tmp->context,
13110                sizeof(pri_chan->context));
13111             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13112                sizeof(pri_chan->mohinterpret));
13113             pri_chan->stripmsd = tmp->stripmsd;
13114          }
13115          break;
13116 #endif   /* defined(HAVE_PRI) */
13117 #if defined(HAVE_SS7)
13118       case SIG_SS7:
13119          if (ss7_chan) {
13120             ss7_chan->inalarm = tmp->inalarm;
13121 
13122             ss7_chan->stripmsd = tmp->stripmsd;
13123             ss7_chan->hidecallerid = tmp->hidecallerid;
13124             ss7_chan->use_callerid = tmp->use_callerid;
13125             ss7_chan->use_callingpres = tmp->use_callingpres;
13126             ss7_chan->immediate = tmp->immediate;
13127             ss7_chan->locallyblocked = tmp->locallyblocked;
13128             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13129             ast_copy_string(ss7_chan->context, tmp->context,
13130                sizeof(ss7_chan->context));
13131             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13132                sizeof(ss7_chan->mohinterpret));
13133          }
13134          break;
13135 #endif   /* defined(HAVE_SS7) */
13136       default:
13137          /* The only sig submodule left should be sig_analog. */
13138          analog_p = tmp->sig_pvt;
13139          if (analog_p) {
13140             analog_p->channel = tmp->channel;
13141             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13142             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13143             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13144             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13145             analog_p->callreturn = conf->chan.callreturn;
13146             analog_p->cancallforward = conf->chan.cancallforward;
13147             analog_p->canpark = conf->chan.canpark;
13148             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13149             analog_p->immediate = conf->chan.immediate;
13150             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13151             analog_p->pulse = conf->chan.pulse;
13152             analog_p->threewaycalling = conf->chan.threewaycalling;
13153             analog_p->transfer = conf->chan.transfer;
13154             analog_p->transfertobusy = conf->chan.transfertobusy;
13155             analog_p->use_callerid = tmp->use_callerid;
13156             analog_p->use_smdi = tmp->use_smdi;
13157             analog_p->smdi_iface = tmp->smdi_iface;
13158             analog_p->outsigmod = ANALOG_SIG_NONE;
13159             analog_p->echotraining = conf->chan.echotraining;
13160             analog_p->cid_signalling = conf->chan.cid_signalling;
13161             analog_p->stripmsd = conf->chan.stripmsd;
13162             switch (conf->chan.cid_start) {
13163             case CID_START_POLARITY:
13164                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13165                break;
13166             case CID_START_POLARITY_IN:
13167                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13168                break;
13169             case CID_START_DTMF_NOALERT:
13170                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13171                break;
13172             default:
13173                analog_p->cid_start = ANALOG_CID_START_RING;
13174                break;
13175             }
13176             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13177             analog_p->ringt = conf->chan.ringt;
13178             analog_p->ringt_base = ringt_base;
13179             analog_p->onhooktime = time(NULL);
13180             if (chan_sig & __DAHDI_SIG_FXO) {
13181                memset(&p, 0, sizeof(p));
13182                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13183                if (!res) {
13184                   analog_p->fxsoffhookstate = p.rxisoffhook;
13185                }
13186 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13187                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13188 #endif
13189             }
13190             analog_p->msgstate = -1;
13191 
13192             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13193             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13194             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13195 
13196             analog_config_complete(analog_p);
13197          }
13198          break;
13199       }
13200 #if defined(HAVE_PRI)
13201       if (tmp->channel == CHAN_PSEUDO) {
13202          /*
13203           * Save off pseudo channel buffer policy values for dynamic creation of
13204           * no B channel interfaces.
13205           */
13206          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13207          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13208          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13209          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13210       }
13211 #endif   /* defined(HAVE_PRI) */
13212    }
13213    if (tmp && !here) {
13214       /* Add the new channel interface to the sorted channel interface list. */
13215       dahdi_iflist_insert(tmp);
13216    }
13217    return tmp;
13218 }
13219 
13220 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13221 {
13222 #if defined(HAVE_PRI)
13223    if (0 < span) {
13224       /* The channel must be on the specified PRI span. */
13225       if (!p->pri || p->pri->span != span) {
13226          return 0;
13227       }
13228       if (!groupmatch && channelmatch == -1) {
13229          /* Match any group since it only needs to be on the PRI span. */
13230          *groupmatched = 1;
13231          return 1;
13232       }
13233    }
13234 #endif   /* defined(HAVE_PRI) */
13235    /* check group matching */
13236    if (groupmatch) {
13237       if ((p->group & groupmatch) != groupmatch)
13238          /* Doesn't match the specified group, try the next one */
13239          return 0;
13240       *groupmatched = 1;
13241    }
13242    /* Check to see if we have a channel match */
13243    if (channelmatch != -1) {
13244       if (p->channel != channelmatch)
13245          /* Doesn't match the specified channel, try the next one */
13246          return 0;
13247       *channelmatched = 1;
13248    }
13249 
13250    return 1;
13251 }
13252 
13253 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13254 {
13255    struct dahdi_pvt *p = *pvt;
13256 
13257    if (p->inalarm)
13258       return 0;
13259 
13260    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13261       return analog_available(p->sig_pvt);
13262 
13263    switch (p->sig) {
13264 #if defined(HAVE_PRI)
13265    case SIG_PRI_LIB_HANDLE_CASES:
13266       {
13267          struct sig_pri_chan *pvt_chan;
13268          int res;
13269 
13270          pvt_chan = p->sig_pvt;
13271          res = sig_pri_available(&pvt_chan, is_specific_channel);
13272          *pvt = pvt_chan->chan_pvt;
13273          return res;
13274       }
13275 #endif   /* defined(HAVE_PRI) */
13276 #if defined(HAVE_SS7)
13277    case SIG_SS7:
13278       return sig_ss7_available(p->sig_pvt);
13279 #endif   /* defined(HAVE_SS7) */
13280    default:
13281       break;
13282    }
13283 
13284    if (p->locallyblocked || p->remotelyblocked) {
13285       return 0;
13286    }
13287 
13288    /* If no owner definitely available */
13289    if (!p->owner) {
13290 #ifdef HAVE_OPENR2
13291       /* Trust MFC/R2 */
13292       if (p->mfcr2) {
13293          if (p->mfcr2call) {
13294             return 0;
13295          } else {
13296             return 1;
13297          }
13298       }
13299 #endif
13300       return 1;
13301    }
13302 
13303    return 0;
13304 }
13305 
13306 #if defined(HAVE_PRI)
13307 #if defined(HAVE_PRI_CALL_WAITING)
13308 /*!
13309  * \internal
13310  * \brief Init the private channel configuration using the span controller.
13311  * \since 1.8
13312  *
13313  * \param priv Channel to init the configuration.
13314  * \param pri sig_pri PRI control structure.
13315  *
13316  * \note Assumes the pri->lock is already obtained.
13317  *
13318  * \return Nothing
13319  */
13320 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13321 {
13322    struct dahdi_pvt *pvt = priv;
13323 
13324    pvt->stripmsd = pri->ch_cfg.stripmsd;
13325    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13326    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13327    pvt->immediate = pri->ch_cfg.immediate;
13328    pvt->priexclusive = pri->ch_cfg.priexclusive;
13329    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13330    pvt->use_callerid = pri->ch_cfg.use_callerid;
13331    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13332    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13333    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13334 }
13335 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13336 #endif   /* defined(HAVE_PRI) */
13337 
13338 #if defined(HAVE_PRI)
13339 /*!
13340  * \internal
13341  * \brief Create a no B channel interface.
13342  * \since 1.8
13343  *
13344  * \param pri sig_pri span controller to add interface.
13345  *
13346  * \note Assumes the pri->lock is already obtained.
13347  *
13348  * \retval array-index into private pointer array on success.
13349  * \retval -1 on error.
13350  */
13351 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13352 {
13353    int pvt_idx;
13354    int res;
13355    unsigned idx;
13356    struct dahdi_pvt *pvt;
13357    struct sig_pri_chan *chan;
13358    struct dahdi_bufferinfo bi;
13359 
13360    static int nobch_channel = CHAN_PSEUDO;
13361 
13362    /* Find spot in the private pointer array for new interface. */
13363    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13364       if (!pri->pvts[pvt_idx]) {
13365          break;
13366       }
13367    }
13368    if (pri->numchans == pvt_idx) {
13369       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13370          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13371          return -1;
13372       }
13373 
13374       /* Add new spot to the private pointer array. */
13375       pri->pvts[pvt_idx] = NULL;
13376       ++pri->numchans;
13377    }
13378 
13379    pvt = ast_calloc(1, sizeof(*pvt));
13380    if (!pvt) {
13381       return -1;
13382    }
13383    pvt->cc_params = ast_cc_config_params_init();
13384    if (!pvt->cc_params) {
13385       ast_free(pvt);
13386       return -1;
13387    }
13388    ast_mutex_init(&pvt->lock);
13389    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13390       pvt->subs[idx].dfd = -1;
13391    }
13392    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13393    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13394    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13395    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13396 
13397    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13398    if (!chan) {
13399       destroy_dahdi_pvt(pvt);
13400       return -1;
13401    }
13402    chan->no_b_channel = 1;
13403 
13404    /*
13405     * Pseudo channel companding law.
13406     * Needed for outgoing call waiting calls.
13407     * XXX May need to make this determined by switchtype or user option.
13408     */
13409    pvt->law_default = DAHDI_LAW_ALAW;
13410 
13411    pvt->sig = pri->sig;
13412    pvt->outsigmod = -1;
13413    pvt->pri = pri;
13414    pvt->sig_pvt = chan;
13415    pri->pvts[pvt_idx] = chan;
13416 
13417    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13418    if (pvt->subs[SUB_REAL].dfd < 0) {
13419       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13420          strerror(errno));
13421       destroy_dahdi_pvt(pvt);
13422       return -1;
13423    }
13424    memset(&bi, 0, sizeof(bi));
13425    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13426    if (!res) {
13427       pvt->bufsize = bi.bufsize;
13428       bi.txbufpolicy = pvt->buf_policy;
13429       bi.rxbufpolicy = pvt->buf_policy;
13430       bi.numbufs = pvt->buf_no;
13431       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13432       if (res < 0) {
13433          ast_log(LOG_WARNING,
13434             "Unable to set buffer policy on no B channel interface: %s\n",
13435             strerror(errno));
13436       }
13437    } else
13438       ast_log(LOG_WARNING,
13439          "Unable to check buffer policy on no B channel interface: %s\n",
13440          strerror(errno));
13441 
13442    --nobch_channel;
13443    if (CHAN_PSEUDO < nobch_channel) {
13444       nobch_channel = CHAN_PSEUDO - 1;
13445    }
13446    pvt->channel = nobch_channel;
13447    pvt->span = pri->span;
13448    chan->channel = pvt->channel;
13449 
13450    dahdi_nobch_insert(pri, pvt);
13451 
13452    return pvt_idx;
13453 }
13454 #endif   /* defined(HAVE_PRI) */
13455 
13456 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13457    structures; it makes no attempt to safely copy regular channel private
13458    structures that might contain reference-counted object pointers and other
13459    scary bits
13460 */
13461 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13462 {
13463    struct dahdi_pvt *p;
13464    struct dahdi_bufferinfo bi;
13465    int res;
13466 
13467    p = ast_malloc(sizeof(*p));
13468    if (!p) {
13469       return NULL;
13470    }
13471    *p = *src;
13472 
13473    /* Must deep copy the cc_params. */
13474    p->cc_params = ast_cc_config_params_init();
13475    if (!p->cc_params) {
13476       ast_free(p);
13477       return NULL;
13478    }
13479    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13480 
13481    p->which_iflist = DAHDI_IFLIST_NONE;
13482    p->next = NULL;
13483    p->prev = NULL;
13484    ast_mutex_init(&p->lock);
13485    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13486    if (p->subs[SUB_REAL].dfd < 0) {
13487       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13488       destroy_dahdi_pvt(p);
13489       return NULL;
13490    }
13491    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13492    if (!res) {
13493       bi.txbufpolicy = src->buf_policy;
13494       bi.rxbufpolicy = src->buf_policy;
13495       bi.numbufs = src->buf_no;
13496       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13497       if (res < 0) {
13498          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13499       }
13500    } else
13501       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13502    p->destroy = 1;
13503    dahdi_iflist_insert(p);
13504    return p;
13505 }
13506 
13507 struct dahdi_starting_point {
13508    /*! Group matching mask.  Zero if not specified. */
13509    ast_group_t groupmatch;
13510    /*! DAHDI channel to match with.  -1 if not specified. */
13511    int channelmatch;
13512    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13513    int rr_starting_point;
13514    /*! ISDN span where channels can be picked (Zero if not specified) */
13515    int span;
13516    /*! Analog channel distinctive ring cadance index. */
13517    int cadance;
13518    /*! Dialing option. c/r/d if present and valid. */
13519    char opt;
13520    /*! TRUE if to search the channel list backwards. */
13521    char backwards;
13522    /*! TRUE if search is done with round robin sequence. */
13523    char roundrobin;
13524 };
13525 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13526 {
13527    char *dest;
13528    char *s;
13529    int x;
13530    int res = 0;
13531    struct dahdi_pvt *p;
13532    char *subdir = NULL;
13533    AST_DECLARE_APP_ARGS(args,
13534       AST_APP_ARG(group);  /* channel/group token */
13535       //AST_APP_ARG(ext);  /* extension token */
13536       //AST_APP_ARG(opts); /* options token */
13537       AST_APP_ARG(other);  /* Any remining unused arguments */
13538    );
13539 
13540    /*
13541     * data is ---v
13542     * Dial(DAHDI/pseudo[/extension[/options]])
13543     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13544     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13545     * Dial(DAHDI/i<span>[/extension[/options]])
13546     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13547     *
13548     * i - ISDN span channel restriction.
13549     *     Used by CC to ensure that the CC recall goes out the same span.
13550     *     Also to make ISDN channel names dialable when the sequence number
13551     *     is stripped off.  (Used by DTMF attended transfer feature.)
13552     *
13553     * g - channel group allocation search forward
13554     * G - channel group allocation search backward
13555     * r - channel group allocation round robin search forward
13556     * R - channel group allocation round robin search backward
13557     *
13558     * c - Wait for DTMF digit to confirm answer
13559     * r<cadance#> - Set distintive ring cadance number
13560     * d - Force bearer capability for ISDN/SS7 call to digital.
13561     */
13562 
13563    if (data) {
13564       dest = ast_strdupa(data);
13565    } else {
13566       ast_log(LOG_WARNING, "Channel requested with no data\n");
13567       return NULL;
13568    }
13569    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13570    if (!args.argc || ast_strlen_zero(args.group)) {
13571       ast_log(LOG_WARNING, "No channel/group specified\n");
13572       return NULL;
13573    }
13574 
13575    /* Initialize the output parameters */
13576    memset(param, 0, sizeof(*param));
13577    param->channelmatch = -1;
13578 
13579    if (strchr(args.group, '!') != NULL) {
13580       char *prev = args.group;
13581       while ((s = strchr(prev, '!')) != NULL) {
13582          *s++ = '/';
13583          prev = s;
13584       }
13585       *(prev - 1) = '\0';
13586       subdir = args.group;
13587       args.group = prev;
13588    } else if (args.group[0] == 'i') {
13589       /* Extract the ISDN span channel restriction specifier. */
13590       res = sscanf(args.group + 1, "%30d", &x);
13591       if (res < 1) {
13592          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13593          return NULL;
13594       }
13595       param->span = x;
13596 
13597       /* Remove the ISDN span channel restriction specifier. */
13598       s = strchr(args.group, '-');
13599       if (!s) {
13600          /* Search all groups since we are ISDN span restricted. */
13601          return iflist;
13602       }
13603       args.group = s + 1;
13604       res = 0;
13605    }
13606    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13607       /* Retrieve the group number */
13608       s = args.group + 1;
13609       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13610       if (res < 1) {
13611          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13612          return NULL;
13613       }
13614       param->groupmatch = ((ast_group_t) 1 << x);
13615 
13616       if (toupper(args.group[0]) == 'G') {
13617          if (args.group[0] == 'G') {
13618             param->backwards = 1;
13619             p = ifend;
13620          } else
13621             p = iflist;
13622       } else {
13623          if (ARRAY_LEN(round_robin) <= x) {
13624             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13625                x, data);
13626             return NULL;
13627          }
13628          if (args.group[0] == 'R') {
13629             param->backwards = 1;
13630             p = round_robin[x] ? round_robin[x]->prev : ifend;
13631             if (!p)
13632                p = ifend;
13633          } else {
13634             p = round_robin[x] ? round_robin[x]->next : iflist;
13635             if (!p)
13636                p = iflist;
13637          }
13638          param->roundrobin = 1;
13639          param->rr_starting_point = x;
13640       }
13641    } else {
13642       s = args.group;
13643       if (!strcasecmp(s, "pseudo")) {
13644          /* Special case for pseudo */
13645          x = CHAN_PSEUDO;
13646          param->channelmatch = x;
13647       } else {
13648          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13649          if (res < 1) {
13650             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13651             return NULL;
13652          } else {
13653             param->channelmatch = x;
13654          }
13655       }
13656       if (subdir) {
13657          char path[PATH_MAX];
13658          struct stat stbuf;
13659 
13660          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13661                subdir, param->channelmatch);
13662          if (stat(path, &stbuf) < 0) {
13663             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13664                   path, strerror(errno));
13665             return NULL;
13666          }
13667          if (!S_ISCHR(stbuf.st_mode)) {
13668             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13669                   path);
13670             return NULL;
13671          }
13672          param->channelmatch = minor(stbuf.st_rdev);
13673       }
13674 
13675       p = iflist;
13676    }
13677 
13678    if (param->opt == 'r' && res < 3) {
13679       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13680       param->opt = '\0';
13681    }
13682 
13683    return p;
13684 }
13685 
13686 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13687 {
13688    int callwait = 0;
13689    struct dahdi_pvt *p;
13690    struct ast_channel *tmp = NULL;
13691    struct dahdi_pvt *exitpvt;
13692    int channelmatched = 0;
13693    int groupmatched = 0;
13694 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13695    int transcapdigital = 0;
13696 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13697    struct dahdi_starting_point start;
13698 
13699    ast_mutex_lock(&iflock);
13700    p = determine_starting_point(data, &start);
13701    if (!p) {
13702       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13703       ast_mutex_unlock(&iflock);
13704       return NULL;
13705    }
13706 
13707    /* Search for an unowned channel */
13708    exitpvt = p;
13709    while (p && !tmp) {
13710       if (start.roundrobin)
13711          round_robin[start.rr_starting_point] = p;
13712 
13713       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13714          && available(&p, channelmatched)) {
13715          ast_debug(1, "Using channel %d\n", p->channel);
13716 
13717          callwait = (p->owner != NULL);
13718 #ifdef HAVE_OPENR2
13719          if (p->mfcr2) {
13720             ast_mutex_lock(&p->lock);
13721             if (p->mfcr2call) {
13722                ast_mutex_unlock(&p->lock);
13723                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13724                goto next;
13725             }
13726             p->mfcr2call = 1;
13727             ast_mutex_unlock(&p->lock);
13728          }
13729 #endif
13730          if (p->channel == CHAN_PSEUDO) {
13731             p = duplicate_pseudo(p);
13732             if (!p) {
13733                break;
13734             }
13735          }
13736 
13737          p->distinctivering = 0;
13738          /* Make special notes */
13739          switch (start.opt) {
13740          case '\0':
13741             /* No option present. */
13742             break;
13743          case 'c':
13744             /* Confirm answer */
13745             p->confirmanswer = 1;
13746             break;
13747          case 'r':
13748             /* Distinctive ring */
13749             p->distinctivering = start.cadance;
13750             break;
13751          case 'd':
13752 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13753             /* If this is an ISDN call, make it digital */
13754             transcapdigital = AST_TRANS_CAP_DIGITAL;
13755 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13756             break;
13757          default:
13758             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13759             break;
13760          }
13761 
13762          p->outgoing = 1;
13763          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13764             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13765 #ifdef HAVE_PRI
13766          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13767             /*
13768              * We already have the B channel reserved for this call.  We
13769              * just need to make sure that dahdi_hangup() has completed
13770              * cleaning up before continuing.
13771              */
13772             ast_mutex_lock(&p->lock);
13773             ast_mutex_unlock(&p->lock);
13774 
13775             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13776                sizeof(p->dnid));
13777             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13778 #endif
13779 #if defined(HAVE_SS7)
13780          } else if (p->sig == SIG_SS7) {
13781             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13782 #endif   /* defined(HAVE_SS7) */
13783          } else {
13784             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13785          }
13786          if (!tmp) {
13787             p->outgoing = 0;
13788 #if defined(HAVE_PRI)
13789             switch (p->sig) {
13790             case SIG_PRI_LIB_HANDLE_CASES:
13791 #if defined(HAVE_PRI_CALL_WAITING)
13792                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13793                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13794                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13795                }
13796 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13797                /*
13798                 * This should be the last thing to clear when we are done with
13799                 * the channel.
13800                 */
13801                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13802                break;
13803             default:
13804                break;
13805             }
13806 #endif   /* defined(HAVE_PRI) */
13807          } else {
13808             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13809          }
13810          break;
13811       }
13812 #ifdef HAVE_OPENR2
13813 next:
13814 #endif
13815       if (start.backwards) {
13816          p = p->prev;
13817          if (!p)
13818             p = ifend;
13819       } else {
13820          p = p->next;
13821          if (!p)
13822             p = iflist;
13823       }
13824       /* stop when you roll to the one that we started from */
13825       if (p == exitpvt)
13826          break;
13827    }
13828    ast_mutex_unlock(&iflock);
13829    restart_monitor();
13830    if (cause && !tmp) {
13831       if (callwait || channelmatched) {
13832          *cause = AST_CAUSE_BUSY;
13833       } else if (groupmatched) {
13834          *cause = AST_CAUSE_CONGESTION;
13835       } else {
13836          /*
13837           * We did not match any channel requested.
13838           * Dialplan error requesting non-existant channel?
13839           */
13840       }
13841    }
13842 
13843    return tmp;
13844 }
13845 
13846 /*!
13847  * \internal
13848  * \brief Determine the device state for a given DAHDI device if we can.
13849  * \since 1.8
13850  *
13851  * \param data DAHDI device name after "DAHDI/".
13852  *
13853  * \retval device_state enum ast_device_state value.
13854  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13855  */
13856 static int dahdi_devicestate(void *data)
13857 {
13858 #if defined(HAVE_PRI)
13859    char *device;
13860    unsigned span;
13861    int res;
13862 
13863    device = data;
13864 
13865    if (*device != 'I') {
13866       /* The request is not for an ISDN span device. */
13867       return AST_DEVICE_UNKNOWN;
13868    }
13869    res = sscanf(device, "I%30u", &span);
13870    if (res != 1 || !span || NUM_SPANS < span) {
13871       /* Bad format for ISDN span device name. */
13872       return AST_DEVICE_UNKNOWN;
13873    }
13874    device = strchr(device, '/');
13875    if (!device) {
13876       /* Bad format for ISDN span device name. */
13877       return AST_DEVICE_UNKNOWN;
13878    }
13879 
13880    /*
13881     * Since there are currently no other span devstate's defined,
13882     * it must be congestion.
13883     */
13884 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13885    ++device;
13886    if (!strcmp(device, "congestion"))
13887 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13888    {
13889       return pris[span - 1].pri.congestion_devstate;
13890    }
13891 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13892    else if (!strcmp(device, "threshold")) {
13893       return pris[span - 1].pri.threshold_devstate;
13894    }
13895    return AST_DEVICE_UNKNOWN;
13896 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13897 #else
13898    return AST_DEVICE_UNKNOWN;
13899 #endif   /* defined(HAVE_PRI) */
13900 }
13901 
13902 /*!
13903  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13904  * \since 1.8
13905  *
13906  * \param inbound Incoming asterisk channel.
13907  * \param dest Same dial string passed to dahdi_request().
13908  * \param callback Callback into CC core to announce a busy channel available for CC.
13909  *
13910  * \details
13911  * This callback acts like a forked dial with all prongs of the fork busy.
13912  * Essentially, for each channel that could have taken the call, indicate that
13913  * it is busy.
13914  *
13915  * \retval 0 on success.
13916  * \retval -1 on error.
13917  */
13918 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13919 {
13920    struct dahdi_pvt *p;
13921    struct dahdi_pvt *exitpvt;
13922    struct dahdi_starting_point start;
13923    int groupmatched = 0;
13924    int channelmatched = 0;
13925 
13926    ast_mutex_lock(&iflock);
13927    p = determine_starting_point(dest, &start);
13928    if (!p) {
13929       ast_mutex_unlock(&iflock);
13930       return -1;
13931    }
13932    exitpvt = p;
13933    for (;;) {
13934       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13935          /* We found a potential match. call the callback */
13936          struct ast_str *device_name;
13937          char *dash;
13938          const char *monitor_type;
13939          char dialstring[AST_CHANNEL_NAME];
13940          char full_device_name[AST_CHANNEL_NAME];
13941 
13942          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13943          case AST_CC_MONITOR_NEVER:
13944             break;
13945          case AST_CC_MONITOR_NATIVE:
13946          case AST_CC_MONITOR_ALWAYS:
13947          case AST_CC_MONITOR_GENERIC:
13948 #if defined(HAVE_PRI)
13949             if (dahdi_sig_pri_lib_handles(p->sig)) {
13950                /*
13951                 * ISDN is in a trunk busy condition so we need to monitor
13952                 * the span congestion device state.
13953                 */
13954                snprintf(full_device_name, sizeof(full_device_name),
13955                   "DAHDI/I%d/congestion", p->pri->span);
13956             } else
13957 #endif   /* defined(HAVE_PRI) */
13958             {
13959 #if defined(HAVE_PRI)
13960                device_name = create_channel_name(p, 1, "");
13961 #else
13962                device_name = create_channel_name(p);
13963 #endif   /* defined(HAVE_PRI) */
13964                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13965                   device_name ? ast_str_buffer(device_name) : "");
13966                ast_free(device_name);
13967                /*
13968                 * The portion after the '-' in the channel name is either a random
13969                 * number, a sequence number, or a subchannel number. None are
13970                 * necessary so strip them off.
13971                 */
13972                dash = strrchr(full_device_name, '-');
13973                if (dash) {
13974                   *dash = '\0';
13975                }
13976             }
13977             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13978 
13979             /*
13980              * Analog can only do generic monitoring.
13981              * ISDN is in a trunk busy condition and any "device" is going
13982              * to be busy until a B channel becomes available.  The generic
13983              * monitor can do this task.
13984              */
13985             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13986             callback(inbound,
13987 #if defined(HAVE_PRI)
13988                p->pri ? p->pri->cc_params : p->cc_params,
13989 #else
13990                p->cc_params,
13991 #endif   /* defined(HAVE_PRI) */
13992                monitor_type, full_device_name, dialstring, NULL);
13993             break;
13994          }
13995       }
13996       p = start.backwards ? p->prev : p->next;
13997       if (!p) {
13998          p = start.backwards ? ifend : iflist;
13999       }
14000       if (p == exitpvt) {
14001          break;
14002       }
14003    }
14004    ast_mutex_unlock(&iflock);
14005    return 0;
14006 }
14007 
14008 #if defined(HAVE_SS7)
14009 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14010 {
14011    int i;
14012 
14013    if (ss7) {
14014       for (i = 0; i < NUM_SPANS; i++) {
14015          if (linksets[i].ss7.ss7 == ss7) {
14016             ast_verbose("[%d] %s", i + 1, s);
14017             return;
14018          }
14019       }
14020    }
14021    ast_verbose("%s", s);
14022 }
14023 #endif   /* defined(HAVE_SS7) */
14024 
14025 #if defined(HAVE_SS7)
14026 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14027 {
14028    int i;
14029 
14030    if (ss7) {
14031       for (i = 0; i < NUM_SPANS; i++) {
14032          if (linksets[i].ss7.ss7 == ss7) {
14033             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14034             return;
14035          }
14036       }
14037    }
14038    ast_log(LOG_ERROR, "%s", s);
14039 }
14040 #endif   /* defined(HAVE_SS7) */
14041 
14042 #if defined(HAVE_OPENR2)
14043 static void *mfcr2_monitor(void *data)
14044 {
14045    struct dahdi_mfcr2 *mfcr2 = data;
14046    /* we should be using pthread_key_create
14047       and allocate pollers dynamically.
14048       I think do_monitor() could be leaking, since it
14049       could be cancelled at any time and is not
14050       using thread keys, why?, */
14051    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14052    int res = 0;
14053    int i = 0;
14054    int oldstate = 0;
14055    int quit_loop = 0;
14056    int maxsleep = 20;
14057    int was_idle = 0;
14058    int pollsize = 0;
14059    /* now that we're ready to get calls, unblock our side and
14060       get current line state */
14061    for (i = 0; i < mfcr2->numchans; i++) {
14062       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14063       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14064    }
14065    while (1) {
14066       /* we trust here that the mfcr2 channel list will not ever change once
14067          the module is loaded */
14068       pollsize = 0;
14069       for (i = 0; i < mfcr2->numchans; i++) {
14070          pollers[i].revents = 0;
14071          pollers[i].events = 0;
14072          if (mfcr2->pvts[i]->owner) {
14073             continue;
14074          }
14075          if (!mfcr2->pvts[i]->r2chan) {
14076             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14077             quit_loop = 1;
14078             break;
14079          }
14080          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14081          pollers[i].events = POLLIN | POLLPRI;
14082          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14083          pollsize++;
14084       }
14085       if (quit_loop) {
14086          break;
14087       }
14088       if (pollsize == 0) {
14089          if (!was_idle) {
14090             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14091             was_idle = 1;
14092          }
14093          poll(NULL, 0, maxsleep);
14094          continue;
14095       }
14096       was_idle = 0;
14097       /* probably poll() is a valid cancel point, lets just be on the safe side
14098          by calling pthread_testcancel */
14099       pthread_testcancel();
14100       res = poll(pollers, mfcr2->numchans, maxsleep);
14101       pthread_testcancel();
14102       if ((res < 0) && (errno != EINTR)) {
14103          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14104          break;
14105       }
14106       /* do we want to allow to cancel while processing events? */
14107       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14108       for (i = 0; i < mfcr2->numchans; i++) {
14109          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14110             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14111          }
14112       }
14113       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14114    }
14115    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14116    return 0;
14117 }
14118 #endif /* HAVE_OPENR2 */
14119 
14120 #if defined(HAVE_PRI)
14121 static void dahdi_pri_message(struct pri *pri, char *s)
14122 {
14123    int x;
14124    int y;
14125    int dchan = -1;
14126    int span = -1;
14127    int dchancount = 0;
14128 
14129    if (pri) {
14130       for (x = 0; x < NUM_SPANS; x++) {
14131          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14132             if (pris[x].pri.dchans[y]) {
14133                dchancount++;
14134             }
14135 
14136             if (pris[x].pri.dchans[y] == pri) {
14137                dchan = y;
14138             }
14139          }
14140          if (dchan >= 0) {
14141             span = x;
14142             break;
14143          }
14144          dchancount = 0;
14145       }
14146       if (-1 < span) {
14147          if (1 < dchancount) {
14148             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14149          } else {
14150             ast_verbose("PRI Span: %d %s", span + 1, s);
14151          }
14152       } else {
14153          ast_verbose("PRI Span: ? %s", s);
14154       }
14155    } else {
14156       ast_verbose("PRI Span: ? %s", s);
14157    }
14158 
14159    ast_mutex_lock(&pridebugfdlock);
14160 
14161    if (pridebugfd >= 0) {
14162       if (write(pridebugfd, s, strlen(s)) < 0) {
14163          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14164       }
14165    }
14166 
14167    ast_mutex_unlock(&pridebugfdlock);
14168 }
14169 #endif   /* defined(HAVE_PRI) */
14170 
14171 #if defined(HAVE_PRI)
14172 static void dahdi_pri_error(struct pri *pri, char *s)
14173 {
14174    int x;
14175    int y;
14176    int dchan = -1;
14177    int span = -1;
14178    int dchancount = 0;
14179 
14180    if (pri) {
14181       for (x = 0; x < NUM_SPANS; x++) {
14182          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14183             if (pris[x].pri.dchans[y]) {
14184                dchancount++;
14185             }
14186 
14187             if (pris[x].pri.dchans[y] == pri) {
14188                dchan = y;
14189             }
14190          }
14191          if (dchan >= 0) {
14192             span = x;
14193             break;
14194          }
14195          dchancount = 0;
14196       }
14197       if (-1 < span) {
14198          if (1 < dchancount) {
14199             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14200          } else {
14201             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14202          }
14203       } else {
14204          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14205       }
14206    } else {
14207       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14208    }
14209 
14210    ast_mutex_lock(&pridebugfdlock);
14211 
14212    if (pridebugfd >= 0) {
14213       if (write(pridebugfd, s, strlen(s)) < 0) {
14214          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14215       }
14216    }
14217 
14218    ast_mutex_unlock(&pridebugfdlock);
14219 }
14220 #endif   /* defined(HAVE_PRI) */
14221 
14222 #if defined(HAVE_PRI)
14223 static int prepare_pri(struct dahdi_pri *pri)
14224 {
14225    int i, res, x;
14226    struct dahdi_params p;
14227    struct dahdi_bufferinfo bi;
14228    struct dahdi_spaninfo si;
14229 
14230    pri->pri.calls = &dahdi_pri_callbacks;
14231 
14232    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14233       if (!pri->dchannels[i])
14234          break;
14235       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14236       x = pri->dchannels[i];
14237       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14238          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14239          return -1;
14240       }
14241       memset(&p, 0, sizeof(p));
14242       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14243       if (res) {
14244          dahdi_close_pri_fd(pri, i);
14245          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14246          return -1;
14247       }
14248       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14249          dahdi_close_pri_fd(pri, i);
14250          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14251          return -1;
14252       }
14253       memset(&si, 0, sizeof(si));
14254       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14255       if (res) {
14256          dahdi_close_pri_fd(pri, i);
14257          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14258       }
14259       if (!si.alarms) {
14260          pri_event_noalarm(&pri->pri, i, 1);
14261       } else {
14262          pri_event_alarm(&pri->pri, i, 1);
14263       }
14264       memset(&bi, 0, sizeof(bi));
14265       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14266       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14267       bi.numbufs = 32;
14268       bi.bufsize = 1024;
14269       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14270          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14271          dahdi_close_pri_fd(pri, i);
14272          return -1;
14273       }
14274       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14275    }
14276    return 0;
14277 }
14278 #endif   /* defined(HAVE_PRI) */
14279 
14280 #if defined(HAVE_PRI)
14281 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14282 {
14283    int which, span;
14284    char *ret = NULL;
14285 
14286    if (pos != rpos)
14287       return ret;
14288 
14289    for (which = span = 0; span < NUM_SPANS; span++) {
14290       if (pris[span].pri.pri && ++which > state) {
14291          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14292             ret = NULL;
14293          }
14294          break;
14295       }
14296    }
14297    return ret;
14298 }
14299 #endif   /* defined(HAVE_PRI) */
14300 
14301 #if defined(HAVE_PRI)
14302 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14303 {
14304    return complete_span_helper(line,word,pos,state,3);
14305 }
14306 #endif   /* defined(HAVE_PRI) */
14307 
14308 #if defined(HAVE_PRI)
14309 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14310 {
14311    int myfd;
14312    switch (cmd) {
14313    case CLI_INIT:
14314       e->command = "pri set debug file";
14315       e->usage = "Usage: pri set debug file [output-file]\n"
14316          "       Sends PRI debug output to the specified output file\n";
14317       return NULL;
14318    case CLI_GENERATE:
14319       return NULL;
14320    }
14321    if (a->argc < 5)
14322       return CLI_SHOWUSAGE;
14323 
14324    if (ast_strlen_zero(a->argv[4]))
14325       return CLI_SHOWUSAGE;
14326 
14327    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14328    if (myfd < 0) {
14329       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14330       return CLI_SUCCESS;
14331    }
14332 
14333    ast_mutex_lock(&pridebugfdlock);
14334 
14335    if (pridebugfd >= 0)
14336       close(pridebugfd);
14337 
14338    pridebugfd = myfd;
14339    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14340    ast_mutex_unlock(&pridebugfdlock);
14341    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14342    return CLI_SUCCESS;
14343 }
14344 #endif   /* defined(HAVE_PRI) */
14345 
14346 #if defined(HAVE_PRI)
14347 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14348 {
14349    int span;
14350    int x;
14351    int level = 0;
14352    switch (cmd) {
14353    case CLI_INIT:
14354       e->command = "pri set debug {on|off|0|1|2} span";
14355       e->usage =
14356          "Usage: pri set debug {<level>|on|off} span <span>\n"
14357          "       Enables debugging on a given PRI span\n";
14358       return NULL;
14359    case CLI_GENERATE:
14360       return complete_span_4(a->line, a->word, a->pos, a->n);
14361    }
14362    if (a->argc < 6) {
14363       return CLI_SHOWUSAGE;
14364    }
14365 
14366    if (!strcasecmp(a->argv[3], "on")) {
14367       level = 1;
14368    } else if (!strcasecmp(a->argv[3], "off")) {
14369       level = 0;
14370    } else {
14371       level = atoi(a->argv[3]);
14372    }
14373    span = atoi(a->argv[5]);
14374    if ((span < 1) || (span > NUM_SPANS)) {
14375       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14376       return CLI_SUCCESS;
14377    }
14378    if (!pris[span-1].pri.pri) {
14379       ast_cli(a->fd, "No PRI running on span %d\n", span);
14380       return CLI_SUCCESS;
14381    }
14382 
14383    /* Set debug level in libpri */
14384    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14385       if (pris[span - 1].pri.dchans[x]) {
14386          switch (level) {
14387          case 0:
14388             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14389             break;
14390          case 1:
14391             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14392             break;
14393          default:
14394             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14395             break;
14396          }
14397       }
14398    }
14399    if (level == 0) {
14400       /* Close the debugging file if it's set */
14401       ast_mutex_lock(&pridebugfdlock);
14402       if (0 <= pridebugfd) {
14403          close(pridebugfd);
14404          pridebugfd = -1;
14405          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14406             pridebugfilename);
14407       }
14408       ast_mutex_unlock(&pridebugfdlock);
14409    }
14410    pris[span - 1].pri.debug = (level) ? 1 : 0;
14411    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14412    return CLI_SUCCESS;
14413 }
14414 #endif   /* defined(HAVE_PRI) */
14415 
14416 #if defined(HAVE_PRI)
14417 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14418 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14419 {
14420    unsigned *why;
14421    int channel;
14422    int trunkgroup;
14423    int x, y, fd = a->fd;
14424    int interfaceid = 0;
14425    char db_chan_name[20], db_answer[5];
14426    struct dahdi_pvt *tmp;
14427    struct dahdi_pri *pri;
14428 
14429    if (a->argc < 5 || a->argc > 6)
14430       return CLI_SHOWUSAGE;
14431    if (strchr(a->argv[4], ':')) {
14432       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14433          return CLI_SHOWUSAGE;
14434       if ((trunkgroup < 1) || (channel < 1))
14435          return CLI_SHOWUSAGE;
14436       pri = NULL;
14437       for (x=0;x<NUM_SPANS;x++) {
14438          if (pris[x].pri.trunkgroup == trunkgroup) {
14439             pri = pris + x;
14440             break;
14441          }
14442       }
14443       if (!pri) {
14444          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14445          return CLI_FAILURE;
14446       }
14447    } else
14448       channel = atoi(a->argv[4]);
14449 
14450    if (a->argc == 6)
14451       interfaceid = atoi(a->argv[5]);
14452 
14453    /* either servicing a D-Channel */
14454    for (x = 0; x < NUM_SPANS; x++) {
14455       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14456          if (pris[x].dchannels[y] == channel) {
14457             pri = pris + x;
14458             if (pri->pri.enable_service_message_support) {
14459                ast_mutex_lock(&pri->pri.lock);
14460                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14461                ast_mutex_unlock(&pri->pri.lock);
14462             } else {
14463                ast_cli(fd,
14464                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14465                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14466             }
14467             return CLI_SUCCESS;
14468          }
14469       }
14470    }
14471 
14472    /* or servicing a B-Channel */
14473    ast_mutex_lock(&iflock);
14474    for (tmp = iflist; tmp; tmp = tmp->next) {
14475       if (tmp->pri && tmp->channel == channel) {
14476          ast_mutex_unlock(&iflock);
14477          ast_mutex_lock(&tmp->pri->lock);
14478          if (!tmp->pri->enable_service_message_support) {
14479             ast_mutex_unlock(&tmp->pri->lock);
14480             ast_cli(fd,
14481                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14482                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14483             return CLI_SUCCESS;
14484          }
14485          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14486          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14487          switch(changestatus) {
14488          case 0: /* enable */
14489             /* Near end wants to be in service now. */
14490             ast_db_del(db_chan_name, SRVST_DBKEY);
14491             *why &= ~SRVST_NEAREND;
14492             if (*why) {
14493                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14494                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14495             } else {
14496                dahdi_pri_update_span_devstate(tmp->pri);
14497             }
14498             break;
14499          /* case 1:  -- loop */
14500          case 2: /* disable */
14501             /* Near end wants to be out-of-service now. */
14502             ast_db_del(db_chan_name, SRVST_DBKEY);
14503             *why |= SRVST_NEAREND;
14504             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14505             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14506             dahdi_pri_update_span_devstate(tmp->pri);
14507             break;
14508          /* case 3:  -- continuity */
14509          /* case 4:  -- shutdown */
14510          default:
14511             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14512             break;
14513          }
14514          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14515          ast_mutex_unlock(&tmp->pri->lock);
14516          return CLI_SUCCESS;
14517       }
14518    }
14519    ast_mutex_unlock(&iflock);
14520 
14521    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14522    return CLI_FAILURE;
14523 }
14524 
14525 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14526 {
14527    switch (cmd) {
14528    case CLI_INIT:
14529       e->command = "pri service enable channel";
14530       e->usage =
14531          "Usage: pri service enable channel <channel> [<interface id>]\n"
14532          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14533          "  to restore a channel to service, with optional interface id\n"
14534          "  as agreed upon with remote switch operator\n";
14535       return NULL;
14536    case CLI_GENERATE:
14537       return NULL;
14538    }
14539    return handle_pri_service_generic(e, cmd, a, 0);
14540 }
14541 
14542 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14543 {
14544    switch (cmd) {
14545    case CLI_INIT:
14546       e->command = "pri service disable channel";
14547       e->usage =
14548          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14549          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14550          "  to remove a channel from service, with optional interface id\n"
14551          "  as agreed upon with remote switch operator\n";
14552       return NULL;
14553    case CLI_GENERATE:
14554       return NULL;
14555    }
14556    return handle_pri_service_generic(e, cmd, a, 2);
14557 }
14558 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14559 #endif   /* defined(HAVE_PRI) */
14560 
14561 #if defined(HAVE_PRI)
14562 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14563 {
14564    int span;
14565 
14566    switch (cmd) {
14567    case CLI_INIT:
14568       e->command = "pri show channels";
14569       e->usage =
14570          "Usage: pri show channels\n"
14571          "       Displays PRI channel information such as the current mapping\n"
14572          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14573          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14574          "       are not associated with any B channel.\n";
14575       return NULL;
14576    case CLI_GENERATE:
14577       return NULL;
14578    }
14579 
14580    if (a->argc != 3)
14581       return CLI_SHOWUSAGE;
14582 
14583    sig_pri_cli_show_channels_header(a->fd);
14584    for (span = 0; span < NUM_SPANS; ++span) {
14585       if (pris[span].pri.pri) {
14586          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14587       }
14588    }
14589    return CLI_SUCCESS;
14590 }
14591 #endif   /* defined(HAVE_PRI) */
14592 
14593 #if defined(HAVE_PRI)
14594 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14595 {
14596    int span;
14597 
14598    switch (cmd) {
14599    case CLI_INIT:
14600       e->command = "pri show spans";
14601       e->usage =
14602          "Usage: pri show spans\n"
14603          "       Displays PRI span information\n";
14604       return NULL;
14605    case CLI_GENERATE:
14606       return NULL;
14607    }
14608 
14609    if (a->argc != 3)
14610       return CLI_SHOWUSAGE;
14611 
14612    for (span = 0; span < NUM_SPANS; span++) {
14613       if (pris[span].pri.pri) {
14614          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14615       }
14616    }
14617    return CLI_SUCCESS;
14618 }
14619 #endif   /* defined(HAVE_PRI) */
14620 
14621 #if defined(HAVE_PRI)
14622 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14623 {
14624    int span;
14625 
14626    switch (cmd) {
14627    case CLI_INIT:
14628       e->command = "pri show span";
14629       e->usage =
14630          "Usage: pri show span <span>\n"
14631          "       Displays PRI Information on a given PRI span\n";
14632       return NULL;
14633    case CLI_GENERATE:
14634       return complete_span_4(a->line, a->word, a->pos, a->n);
14635    }
14636 
14637    if (a->argc < 4)
14638       return CLI_SHOWUSAGE;
14639    span = atoi(a->argv[3]);
14640    if ((span < 1) || (span > NUM_SPANS)) {
14641       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14642       return CLI_SUCCESS;
14643    }
14644    if (!pris[span-1].pri.pri) {
14645       ast_cli(a->fd, "No PRI running on span %d\n", span);
14646       return CLI_SUCCESS;
14647    }
14648 
14649    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14650 
14651    return CLI_SUCCESS;
14652 }
14653 #endif   /* defined(HAVE_PRI) */
14654 
14655 #if defined(HAVE_PRI)
14656 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14657 {
14658    int x;
14659    int span;
14660    int count=0;
14661    int debug;
14662 
14663    switch (cmd) {
14664    case CLI_INIT:
14665       e->command = "pri show debug";
14666       e->usage =
14667          "Usage: pri show debug\n"
14668          "  Show the debug state of pri spans\n";
14669       return NULL;
14670    case CLI_GENERATE:
14671       return NULL;
14672    }
14673 
14674    for (span = 0; span < NUM_SPANS; span++) {
14675       if (pris[span].pri.pri) {
14676          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14677             if (pris[span].pri.dchans[x]) {
14678                debug = pri_get_debug(pris[span].pri.dchans[x]);
14679                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" );
14680                count++;
14681             }
14682          }
14683       }
14684 
14685    }
14686    ast_mutex_lock(&pridebugfdlock);
14687    if (pridebugfd >= 0)
14688       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14689    ast_mutex_unlock(&pridebugfdlock);
14690 
14691    if (!count)
14692       ast_cli(a->fd, "No PRI running\n");
14693    return CLI_SUCCESS;
14694 }
14695 #endif   /* defined(HAVE_PRI) */
14696 
14697 #if defined(HAVE_PRI)
14698 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14699 {
14700    switch (cmd) {
14701    case CLI_INIT:
14702       e->command = "pri show version";
14703       e->usage =
14704          "Usage: pri show version\n"
14705          "Show libpri version information\n";
14706       return NULL;
14707    case CLI_GENERATE:
14708       return NULL;
14709    }
14710 
14711    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14712 
14713    return CLI_SUCCESS;
14714 }
14715 #endif   /* defined(HAVE_PRI) */
14716 
14717 #if defined(HAVE_PRI)
14718 static struct ast_cli_entry dahdi_pri_cli[] = {
14719    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14720 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14721    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14722    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14723 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14724    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14725    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14726    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14727    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14728    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14729    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14730 };
14731 #endif   /* defined(HAVE_PRI) */
14732 
14733 #ifdef HAVE_OPENR2
14734 
14735 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14736 {
14737    switch (cmd) {
14738    case CLI_INIT:
14739       e->command = "mfcr2 show version";
14740       e->usage =
14741          "Usage: mfcr2 show version\n"
14742          "       Shows the version of the OpenR2 library being used.\n";
14743       return NULL;
14744    case CLI_GENERATE:
14745       return NULL;
14746    }
14747    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14748    return CLI_SUCCESS;
14749 }
14750 
14751 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14752 {
14753 #define FORMAT "%4s %40s\n"
14754    int i = 0;
14755    int numvariants = 0;
14756    const openr2_variant_entry_t *variants;
14757    switch (cmd) {
14758    case CLI_INIT:
14759       e->command = "mfcr2 show variants";
14760       e->usage =
14761          "Usage: mfcr2 show variants\n"
14762          "       Shows the list of MFC/R2 variants supported.\n";
14763       return NULL;
14764    case CLI_GENERATE:
14765       return NULL;
14766    }
14767    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14768       ast_cli(a->fd, "Failed to get list of variants.\n");
14769       return CLI_FAILURE;
14770    }
14771    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14772    for (i = 0; i < numvariants; i++) {
14773       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14774    }
14775    return CLI_SUCCESS;
14776 #undef FORMAT
14777 }
14778 
14779 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14780 {
14781 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14782    int filtertype = 0;
14783    int targetnum = 0;
14784    char channo[5];
14785    char anino[5];
14786    char dnisno[5];
14787    struct dahdi_pvt *p;
14788    openr2_context_t *r2context;
14789    openr2_variant_t r2variant;
14790    switch (cmd) {
14791    case CLI_INIT:
14792       e->command = "mfcr2 show channels [group|context]";
14793       e->usage =
14794          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14795          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14796       return NULL;
14797    case CLI_GENERATE:
14798       return NULL;
14799    }
14800    if (!((a->argc == 3) || (a->argc == 5))) {
14801       return CLI_SHOWUSAGE;
14802    }
14803    if (a->argc == 5) {
14804       if (!strcasecmp(a->argv[3], "group")) {
14805          targetnum = atoi(a->argv[4]);
14806          if ((targetnum < 0) || (targetnum > 63))
14807             return CLI_SHOWUSAGE;
14808          targetnum = 1 << targetnum;
14809          filtertype = 1;
14810       } else if (!strcasecmp(a->argv[3], "context")) {
14811          filtertype = 2;
14812       } else {
14813          return CLI_SHOWUSAGE;
14814       }
14815    }
14816    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14817    ast_mutex_lock(&iflock);
14818    for (p = iflist; p; p = p->next) {
14819       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14820          continue;
14821       }
14822       if (filtertype) {
14823          switch(filtertype) {
14824          case 1: /* mfcr2 show channels group <group> */
14825             if (p->group != targetnum) {
14826                continue;
14827             }
14828             break;
14829          case 2: /* mfcr2 show channels context <context> */
14830             if (strcasecmp(p->context, a->argv[4])) {
14831                continue;
14832             }
14833             break;
14834          default:
14835             ;
14836          }
14837       }
14838       r2context = openr2_chan_get_context(p->r2chan);
14839       r2variant = openr2_context_get_variant(r2context);
14840       snprintf(channo, sizeof(channo), "%d", p->channel);
14841       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14842       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14843       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14844             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14845             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14846             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14847    }
14848    ast_mutex_unlock(&iflock);
14849    return CLI_SUCCESS;
14850 #undef FORMAT
14851 }
14852 
14853 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14854 {
14855    struct dahdi_pvt *p = NULL;
14856    int channo = 0;
14857    char *toklevel = NULL;
14858    char *saveptr = NULL;
14859    char *logval = NULL;
14860    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14861    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14862    switch (cmd) {
14863    case CLI_INIT:
14864       e->command = "mfcr2 set debug";
14865       e->usage =
14866          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14867          "       Set a new logging level for the specified channel.\n"
14868          "       If no channel is specified the logging level will be applied to all channels.\n";
14869       return NULL;
14870    case CLI_GENERATE:
14871       return NULL;
14872    }
14873    if (a->argc < 4) {
14874       return CLI_SHOWUSAGE;
14875    }
14876    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14877    logval = ast_strdupa(a->argv[3]);
14878    toklevel = strtok_r(logval, ",", &saveptr);
14879    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14880       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14881       return CLI_FAILURE;
14882    } else if (OR2_LOG_NOTHING == tmplevel) {
14883       loglevel = tmplevel;
14884    } else {
14885       loglevel |= tmplevel;
14886       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14887          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14888             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14889             continue;
14890          }
14891          loglevel |= tmplevel;
14892       }
14893    }
14894    ast_mutex_lock(&iflock);
14895    for (p = iflist; p; p = p->next) {
14896       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14897          continue;
14898       }
14899       if ((channo != -1) && (p->channel != channo )) {
14900          continue;
14901       }
14902       openr2_chan_set_log_level(p->r2chan, loglevel);
14903       if (channo != -1) {
14904          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14905          break;
14906       }
14907    }
14908    if ((channo != -1) && !p) {
14909       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14910    }
14911    if (channo == -1) {
14912       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14913    }
14914    ast_mutex_unlock(&iflock);
14915    return CLI_SUCCESS;
14916 }
14917 
14918 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14919 {
14920    struct dahdi_pvt *p = NULL;
14921    int channo = 0;
14922    switch (cmd) {
14923    case CLI_INIT:
14924       e->command = "mfcr2 call files [on|off]";
14925       e->usage =
14926          "Usage: mfcr2 call files [on|off] <channel>\n"
14927          "       Enable call files creation on the specified channel.\n"
14928          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14929       return NULL;
14930    case CLI_GENERATE:
14931       return NULL;
14932    }
14933    if (a->argc < 4) {
14934       return CLI_SHOWUSAGE;
14935    }
14936    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14937    ast_mutex_lock(&iflock);
14938    for (p = iflist; p; p = p->next) {
14939       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14940          continue;
14941       }
14942       if ((channo != -1) && (p->channel != channo )) {
14943          continue;
14944       }
14945       if (ast_true(a->argv[3])) {
14946          openr2_chan_enable_call_files(p->r2chan);
14947       } else {
14948          openr2_chan_disable_call_files(p->r2chan);
14949       }
14950       if (channo != -1) {
14951          if (ast_true(a->argv[3])) {
14952             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14953          } else {
14954             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14955          }
14956          break;
14957       }
14958    }
14959    if ((channo != -1) && !p) {
14960       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14961    }
14962    if (channo == -1) {
14963       if (ast_true(a->argv[3])) {
14964          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14965       } else {
14966          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14967       }
14968    }
14969    ast_mutex_unlock(&iflock);
14970    return CLI_SUCCESS;
14971 }
14972 
14973 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14974 {
14975    struct dahdi_pvt *p = NULL;
14976    int channo = 0;
14977    switch (cmd) {
14978    case CLI_INIT:
14979       e->command = "mfcr2 set idle";
14980       e->usage =
14981          "Usage: mfcr2 set idle <channel>\n"
14982          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14983          "       Force the given channel into IDLE state.\n"
14984          "       If no channel is specified, all channels will be set to IDLE.\n";
14985       return NULL;
14986    case CLI_GENERATE:
14987       return NULL;
14988    }
14989    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14990    ast_mutex_lock(&iflock);
14991    for (p = iflist; p; p = p->next) {
14992       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14993          continue;
14994       }
14995       if ((channo != -1) && (p->channel != channo )) {
14996          continue;
14997       }
14998       openr2_chan_set_idle(p->r2chan);
14999       ast_mutex_lock(&p->lock);
15000       p->locallyblocked = 0;
15001       p->mfcr2call = 0;
15002       ast_mutex_unlock(&p->lock);
15003       if (channo != -1) {
15004          break;
15005       }
15006    }
15007    if ((channo != -1) && !p) {
15008       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15009    }
15010    ast_mutex_unlock(&iflock);
15011    return CLI_SUCCESS;
15012 }
15013 
15014 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15015 {
15016    struct dahdi_pvt *p = NULL;
15017    int channo = 0;
15018    switch (cmd) {
15019    case CLI_INIT:
15020       e->command = "mfcr2 set blocked";
15021       e->usage =
15022          "Usage: mfcr2 set blocked <channel>\n"
15023          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15024          "       Force the given channel into BLOCKED state.\n"
15025          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15026       return NULL;
15027    case CLI_GENERATE:
15028       return NULL;
15029    }
15030    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15031    ast_mutex_lock(&iflock);
15032    for (p = iflist; p; p = p->next) {
15033       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15034          continue;
15035       }
15036       if ((channo != -1) && (p->channel != channo )) {
15037          continue;
15038       }
15039       openr2_chan_set_blocked(p->r2chan);
15040       ast_mutex_lock(&p->lock);
15041       p->locallyblocked = 1;
15042       ast_mutex_unlock(&p->lock);
15043       if (channo != -1) {
15044          break;
15045       }
15046    }
15047    if ((channo != -1) && !p) {
15048       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15049    }
15050    ast_mutex_unlock(&iflock);
15051    return CLI_SUCCESS;
15052 }
15053 
15054 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15055    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15056    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15057    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15058    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15059    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15060    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15061    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15062 };
15063 
15064 #endif /* HAVE_OPENR2 */
15065 
15066 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15067 {
15068    int channel;
15069    int ret;
15070    switch (cmd) {
15071    case CLI_INIT:
15072       e->command = "dahdi destroy channel";
15073       e->usage =
15074          "Usage: dahdi destroy channel <chan num>\n"
15075          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15076       return NULL;
15077    case CLI_GENERATE:
15078       return NULL;
15079    }
15080    if (a->argc != 4)
15081       return CLI_SHOWUSAGE;
15082 
15083    channel = atoi(a->argv[3]);
15084    ret = dahdi_destroy_channel_bynum(channel);
15085    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15086 }
15087 
15088 static void dahdi_softhangup_all(void)
15089 {
15090    struct dahdi_pvt *p;
15091 retry:
15092    ast_mutex_lock(&iflock);
15093    for (p = iflist; p; p = p->next) {
15094       ast_mutex_lock(&p->lock);
15095       if (p->owner && !p->restartpending) {
15096          if (ast_channel_trylock(p->owner)) {
15097             if (option_debug > 2)
15098                ast_verbose("Avoiding deadlock\n");
15099             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15100             ast_mutex_unlock(&p->lock);
15101             ast_mutex_unlock(&iflock);
15102             goto retry;
15103          }
15104          if (option_debug > 2)
15105             ast_verbose("Softhanging up on %s\n", p->owner->name);
15106          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15107          p->restartpending = 1;
15108          num_restart_pending++;
15109          ast_channel_unlock(p->owner);
15110       }
15111       ast_mutex_unlock(&p->lock);
15112    }
15113    ast_mutex_unlock(&iflock);
15114 }
15115 
15116 static int setup_dahdi(int reload);
15117 static int dahdi_restart(void)
15118 {
15119 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15120    int i, j;
15121 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15122    int cancel_code;
15123    struct dahdi_pvt *p;
15124 
15125    ast_mutex_lock(&restart_lock);
15126    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15127    dahdi_softhangup_all();
15128    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15129 #ifdef HAVE_OPENR2
15130    dahdi_r2_destroy_links();
15131 #endif
15132 
15133 #if defined(HAVE_PRI)
15134    for (i = 0; i < NUM_SPANS; i++) {
15135       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15136          cancel_code = pthread_cancel(pris[i].pri.master);
15137          pthread_kill(pris[i].pri.master, SIGURG);
15138          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);
15139          pthread_join(pris[i].pri.master, NULL);
15140          ast_debug(4, "Joined thread of span %d\n", i);
15141       }
15142    }
15143 #endif
15144 
15145 #if defined(HAVE_SS7)
15146    for (i = 0; i < NUM_SPANS; i++) {
15147       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15148          cancel_code = pthread_cancel(linksets[i].ss7.master);
15149          pthread_kill(linksets[i].ss7.master, SIGURG);
15150          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);
15151          pthread_join(linksets[i].ss7.master, NULL);
15152          ast_debug(4, "Joined thread of span %d\n", i);
15153       }
15154    }
15155 #endif   /* defined(HAVE_SS7) */
15156 
15157    ast_mutex_lock(&monlock);
15158    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15159       cancel_code = pthread_cancel(monitor_thread);
15160       pthread_kill(monitor_thread, SIGURG);
15161       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15162       pthread_join(monitor_thread, NULL);
15163       ast_debug(4, "Joined monitor thread\n");
15164    }
15165    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15166 
15167    ast_mutex_lock(&ss_thread_lock);
15168    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15169       int x = DAHDI_FLASH;
15170       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15171 
15172       ast_mutex_lock(&iflock);
15173       for (p = iflist; p; p = p->next) {
15174          if (p->owner) {
15175             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15176             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15177          }
15178       }
15179       ast_mutex_unlock(&iflock);
15180       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15181    }
15182 
15183    /* ensure any created channels before monitor threads were stopped are hungup */
15184    dahdi_softhangup_all();
15185    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15186    destroy_all_channels();
15187    memset(round_robin, 0, sizeof(round_robin));
15188    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15189 
15190    ast_mutex_unlock(&monlock);
15191 
15192 #ifdef HAVE_PRI
15193    for (i = 0; i < NUM_SPANS; i++) {
15194       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15195          dahdi_close_pri_fd(&(pris[i]), j);
15196    }
15197 
15198    memset(pris, 0, sizeof(pris));
15199    for (i = 0; i < NUM_SPANS; i++) {
15200       sig_pri_init_pri(&pris[i].pri);
15201    }
15202    pri_set_error(dahdi_pri_error);
15203    pri_set_message(dahdi_pri_message);
15204 #endif
15205 #if defined(HAVE_SS7)
15206    for (i = 0; i < NUM_SPANS; i++) {
15207       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15208          dahdi_close_ss7_fd(&(linksets[i]), j);
15209    }
15210 
15211    memset(linksets, 0, sizeof(linksets));
15212    for (i = 0; i < NUM_SPANS; i++) {
15213       sig_ss7_init_linkset(&linksets[i].ss7);
15214    }
15215    ss7_set_error(dahdi_ss7_error);
15216    ss7_set_message(dahdi_ss7_message);
15217 #endif   /* defined(HAVE_SS7) */
15218 
15219    if (setup_dahdi(2) != 0) {
15220       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15221       ast_mutex_unlock(&ss_thread_lock);
15222       return 1;
15223    }
15224    ast_mutex_unlock(&ss_thread_lock);
15225    ast_mutex_unlock(&restart_lock);
15226    return 0;
15227 }
15228 
15229 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15230 {
15231    switch (cmd) {
15232    case CLI_INIT:
15233       e->command = "dahdi restart";
15234       e->usage =
15235          "Usage: dahdi restart\n"
15236          "  Restarts the DAHDI channels: destroys them all and then\n"
15237          "  re-reads them from chan_dahdi.conf.\n"
15238          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15239          "";
15240       return NULL;
15241    case CLI_GENERATE:
15242       return NULL;
15243    }
15244    if (a->argc != 2)
15245       return CLI_SHOWUSAGE;
15246 
15247    if (dahdi_restart() != 0)
15248       return CLI_FAILURE;
15249    return CLI_SUCCESS;
15250 }
15251 
15252 static int action_dahdirestart(struct mansession *s, const struct message *m)
15253 {
15254    if (dahdi_restart() != 0) {
15255       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15256       return 1;
15257    }
15258    astman_send_ack(s, m, "DAHDIRestart: Success");
15259    return 0;
15260 }
15261 
15262 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15263 {
15264 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15265 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15266    ast_group_t targetnum = 0;
15267    int filtertype = 0;
15268    struct dahdi_pvt *tmp = NULL;
15269    char tmps[20] = "";
15270    char statestr[20] = "";
15271    char blockstr[20] = "";
15272 
15273    switch (cmd) {
15274    case CLI_INIT:
15275       e->command = "dahdi show channels [group|context]";
15276       e->usage =
15277          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15278          "  Shows a list of available channels with optional filtering\n"
15279          "  <group> must be a number between 0 and 63\n";
15280       return NULL;
15281    case CLI_GENERATE:
15282       return NULL;
15283    }
15284 
15285    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15286 
15287    if (!((a->argc == 3) || (a->argc == 5)))
15288       return CLI_SHOWUSAGE;
15289 
15290    if (a->argc == 5) {
15291       if (!strcasecmp(a->argv[3], "group")) {
15292          targetnum = atoi(a->argv[4]);
15293          if (63 < targetnum) {
15294             return CLI_SHOWUSAGE;
15295          }
15296          targetnum = ((ast_group_t) 1) << targetnum;
15297          filtertype = 1;
15298       } else if (!strcasecmp(a->argv[3], "context")) {
15299          filtertype = 2;
15300       }
15301    }
15302 
15303    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15304    ast_mutex_lock(&iflock);
15305    for (tmp = iflist; tmp; tmp = tmp->next) {
15306       if (filtertype) {
15307          switch(filtertype) {
15308          case 1: /* dahdi show channels group <group> */
15309             if (!(tmp->group & targetnum)) {
15310                continue;
15311             }
15312             break;
15313          case 2: /* dahdi show channels context <context> */
15314             if (strcasecmp(tmp->context, a->argv[4])) {
15315                continue;
15316             }
15317             break;
15318          default:
15319             break;
15320          }
15321       }
15322       if (tmp->channel > 0) {
15323          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15324       } else
15325          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15326 
15327       if (tmp->locallyblocked)
15328          blockstr[0] = 'L';
15329       else
15330          blockstr[0] = ' ';
15331 
15332       if (tmp->remotelyblocked)
15333          blockstr[1] = 'R';
15334       else
15335          blockstr[1] = ' ';
15336 
15337       blockstr[2] = '\0';
15338 
15339       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15340 
15341       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15342    }
15343    ast_mutex_unlock(&iflock);
15344    return CLI_SUCCESS;
15345 #undef FORMAT
15346 #undef FORMAT2
15347 }
15348 
15349 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15350 {
15351    int channel;
15352    struct dahdi_pvt *tmp = NULL;
15353    struct dahdi_confinfo ci;
15354    struct dahdi_params ps;
15355    int x;
15356 
15357    switch (cmd) {
15358    case CLI_INIT:
15359       e->command = "dahdi show channel";
15360       e->usage =
15361          "Usage: dahdi show channel <chan num>\n"
15362          "  Detailed information about a given channel\n";
15363       return NULL;
15364    case CLI_GENERATE:
15365       return NULL;
15366    }
15367 
15368    if (a->argc != 4)
15369       return CLI_SHOWUSAGE;
15370 
15371    channel = atoi(a->argv[3]);
15372 
15373    ast_mutex_lock(&iflock);
15374    for (tmp = iflist; tmp; tmp = tmp->next) {
15375       if (tmp->channel == channel) {
15376          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15377          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15378          ast_cli(a->fd, "Span: %d\n", tmp->span);
15379          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15380          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15381          ast_cli(a->fd, "Context: %s\n", tmp->context);
15382          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15383          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15384 #if defined(HAVE_PRI)
15385 #if defined(HAVE_PRI_SUBADDR)
15386          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15387 #endif   /* defined(HAVE_PRI_SUBADDR) */
15388 #endif   /* defined(HAVE_PRI) */
15389          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15390          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15391          if (tmp->vars) {
15392             struct ast_variable *v;
15393             ast_cli(a->fd, "Variables:\n");
15394             for (v = tmp->vars ; v ; v = v->next)
15395                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15396          }
15397          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15398          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15399          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15400          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15401          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15402          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)" : "");
15403          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)" : "");
15404          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)" : "");
15405          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15406          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15407          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15408          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15409          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15410          if (tmp->busydetect) {
15411 #if defined(BUSYDETECT_TONEONLY)
15412             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15413 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15414             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15415 #endif
15416 #ifdef BUSYDETECT_DEBUG
15417             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15418 #endif
15419             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15420             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15421          }
15422          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15423          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15424          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15425          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15426          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15427          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15428          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15429          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15430          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15431          ast_cli(a->fd, "Echo Cancellation:\n");
15432 
15433          if (tmp->echocancel.head.tap_length) {
15434             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15435             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15436                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15437             }
15438             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15439          } else {
15440             ast_cli(a->fd, "\tnone\n");
15441          }
15442          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15443          if (tmp->master)
15444             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15445          for (x = 0; x < MAX_SLAVES; x++) {
15446             if (tmp->slaves[x])
15447                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15448          }
15449 #ifdef HAVE_OPENR2
15450          if (tmp->mfcr2) {
15451             char calldir[OR2_MAX_PATH];
15452             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15453             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15454             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15455             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15456             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15457             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15458             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15459             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15460             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15461             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15462             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15463 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15464             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15465 #endif
15466             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15467             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15468             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15469             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15470             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15471             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15472             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15473             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15474             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15475             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15476             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15477             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15478          }
15479 #endif
15480 #if defined(HAVE_SS7)
15481          if (tmp->ss7) {
15482             struct sig_ss7_chan *chan = tmp->sig_pvt;
15483 
15484             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15485          }
15486 #endif   /* defined(HAVE_SS7) */
15487 #ifdef HAVE_PRI
15488          if (tmp->pri) {
15489             struct sig_pri_chan *chan = tmp->sig_pvt;
15490 
15491             ast_cli(a->fd, "PRI Flags: ");
15492             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15493                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15494             }
15495             if (chan->call)
15496                ast_cli(a->fd, "Call ");
15497             if (chan->allocated) {
15498                ast_cli(a->fd, "Allocated ");
15499             }
15500             ast_cli(a->fd, "\n");
15501             if (tmp->logicalspan)
15502                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15503             else
15504                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15505          }
15506 #endif
15507          memset(&ci, 0, sizeof(ci));
15508          ps.channo = tmp->channel;
15509          if (tmp->subs[SUB_REAL].dfd > -1) {
15510             memset(&ci, 0, sizeof(ci));
15511             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15512                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15513             }
15514             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15515                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15516             }
15517             memset(&ps, 0, sizeof(ps));
15518             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15519                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15520             } else {
15521                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15522             }
15523          }
15524          ast_mutex_unlock(&iflock);
15525          return CLI_SUCCESS;
15526       }
15527    }
15528    ast_mutex_unlock(&iflock);
15529 
15530    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15531    return CLI_FAILURE;
15532 }
15533 
15534 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15535 {
15536    int i, j;
15537    switch (cmd) {
15538    case CLI_INIT:
15539       e->command = "dahdi show cadences";
15540       e->usage =
15541          "Usage: dahdi show cadences\n"
15542          "       Shows all cadences currently defined\n";
15543       return NULL;
15544    case CLI_GENERATE:
15545       return NULL;
15546    }
15547    for (i = 0; i < num_cadence; i++) {
15548       char output[1024];
15549       char tmp[16], tmp2[64];
15550       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15551       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15552 
15553       for (j = 0; j < 16; j++) {
15554          if (cadences[i].ringcadence[j] == 0)
15555             break;
15556          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15557          if (cidrings[i] * 2 - 1 == j)
15558             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15559          else
15560             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15561          if (j != 0)
15562             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15563          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15564       }
15565       ast_cli(a->fd,"%s\n",output);
15566    }
15567    return CLI_SUCCESS;
15568 }
15569 
15570 /* Based on irqmiss.c */
15571 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15572 {
15573    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15574    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15575    int span;
15576    int res;
15577    char alarmstr[50];
15578 
15579    int ctl;
15580    struct dahdi_spaninfo s;
15581 
15582    switch (cmd) {
15583    case CLI_INIT:
15584       e->command = "dahdi show status";
15585       e->usage =
15586          "Usage: dahdi show status\n"
15587          "       Shows a list of DAHDI cards with status\n";
15588       return NULL;
15589    case CLI_GENERATE:
15590       return NULL;
15591    }
15592    ctl = open("/dev/dahdi/ctl", O_RDWR);
15593    if (ctl < 0) {
15594       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15595       return CLI_FAILURE;
15596    }
15597    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15598 
15599    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15600       s.spanno = span;
15601       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15602       if (res) {
15603          continue;
15604       }
15605       alarmstr[0] = '\0';
15606       if (s.alarms > 0) {
15607          if (s.alarms & DAHDI_ALARM_BLUE)
15608             strcat(alarmstr, "BLU/");
15609          if (s.alarms & DAHDI_ALARM_YELLOW)
15610             strcat(alarmstr, "YEL/");
15611          if (s.alarms & DAHDI_ALARM_RED)
15612             strcat(alarmstr, "RED/");
15613          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15614             strcat(alarmstr, "LB/");
15615          if (s.alarms & DAHDI_ALARM_RECOVER)
15616             strcat(alarmstr, "REC/");
15617          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15618             strcat(alarmstr, "NOP/");
15619          if (!strlen(alarmstr))
15620             strcat(alarmstr, "UUU/");
15621          if (strlen(alarmstr)) {
15622             /* Strip trailing / */
15623             alarmstr[strlen(alarmstr) - 1] = '\0';
15624          }
15625       } else {
15626          if (s.numchans)
15627             strcpy(alarmstr, "OK");
15628          else
15629             strcpy(alarmstr, "UNCONFIGURED");
15630       }
15631 
15632       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15633          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15634          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15635          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15636          "CAS",
15637          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15638          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15639          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15640          "Unk",
15641          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15642             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15643             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15644          lbostr[s.lbo]
15645          );
15646    }
15647    close(ctl);
15648 
15649    return CLI_SUCCESS;
15650 #undef FORMAT
15651 #undef FORMAT2
15652 }
15653 
15654 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15655 {
15656    int pseudo_fd = -1;
15657    struct dahdi_versioninfo vi;
15658 
15659    switch (cmd) {
15660    case CLI_INIT:
15661       e->command = "dahdi show version";
15662       e->usage =
15663          "Usage: dahdi show version\n"
15664          "       Shows the DAHDI version in use\n";
15665       return NULL;
15666    case CLI_GENERATE:
15667       return NULL;
15668    }
15669    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15670       ast_cli(a->fd, "Failed to open control file to get version.\n");
15671       return CLI_SUCCESS;
15672    }
15673 
15674    strcpy(vi.version, "Unknown");
15675    strcpy(vi.echo_canceller, "Unknown");
15676 
15677    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15678       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15679    else
15680       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15681 
15682    close(pseudo_fd);
15683 
15684    return CLI_SUCCESS;
15685 }
15686 
15687 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15688 {
15689    int channel;
15690    int gain;
15691    int tx;
15692    struct dahdi_hwgain hwgain;
15693    struct dahdi_pvt *tmp = NULL;
15694 
15695    switch (cmd) {
15696    case CLI_INIT:
15697       e->command = "dahdi set hwgain {rx|tx}";
15698       e->usage =
15699          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15700          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15701          "   immediately whether the channel is in use or not.\n"
15702          "\n"
15703          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15704          "   <chan num> is the channel number relative to the device\n"
15705          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15706          "\n"
15707          "   Please note:\n"
15708          "   * This is currently the only way to set hwgain by the channel driver.\n"
15709          "   * hwgain is only supportable by hardware with analog ports because\n"
15710          "     hwgain works on the analog side of an analog-digital conversion.\n";
15711       return NULL;
15712    case CLI_GENERATE:
15713       return NULL;
15714    }
15715 
15716    if (a->argc != 6)
15717       return CLI_SHOWUSAGE;
15718 
15719    if (!strcasecmp("rx", a->argv[3]))
15720       tx = 0; /* rx */
15721    else if (!strcasecmp("tx", a->argv[3]))
15722       tx = 1; /* tx */
15723    else
15724       return CLI_SHOWUSAGE;
15725 
15726    channel = atoi(a->argv[4]);
15727    gain = atof(a->argv[5])*10.0;
15728 
15729    ast_mutex_lock(&iflock);
15730 
15731    for (tmp = iflist; tmp; tmp = tmp->next) {
15732 
15733       if (tmp->channel != channel)
15734          continue;
15735 
15736       if (tmp->subs[SUB_REAL].dfd == -1)
15737          break;
15738 
15739       hwgain.newgain = gain;
15740       hwgain.tx = tx;
15741       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15742          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15743          ast_mutex_unlock(&iflock);
15744          return CLI_FAILURE;
15745       }
15746       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15747          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15748       break;
15749    }
15750 
15751    ast_mutex_unlock(&iflock);
15752 
15753    if (tmp)
15754       return CLI_SUCCESS;
15755 
15756    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15757    return CLI_FAILURE;
15758 
15759 }
15760 
15761 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15762 {
15763    int channel;
15764    float gain;
15765    int tx;
15766    int res;
15767    struct dahdi_pvt *tmp = NULL;
15768 
15769    switch (cmd) {
15770    case CLI_INIT:
15771       e->command = "dahdi set swgain {rx|tx}";
15772       e->usage =
15773          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15774          "   Sets the software gain on a given channel and overrides the\n"
15775          "   value provided at module loadtime.  Changes take effect\n"
15776          "   immediately whether the channel is in use or not.\n"
15777          "\n"
15778          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15779          "   <chan num> is the channel number relative to the device\n"
15780          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15781       return NULL;
15782    case CLI_GENERATE:
15783       return NULL;
15784    }
15785 
15786    if (a->argc != 6)
15787       return CLI_SHOWUSAGE;
15788 
15789    if (!strcasecmp("rx", a->argv[3]))
15790       tx = 0; /* rx */
15791    else if (!strcasecmp("tx", a->argv[3]))
15792       tx = 1; /* tx */
15793    else
15794       return CLI_SHOWUSAGE;
15795 
15796    channel = atoi(a->argv[4]);
15797    gain = atof(a->argv[5]);
15798 
15799    ast_mutex_lock(&iflock);
15800    for (tmp = iflist; tmp; tmp = tmp->next) {
15801 
15802       if (tmp->channel != channel)
15803          continue;
15804 
15805       if (tmp->subs[SUB_REAL].dfd == -1)
15806          break;
15807 
15808       if (tx)
15809          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15810       else
15811          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15812 
15813       if (res) {
15814          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15815          ast_mutex_unlock(&iflock);
15816          return CLI_FAILURE;
15817       }
15818 
15819       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15820          tx ? "tx" : "rx", gain, channel);
15821 
15822       if (tx) {
15823          tmp->txgain = gain;
15824       } else {
15825          tmp->rxgain = gain;
15826       }
15827       break;
15828    }
15829    ast_mutex_unlock(&iflock);
15830 
15831    if (tmp)
15832       return CLI_SUCCESS;
15833 
15834    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15835    return CLI_FAILURE;
15836 
15837 }
15838 
15839 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15840 {
15841    int channel;
15842    int on;
15843    struct dahdi_pvt *dahdi_chan = NULL;
15844 
15845    switch (cmd) {
15846    case CLI_INIT:
15847       e->command = "dahdi set dnd";
15848       e->usage =
15849          "Usage: dahdi set dnd <chan#> <on|off>\n"
15850          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15851          "  Changes take effect immediately.\n"
15852          "  <chan num> is the channel number\n"
15853          "  <on|off> Enable or disable DND mode?\n"
15854          ;
15855       return NULL;
15856    case CLI_GENERATE:
15857       return NULL;
15858    }
15859 
15860    if (a->argc != 5)
15861       return CLI_SHOWUSAGE;
15862 
15863    if ((channel = atoi(a->argv[3])) <= 0) {
15864       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15865       return CLI_SHOWUSAGE;
15866    }
15867 
15868    if (ast_true(a->argv[4]))
15869       on = 1;
15870    else if (ast_false(a->argv[4]))
15871       on = 0;
15872    else {
15873       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15874       return CLI_SHOWUSAGE;
15875    }
15876 
15877    ast_mutex_lock(&iflock);
15878    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15879       if (dahdi_chan->channel != channel)
15880          continue;
15881 
15882       /* Found the channel. Actually set it */
15883       dahdi_dnd(dahdi_chan, on);
15884       break;
15885    }
15886    ast_mutex_unlock(&iflock);
15887 
15888    if (!dahdi_chan) {
15889       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15890       return CLI_FAILURE;
15891    }
15892 
15893    return CLI_SUCCESS;
15894 }
15895 
15896 static struct ast_cli_entry dahdi_cli[] = {
15897    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15898    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15899    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15900    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15901    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15902    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15903    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15904    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15905    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15906    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15907 };
15908 
15909 #define TRANSFER  0
15910 #define HANGUP    1
15911 
15912 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15913 {
15914    if (p) {
15915       switch (mode) {
15916       case TRANSFER:
15917          p->fake_event = DAHDI_EVENT_WINKFLASH;
15918          break;
15919       case HANGUP:
15920          p->fake_event = DAHDI_EVENT_ONHOOK;
15921          break;
15922       default:
15923          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15924       }
15925    }
15926    return 0;
15927 }
15928 static struct dahdi_pvt *find_channel(int channel)
15929 {
15930    struct dahdi_pvt *p;
15931 
15932    ast_mutex_lock(&iflock);
15933    for (p = iflist; p; p = p->next) {
15934       if (p->channel == channel) {
15935          break;
15936       }
15937    }
15938    ast_mutex_unlock(&iflock);
15939    return p;
15940 }
15941 
15942 /*!
15943  * \internal
15944  * \brief Get private struct using given numeric channel string.
15945  *
15946  * \param channel Numeric channel number string get private struct.
15947  *
15948  * \retval pvt on success.
15949  * \retval NULL on error.
15950  */
15951 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15952 {
15953    int chan_num;
15954 
15955    if (sscanf(channel, "%30d", &chan_num) != 1) {
15956       /* Not numeric string. */
15957       return NULL;
15958    }
15959 
15960    return find_channel(chan_num);
15961 }
15962 
15963 static int action_dahdidndon(struct mansession *s, const struct message *m)
15964 {
15965    struct dahdi_pvt *p;
15966    const char *channel = astman_get_header(m, "DAHDIChannel");
15967 
15968    if (ast_strlen_zero(channel)) {
15969       astman_send_error(s, m, "No channel specified");
15970       return 0;
15971    }
15972    p = find_channel_from_str(channel);
15973    if (!p) {
15974       astman_send_error(s, m, "No such channel");
15975       return 0;
15976    }
15977    dahdi_dnd(p, 1);
15978    astman_send_ack(s, m, "DND Enabled");
15979    return 0;
15980 }
15981 
15982 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15983 {
15984    struct dahdi_pvt *p;
15985    const char *channel = astman_get_header(m, "DAHDIChannel");
15986 
15987    if (ast_strlen_zero(channel)) {
15988       astman_send_error(s, m, "No channel specified");
15989       return 0;
15990    }
15991    p = find_channel_from_str(channel);
15992    if (!p) {
15993       astman_send_error(s, m, "No such channel");
15994       return 0;
15995    }
15996    dahdi_dnd(p, 0);
15997    astman_send_ack(s, m, "DND Disabled");
15998    return 0;
15999 }
16000 
16001 static int action_transfer(struct mansession *s, const struct message *m)
16002 {
16003    struct dahdi_pvt *p;
16004    const char *channel = astman_get_header(m, "DAHDIChannel");
16005 
16006    if (ast_strlen_zero(channel)) {
16007       astman_send_error(s, m, "No channel specified");
16008       return 0;
16009    }
16010    p = find_channel_from_str(channel);
16011    if (!p) {
16012       astman_send_error(s, m, "No such channel");
16013       return 0;
16014    }
16015    if (!analog_lib_handles(p->sig, 0, 0)) {
16016       astman_send_error(s, m, "Channel signaling is not analog");
16017       return 0;
16018    }
16019    dahdi_fake_event(p,TRANSFER);
16020    astman_send_ack(s, m, "DAHDITransfer");
16021    return 0;
16022 }
16023 
16024 static int action_transferhangup(struct mansession *s, const struct message *m)
16025 {
16026    struct dahdi_pvt *p;
16027    const char *channel = astman_get_header(m, "DAHDIChannel");
16028 
16029    if (ast_strlen_zero(channel)) {
16030       astman_send_error(s, m, "No channel specified");
16031       return 0;
16032    }
16033    p = find_channel_from_str(channel);
16034    if (!p) {
16035       astman_send_error(s, m, "No such channel");
16036       return 0;
16037    }
16038    if (!analog_lib_handles(p->sig, 0, 0)) {
16039       astman_send_error(s, m, "Channel signaling is not analog");
16040       return 0;
16041    }
16042    dahdi_fake_event(p,HANGUP);
16043    astman_send_ack(s, m, "DAHDIHangup");
16044    return 0;
16045 }
16046 
16047 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16048 {
16049    struct dahdi_pvt *p;
16050    const char *channel = astman_get_header(m, "DAHDIChannel");
16051    const char *number = astman_get_header(m, "Number");
16052    int i;
16053 
16054    if (ast_strlen_zero(channel)) {
16055       astman_send_error(s, m, "No channel specified");
16056       return 0;
16057    }
16058    if (ast_strlen_zero(number)) {
16059       astman_send_error(s, m, "No number specified");
16060       return 0;
16061    }
16062    p = find_channel_from_str(channel);
16063    if (!p) {
16064       astman_send_error(s, m, "No such channel");
16065       return 0;
16066    }
16067    if (!p->owner) {
16068       astman_send_error(s, m, "Channel does not have it's owner");
16069       return 0;
16070    }
16071    for (i = 0; i < strlen(number); i++) {
16072       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16073       dahdi_queue_frame(p, &f);
16074    }
16075    astman_send_ack(s, m, "DAHDIDialOffhook");
16076    return 0;
16077 }
16078 
16079 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16080 {
16081    struct dahdi_pvt *tmp = NULL;
16082    const char *id = astman_get_header(m, "ActionID");
16083    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16084    char idText[256] = "";
16085    int channels = 0;
16086    int dahdichanquery;
16087 
16088    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16089       /* Not numeric string. */
16090       dahdichanquery = -1;
16091    }
16092 
16093    astman_send_ack(s, m, "DAHDI channel status will follow");
16094    if (!ast_strlen_zero(id))
16095       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16096 
16097    ast_mutex_lock(&iflock);
16098 
16099    for (tmp = iflist; tmp; tmp = tmp->next) {
16100       if (tmp->channel > 0) {
16101          int alm;
16102 
16103          /* If a specific channel is queried for, only deliver status for that channel */
16104          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16105             continue;
16106 
16107          alm = get_alarms(tmp);
16108          channels++;
16109          if (tmp->owner) {
16110             /* Add data if we have a current call */
16111             astman_append(s,
16112                "Event: DAHDIShowChannels\r\n"
16113                "DAHDIChannel: %d\r\n"
16114                "Channel: %s\r\n"
16115                "Uniqueid: %s\r\n"
16116                "AccountCode: %s\r\n"
16117                "Signalling: %s\r\n"
16118                "SignallingCode: %d\r\n"
16119                "Context: %s\r\n"
16120                "DND: %s\r\n"
16121                "Alarm: %s\r\n"
16122                "%s"
16123                "\r\n",
16124                tmp->channel,
16125                tmp->owner->name,
16126                tmp->owner->uniqueid,
16127                tmp->owner->accountcode,
16128                sig2str(tmp->sig),
16129                tmp->sig,
16130                tmp->context,
16131                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16132                alarm2str(alm), idText);
16133          } else {
16134             astman_append(s,
16135                "Event: DAHDIShowChannels\r\n"
16136                "DAHDIChannel: %d\r\n"
16137                "Signalling: %s\r\n"
16138                "SignallingCode: %d\r\n"
16139                "Context: %s\r\n"
16140                "DND: %s\r\n"
16141                "Alarm: %s\r\n"
16142                "%s"
16143                "\r\n",
16144                tmp->channel, sig2str(tmp->sig), tmp->sig,
16145                tmp->context,
16146                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16147                alarm2str(alm), idText);
16148          }
16149       }
16150    }
16151 
16152    ast_mutex_unlock(&iflock);
16153 
16154    astman_append(s,
16155       "Event: DAHDIShowChannelsComplete\r\n"
16156       "%s"
16157       "Items: %d\r\n"
16158       "\r\n",
16159       idText,
16160       channels);
16161    return 0;
16162 }
16163 
16164 #if defined(HAVE_SS7)
16165 static int linkset_addsigchan(int sigchan)
16166 {
16167    struct dahdi_ss7 *link;
16168    int res;
16169    int curfd;
16170    struct dahdi_params params;
16171    struct dahdi_bufferinfo bi;
16172    struct dahdi_spaninfo si;
16173 
16174    if (sigchan < 0) {
16175       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16176       return -1;
16177    }
16178    if (cur_ss7type < 0) {
16179       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16180       return -1;
16181    }
16182    if (cur_pointcode < 0) {
16183       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16184       return -1;
16185    }
16186    if (cur_adjpointcode < 0) {
16187       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16188       return -1;
16189    }
16190    if (cur_defaultdpc < 0) {
16191       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16192       return -1;
16193    }
16194    if (cur_networkindicator < 0) {
16195       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16196       return -1;
16197    }
16198    link = ss7_resolve_linkset(cur_linkset);
16199    if (!link) {
16200       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16201       return -1;
16202    }
16203    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16204       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16205       return -1;
16206    }
16207 
16208    curfd = link->ss7.numsigchans;
16209 
16210    /* Open signaling channel */
16211    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16212    if (link->ss7.fds[curfd] < 0) {
16213       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16214          strerror(errno));
16215       return -1;
16216    }
16217    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16218       dahdi_close_ss7_fd(link, curfd);
16219       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16220          strerror(errno));
16221       return -1;
16222    }
16223 
16224    /* Get signaling channel parameters */
16225    memset(&params, 0, sizeof(params));
16226    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16227    if (res) {
16228       dahdi_close_ss7_fd(link, curfd);
16229       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16230          strerror(errno));
16231       return -1;
16232    }
16233    if (params.sigtype != DAHDI_SIG_HDLCFCS
16234       && params.sigtype != DAHDI_SIG_HARDHDLC
16235       && params.sigtype != DAHDI_SIG_MTP2) {
16236       dahdi_close_ss7_fd(link, curfd);
16237       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16238       return -1;
16239    }
16240 
16241    /* Set signaling channel buffer policy. */
16242    memset(&bi, 0, sizeof(bi));
16243    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16244    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16245    bi.numbufs = 32;
16246    bi.bufsize = 512;
16247    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16248       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16249          sigchan, strerror(errno));
16250       dahdi_close_ss7_fd(link, curfd);
16251       return -1;
16252    }
16253 
16254    /* Get current signaling channel alarm status. */
16255    memset(&si, 0, sizeof(si));
16256    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16257    if (res) {
16258       dahdi_close_ss7_fd(link, curfd);
16259       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16260          strerror(errno));
16261    }
16262 
16263    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16264       (params.sigtype == DAHDI_SIG_MTP2)
16265          ? SS7_TRANSPORT_DAHDIMTP2
16266          : SS7_TRANSPORT_DAHDIDCHAN,
16267       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16268    if (res) {
16269       dahdi_close_ss7_fd(link, curfd);
16270       return -1;
16271    }
16272 
16273    ++link->ss7.numsigchans;
16274 
16275    return 0;
16276 }
16277 #endif   /* defined(HAVE_SS7) */
16278 
16279 #if defined(HAVE_SS7)
16280 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16281 {
16282    int span;
16283    switch (cmd) {
16284    case CLI_INIT:
16285       e->command = "ss7 set debug {on|off} linkset";
16286       e->usage =
16287          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16288          "       Enables debugging on a given SS7 linkset\n";
16289       return NULL;
16290    case CLI_GENERATE:
16291       return NULL;
16292    }
16293    if (a->argc < 6)
16294       return CLI_SHOWUSAGE;
16295    span = atoi(a->argv[5]);
16296    if ((span < 1) || (span > NUM_SPANS)) {
16297       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16298       return CLI_SUCCESS;
16299    }
16300    if (!linksets[span-1].ss7.ss7) {
16301       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16302    } else {
16303       if (!strcasecmp(a->argv[3], "on")) {
16304          linksets[span - 1].ss7.debug = 1;
16305          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16306          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16307       } else {
16308          linksets[span - 1].ss7.debug = 0;
16309          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16310          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16311       }
16312    }
16313 
16314    return CLI_SUCCESS;
16315 }
16316 #endif   /* defined(HAVE_SS7) */
16317 
16318 #if defined(HAVE_SS7)
16319 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16320 {
16321    int linkset, cic;
16322    int blocked = -1, i;
16323    switch (cmd) {
16324    case CLI_INIT:
16325       e->command = "ss7 block cic";
16326       e->usage =
16327          "Usage: ss7 block cic <linkset> <CIC>\n"
16328          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16329       return NULL;
16330    case CLI_GENERATE:
16331       return NULL;
16332    }
16333    if (a->argc == 5)
16334       linkset = atoi(a->argv[3]);
16335    else
16336       return CLI_SHOWUSAGE;
16337 
16338    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16339       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16340       return CLI_SUCCESS;
16341    }
16342 
16343    if (!linksets[linkset-1].ss7.ss7) {
16344       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16345       return CLI_SUCCESS;
16346    }
16347 
16348    cic = atoi(a->argv[4]);
16349 
16350    if (cic < 1) {
16351       ast_cli(a->fd, "Invalid CIC specified!\n");
16352       return CLI_SUCCESS;
16353    }
16354 
16355    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16356       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16357          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16358          if (!blocked) {
16359             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16360             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16361             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16362          }
16363       }
16364    }
16365 
16366    if (blocked < 0) {
16367       ast_cli(a->fd, "Invalid CIC specified!\n");
16368       return CLI_SUCCESS;
16369    }
16370 
16371    if (!blocked)
16372       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16373    else
16374       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16375 
16376    /* Break poll on the linkset so it sends our messages */
16377    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16378 
16379    return CLI_SUCCESS;
16380 }
16381 #endif   /* defined(HAVE_SS7) */
16382 
16383 #if defined(HAVE_SS7)
16384 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16385 {
16386    int linkset;
16387    int i;
16388    switch (cmd) {
16389    case CLI_INIT:
16390       e->command = "ss7 block linkset";
16391       e->usage =
16392          "Usage: ss7 block linkset <linkset number>\n"
16393          "       Sends a remote blocking request for all CICs on the given linkset\n";
16394       return NULL;
16395    case CLI_GENERATE:
16396       return NULL;
16397    }
16398    if (a->argc == 4)
16399       linkset = atoi(a->argv[3]);
16400    else
16401       return CLI_SHOWUSAGE;
16402 
16403    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16404       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16405       return CLI_SUCCESS;
16406    }
16407 
16408    if (!linksets[linkset-1].ss7.ss7) {
16409       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16410       return CLI_SUCCESS;
16411    }
16412 
16413    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16414       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16415       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16416       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16417       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16418    }
16419 
16420    /* Break poll on the linkset so it sends our messages */
16421    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16422 
16423    return CLI_SUCCESS;
16424 }
16425 #endif   /* defined(HAVE_SS7) */
16426 
16427 #if defined(HAVE_SS7)
16428 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16429 {
16430    int linkset, cic;
16431    int i, blocked = -1;
16432    switch (cmd) {
16433    case CLI_INIT:
16434       e->command = "ss7 unblock cic";
16435       e->usage =
16436          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16437          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16438       return NULL;
16439    case CLI_GENERATE:
16440       return NULL;
16441    }
16442 
16443    if (a->argc == 5)
16444       linkset = atoi(a->argv[3]);
16445    else
16446       return CLI_SHOWUSAGE;
16447 
16448    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16449       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16450       return CLI_SUCCESS;
16451    }
16452 
16453    if (!linksets[linkset-1].ss7.ss7) {
16454       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16455       return CLI_SUCCESS;
16456    }
16457 
16458    cic = atoi(a->argv[4]);
16459 
16460    if (cic < 1) {
16461       ast_cli(a->fd, "Invalid CIC specified!\n");
16462       return CLI_SUCCESS;
16463    }
16464 
16465    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16466       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16467          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16468          if (blocked) {
16469             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16470             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16471             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16472          }
16473       }
16474    }
16475 
16476    if (blocked > 0)
16477       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16478 
16479    /* Break poll on the linkset so it sends our messages */
16480    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16481 
16482    return CLI_SUCCESS;
16483 }
16484 #endif   /* defined(HAVE_SS7) */
16485 
16486 #if defined(HAVE_SS7)
16487 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16488 {
16489    int linkset;
16490    int i;
16491    switch (cmd) {
16492    case CLI_INIT:
16493       e->command = "ss7 unblock linkset";
16494       e->usage =
16495          "Usage: ss7 unblock linkset <linkset number>\n"
16496          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16497       return NULL;
16498    case CLI_GENERATE:
16499       return NULL;
16500    }
16501 
16502    if (a->argc == 4)
16503       linkset = atoi(a->argv[3]);
16504    else
16505       return CLI_SHOWUSAGE;
16506 
16507    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16508       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16509       return CLI_SUCCESS;
16510    }
16511 
16512    if (!linksets[linkset-1].ss7.ss7) {
16513       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16514       return CLI_SUCCESS;
16515    }
16516 
16517    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16518       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16519       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16520       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16521       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16522    }
16523 
16524    /* Break poll on the linkset so it sends our messages */
16525    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16526 
16527    return CLI_SUCCESS;
16528 }
16529 #endif   /* defined(HAVE_SS7) */
16530 
16531 #if defined(HAVE_SS7)
16532 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16533 {
16534    int linkset;
16535    struct sig_ss7_linkset *ss7;
16536    switch (cmd) {
16537    case CLI_INIT:
16538       e->command = "ss7 show linkset";
16539       e->usage =
16540          "Usage: ss7 show linkset <span>\n"
16541          "       Shows the status of an SS7 linkset.\n";
16542       return NULL;
16543    case CLI_GENERATE:
16544       return NULL;
16545    }
16546 
16547    if (a->argc < 4)
16548       return CLI_SHOWUSAGE;
16549    linkset = atoi(a->argv[3]);
16550    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16551       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16552       return CLI_SUCCESS;
16553    }
16554    ss7 = &linksets[linkset - 1].ss7;
16555    if (!ss7->ss7) {
16556       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16557       return CLI_SUCCESS;
16558    }
16559 
16560    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16561 
16562    return CLI_SUCCESS;
16563 }
16564 #endif   /* defined(HAVE_SS7) */
16565 
16566 #if defined(HAVE_SS7)
16567 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16568 {
16569    int linkset;
16570 
16571    switch (cmd) {
16572    case CLI_INIT:
16573       e->command = "ss7 show channels";
16574       e->usage =
16575          "Usage: ss7 show channels\n"
16576          "       Displays SS7 channel information at a glance.\n";
16577       return NULL;
16578    case CLI_GENERATE:
16579       return NULL;
16580    }
16581 
16582    if (a->argc != 3)
16583       return CLI_SHOWUSAGE;
16584 
16585    sig_ss7_cli_show_channels_header(a->fd);
16586    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16587       if (linksets[linkset].ss7.ss7) {
16588          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16589       }
16590    }
16591    return CLI_SUCCESS;
16592 }
16593 #endif   /* defined(HAVE_SS7) */
16594 
16595 #if defined(HAVE_SS7)
16596 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16597 {
16598    switch (cmd) {
16599    case CLI_INIT:
16600       e->command = "ss7 show version";
16601       e->usage =
16602          "Usage: ss7 show version\n"
16603          "  Show the libss7 version\n";
16604       return NULL;
16605    case CLI_GENERATE:
16606       return NULL;
16607    }
16608 
16609    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16610 
16611    return CLI_SUCCESS;
16612 }
16613 #endif   /* defined(HAVE_SS7) */
16614 
16615 #if defined(HAVE_SS7)
16616 static struct ast_cli_entry dahdi_ss7_cli[] = {
16617    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16618    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16619    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16620    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16621    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16622    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16623    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16624    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16625 };
16626 #endif   /* defined(HAVE_SS7) */
16627 
16628 #if defined(HAVE_PRI)
16629 #if defined(HAVE_PRI_CCSS)
16630 /*!
16631  * \internal
16632  * \brief CC agent initialization.
16633  * \since 1.8
16634  *
16635  * \param agent CC core agent control.
16636  * \param chan Original channel the agent will attempt to recall.
16637  *
16638  * \details
16639  * This callback is called when the CC core is initialized.  Agents should allocate
16640  * any private data necessary for the call and assign it to the private_data
16641  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16642  * specific agent type, they should be set in this function as well.
16643  *
16644  * \retval 0 on success.
16645  * \retval -1 on error.
16646  */
16647 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16648 {
16649    struct dahdi_pvt *pvt;
16650    struct sig_pri_chan *pvt_chan;
16651    int res;
16652 
16653    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16654 
16655    pvt = chan->tech_pvt;
16656    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16657       pvt_chan = pvt->sig_pvt;
16658    } else {
16659       pvt_chan = NULL;
16660    }
16661    if (!pvt_chan) {
16662       return -1;
16663    }
16664 
16665    ast_module_ref(ast_module_info->self);
16666 
16667    res = sig_pri_cc_agent_init(agent, pvt_chan);
16668    if (res) {
16669       ast_module_unref(ast_module_info->self);
16670    }
16671    return res;
16672 }
16673 #endif   /* defined(HAVE_PRI_CCSS) */
16674 #endif   /* defined(HAVE_PRI) */
16675 
16676 #if defined(HAVE_PRI)
16677 #if defined(HAVE_PRI_CCSS)
16678 /*!
16679  * \internal
16680  * \brief Destroy private data on the agent.
16681  * \since 1.8
16682  *
16683  * \param agent CC core agent control.
16684  *
16685  * \details
16686  * The core will call this function upon completion
16687  * or failure of CC.
16688  *
16689  * \return Nothing
16690  */
16691 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16692 {
16693    sig_pri_cc_agent_destructor(agent);
16694 
16695    ast_module_unref(ast_module_info->self);
16696 }
16697 #endif   /* defined(HAVE_PRI_CCSS) */
16698 #endif   /* defined(HAVE_PRI) */
16699 
16700 #if defined(HAVE_PRI)
16701 #if defined(HAVE_PRI_CCSS)
16702 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16703    .type = dahdi_pri_cc_type,
16704    .init = dahdi_pri_cc_agent_init,
16705    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16706    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16707    .respond = sig_pri_cc_agent_req_rsp,
16708    .status_request = sig_pri_cc_agent_status_req,
16709    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16710    .party_b_free = sig_pri_cc_agent_party_b_free,
16711    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16712    .callee_available = sig_pri_cc_agent_callee_available,
16713    .destructor = dahdi_pri_cc_agent_destructor,
16714 };
16715 #endif   /* defined(HAVE_PRI_CCSS) */
16716 #endif   /* defined(HAVE_PRI) */
16717 
16718 #if defined(HAVE_PRI)
16719 #if defined(HAVE_PRI_CCSS)
16720 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16721    .type = dahdi_pri_cc_type,
16722    .request_cc = sig_pri_cc_monitor_req_cc,
16723    .suspend = sig_pri_cc_monitor_suspend,
16724    .unsuspend = sig_pri_cc_monitor_unsuspend,
16725    .status_response = sig_pri_cc_monitor_status_rsp,
16726    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16727    .destructor = sig_pri_cc_monitor_destructor,
16728 };
16729 #endif   /* defined(HAVE_PRI_CCSS) */
16730 #endif   /* defined(HAVE_PRI) */
16731 
16732 static int __unload_module(void)
16733 {
16734    struct dahdi_pvt *p;
16735 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16736    int i, j;
16737 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16738 
16739 #ifdef HAVE_PRI
16740    for (i = 0; i < NUM_SPANS; i++) {
16741       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16742          pthread_cancel(pris[i].pri.master);
16743          pthread_kill(pris[i].pri.master, SIGURG);
16744       }
16745    }
16746    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16747    ast_unregister_application(dahdi_send_keypad_facility_app);
16748 #ifdef HAVE_PRI_PROG_W_CAUSE
16749    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16750 #endif
16751 #endif
16752 #if defined(HAVE_SS7)
16753    for (i = 0; i < NUM_SPANS; i++) {
16754       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16755          pthread_cancel(linksets[i].ss7.master);
16756          pthread_kill(linksets[i].ss7.master, SIGURG);
16757       }
16758    }
16759    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16760 #endif   /* defined(HAVE_SS7) */
16761 #if defined(HAVE_OPENR2)
16762    dahdi_r2_destroy_links();
16763    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16764    ast_unregister_application(dahdi_accept_r2_call_app);
16765 #endif
16766 
16767    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16768    ast_manager_unregister("DAHDIDialOffhook");
16769    ast_manager_unregister("DAHDIHangup");
16770    ast_manager_unregister("DAHDITransfer");
16771    ast_manager_unregister("DAHDIDNDoff");
16772    ast_manager_unregister("DAHDIDNDon");
16773    ast_manager_unregister("DAHDIShowChannels");
16774    ast_manager_unregister("DAHDIRestart");
16775    ast_data_unregister(NULL);
16776    ast_channel_unregister(&dahdi_tech);
16777 
16778    /* Hangup all interfaces if they have an owner */
16779    ast_mutex_lock(&iflock);
16780    for (p = iflist; p; p = p->next) {
16781       if (p->owner)
16782          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16783    }
16784    ast_mutex_unlock(&iflock);
16785 
16786    ast_mutex_lock(&monlock);
16787    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16788       pthread_cancel(monitor_thread);
16789       pthread_kill(monitor_thread, SIGURG);
16790       pthread_join(monitor_thread, NULL);
16791    }
16792    monitor_thread = AST_PTHREADT_STOP;
16793    ast_mutex_unlock(&monlock);
16794 
16795    destroy_all_channels();
16796 
16797 #if defined(HAVE_PRI)
16798    for (i = 0; i < NUM_SPANS; i++) {
16799       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16800          pthread_join(pris[i].pri.master, NULL);
16801       }
16802       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16803          dahdi_close_pri_fd(&(pris[i]), j);
16804       }
16805       sig_pri_stop_pri(&pris[i].pri);
16806    }
16807 #if defined(HAVE_PRI_CCSS)
16808    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16809    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16810 #endif   /* defined(HAVE_PRI_CCSS) */
16811    sig_pri_unload();
16812 #endif
16813 
16814 #if defined(HAVE_SS7)
16815    for (i = 0; i < NUM_SPANS; i++) {
16816       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16817          pthread_join(linksets[i].ss7.master, NULL);
16818       }
16819       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16820          dahdi_close_ss7_fd(&(linksets[i]), j);
16821       }
16822    }
16823 #endif   /* defined(HAVE_SS7) */
16824    ast_cond_destroy(&ss_thread_complete);
16825    return 0;
16826 }
16827 
16828 static int unload_module(void)
16829 {
16830 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16831    int y;
16832 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16833 #ifdef HAVE_PRI
16834    for (y = 0; y < NUM_SPANS; y++)
16835       ast_mutex_destroy(&pris[y].pri.lock);
16836 #endif
16837 #if defined(HAVE_SS7)
16838    for (y = 0; y < NUM_SPANS; y++)
16839       ast_mutex_destroy(&linksets[y].ss7.lock);
16840 #endif   /* defined(HAVE_SS7) */
16841    return __unload_module();
16842 }
16843 
16844 static void string_replace(char *str, int char1, int char2)
16845 {
16846    for (; *str; str++) {
16847       if (*str == char1) {
16848          *str = char2;
16849       }
16850    }
16851 }
16852 
16853 static char *parse_spanchan(char *chanstr, char **subdir)
16854 {
16855    char *p;
16856 
16857    if ((p = strrchr(chanstr, '!')) == NULL) {
16858       *subdir = NULL;
16859       return chanstr;
16860    }
16861    *p++ = '\0';
16862    string_replace(chanstr, '!', '/');
16863    *subdir = chanstr;
16864    return p;
16865 }
16866 
16867 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16868 {
16869    char *c, *chan;
16870    char *subdir;
16871    int x, start, finish;
16872    struct dahdi_pvt *tmp;
16873 
16874    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16875       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16876       return -1;
16877    }
16878 
16879    c = ast_strdupa(value);
16880    c = parse_spanchan(c, &subdir);
16881 
16882    while ((chan = strsep(&c, ","))) {
16883       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16884          /* Range */
16885       } else if (sscanf(chan, "%30d", &start)) {
16886          /* Just one */
16887          finish = start;
16888       } else if (!strcasecmp(chan, "pseudo")) {
16889          finish = start = CHAN_PSEUDO;
16890          if (found_pseudo)
16891             *found_pseudo = 1;
16892       } else {
16893          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16894          return -1;
16895       }
16896       if (finish < start) {
16897          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16898          x = finish;
16899          finish = start;
16900          start = x;
16901       }
16902 
16903       for (x = start; x <= finish; x++) {
16904          char fn[PATH_MAX];
16905          int real_channel = x;
16906 
16907          if (!ast_strlen_zero(subdir)) {
16908             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16909             if (real_channel < 0) {
16910                if (conf->ignore_failed_channels) {
16911                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16912                         subdir, x, real_channel);
16913                   continue;
16914                } else {
16915                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16916                         subdir, x, real_channel);
16917                   return -1;
16918                }
16919             }
16920          }
16921          tmp = mkintf(real_channel, conf, reload);
16922 
16923          if (tmp) {
16924             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16925          } else {
16926             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16927                   (reload == 1) ? "reconfigure" : "register", value);
16928             return -1;
16929          }
16930       }
16931    }
16932 
16933    return 0;
16934 }
16935 
16936 /** The length of the parameters list of 'dahdichan'.
16937  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16938 #define MAX_CHANLIST_LEN 80
16939 
16940 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16941 {
16942    char *parse = ast_strdupa(data);
16943    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16944    unsigned int param_count;
16945    unsigned int x;
16946 
16947    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16948       return;
16949 
16950    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16951 
16952    /* first parameter is tap length, process it here */
16953 
16954    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16955 
16956    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16957       confp->chan.echocancel.head.tap_length = x;
16958    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16959       confp->chan.echocancel.head.tap_length = 128;
16960 
16961    /* now process any remaining parameters */
16962 
16963    for (x = 1; x < param_count; x++) {
16964       struct {
16965          char *name;
16966          char *value;
16967       } param;
16968 
16969       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16970          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16971          continue;
16972       }
16973 
16974       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16975          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16976          continue;
16977       }
16978 
16979       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16980 
16981       if (param.value) {
16982          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16983             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16984             continue;
16985          }
16986       }
16987       confp->chan.echocancel.head.param_count++;
16988    }
16989 }
16990 
16991 /*! process_dahdi() - ignore keyword 'channel' and similar */
16992 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16993 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16994 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16995 
16996 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16997 {
16998    struct dahdi_pvt *tmp;
16999    int y;
17000    int found_pseudo = 0;
17001    struct ast_variable *dahdichan = NULL;
17002 
17003    for (; v; v = v->next) {
17004       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17005          continue;
17006 
17007       /* Create the interface list */
17008       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17009          if (options & PROC_DAHDI_OPT_NOCHAN) {
17010             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17011             continue;
17012          }
17013          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17014             if (confp->ignore_failed_channels) {
17015                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17016                continue;
17017             } else {
17018                return -1;
17019             }
17020          }
17021          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17022       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17023          confp->ignore_failed_channels = ast_true(v->value);
17024       } else if (!strcasecmp(v->name, "buffers")) {
17025          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17026             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17027             confp->chan.buf_no = numbufs;
17028             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17029          }
17030       } else if (!strcasecmp(v->name, "faxbuffers")) {
17031          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17032             confp->chan.usefaxbuffers = 1;
17033          }
17034       } else if (!strcasecmp(v->name, "dahdichan")) {
17035          /* Only process the last dahdichan value. */
17036          dahdichan = v;
17037       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17038          usedistinctiveringdetection = ast_true(v->value);
17039       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17040          distinctiveringaftercid = ast_true(v->value);
17041       } else if (!strcasecmp(v->name, "dring1context")) {
17042          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17043       } else if (!strcasecmp(v->name, "dring2context")) {
17044          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17045       } else if (!strcasecmp(v->name, "dring3context")) {
17046          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17047       } else if (!strcasecmp(v->name, "dring1range")) {
17048          confp->chan.drings.ringnum[0].range = atoi(v->value);
17049       } else if (!strcasecmp(v->name, "dring2range")) {
17050          confp->chan.drings.ringnum[1].range = atoi(v->value);
17051       } else if (!strcasecmp(v->name, "dring3range")) {
17052          confp->chan.drings.ringnum[2].range = atoi(v->value);
17053       } else if (!strcasecmp(v->name, "dring1")) {
17054          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]);
17055       } else if (!strcasecmp(v->name, "dring2")) {
17056          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]);
17057       } else if (!strcasecmp(v->name, "dring3")) {
17058          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]);
17059       } else if (!strcasecmp(v->name, "usecallerid")) {
17060          confp->chan.use_callerid = ast_true(v->value);
17061       } else if (!strcasecmp(v->name, "cidsignalling")) {
17062          if (!strcasecmp(v->value, "bell"))
17063             confp->chan.cid_signalling = CID_SIG_BELL;
17064          else if (!strcasecmp(v->value, "v23"))
17065             confp->chan.cid_signalling = CID_SIG_V23;
17066          else if (!strcasecmp(v->value, "dtmf"))
17067             confp->chan.cid_signalling = CID_SIG_DTMF;
17068          else if (!strcasecmp(v->value, "smdi"))
17069             confp->chan.cid_signalling = CID_SIG_SMDI;
17070          else if (!strcasecmp(v->value, "v23_jp"))
17071             confp->chan.cid_signalling = CID_SIG_V23_JP;
17072          else if (ast_true(v->value))
17073             confp->chan.cid_signalling = CID_SIG_BELL;
17074       } else if (!strcasecmp(v->name, "cidstart")) {
17075          if (!strcasecmp(v->value, "ring"))
17076             confp->chan.cid_start = CID_START_RING;
17077          else if (!strcasecmp(v->value, "polarity_in"))
17078             confp->chan.cid_start = CID_START_POLARITY_IN;
17079          else if (!strcasecmp(v->value, "polarity"))
17080             confp->chan.cid_start = CID_START_POLARITY;
17081          else if (!strcasecmp(v->value, "dtmf"))
17082             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17083          else if (ast_true(v->value))
17084             confp->chan.cid_start = CID_START_RING;
17085       } else if (!strcasecmp(v->name, "threewaycalling")) {
17086          confp->chan.threewaycalling = ast_true(v->value);
17087       } else if (!strcasecmp(v->name, "cancallforward")) {
17088          confp->chan.cancallforward = ast_true(v->value);
17089       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17090          if (ast_true(v->value))
17091             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17092          else
17093             confp->chan.dtmfrelax = 0;
17094       } else if (!strcasecmp(v->name, "mailbox")) {
17095          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17096       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17097          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17098             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17099          }
17100       } else if (!strcasecmp(v->name, "adsi")) {
17101          confp->chan.adsi = ast_true(v->value);
17102       } else if (!strcasecmp(v->name, "usesmdi")) {
17103          confp->chan.use_smdi = ast_true(v->value);
17104       } else if (!strcasecmp(v->name, "smdiport")) {
17105          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17106       } else if (!strcasecmp(v->name, "transfer")) {
17107          confp->chan.transfer = ast_true(v->value);
17108       } else if (!strcasecmp(v->name, "canpark")) {
17109          confp->chan.canpark = ast_true(v->value);
17110       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17111          confp->chan.echocanbridged = ast_true(v->value);
17112       } else if (!strcasecmp(v->name, "busydetect")) {
17113          confp->chan.busydetect = ast_true(v->value);
17114       } else if (!strcasecmp(v->name, "busycount")) {
17115          confp->chan.busycount = atoi(v->value);
17116       } else if (!strcasecmp(v->name, "busypattern")) {
17117          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17118             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17119          }
17120       } else if (!strcasecmp(v->name, "callprogress")) {
17121          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17122          if (ast_true(v->value))
17123             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17124       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17125          confp->chan.waitfordialtone = atoi(v->value);
17126       } else if (!strcasecmp(v->name, "faxdetect")) {
17127          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17128          if (!strcasecmp(v->value, "incoming")) {
17129             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17130          } else if (!strcasecmp(v->value, "outgoing")) {
17131             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17132          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17133             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17134       } else if (!strcasecmp(v->name, "echocancel")) {
17135          process_echocancel(confp, v->value, v->lineno);
17136       } else if (!strcasecmp(v->name, "echotraining")) {
17137          if (sscanf(v->value, "%30d", &y) == 1) {
17138             if ((y < 10) || (y > 4000)) {
17139                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17140             } else {
17141                confp->chan.echotraining = y;
17142             }
17143          } else if (ast_true(v->value)) {
17144             confp->chan.echotraining = 400;
17145          } else
17146             confp->chan.echotraining = 0;
17147       } else if (!strcasecmp(v->name, "hidecallerid")) {
17148          confp->chan.hidecallerid = ast_true(v->value);
17149       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17150          confp->chan.hidecalleridname = ast_true(v->value);
17151       } else if (!strcasecmp(v->name, "pulsedial")) {
17152          confp->chan.pulse = ast_true(v->value);
17153       } else if (!strcasecmp(v->name, "callreturn")) {
17154          confp->chan.callreturn = ast_true(v->value);
17155       } else if (!strcasecmp(v->name, "callwaiting")) {
17156          confp->chan.callwaiting = ast_true(v->value);
17157       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17158          confp->chan.callwaitingcallerid = ast_true(v->value);
17159       } else if (!strcasecmp(v->name, "context")) {
17160          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17161       } else if (!strcasecmp(v->name, "language")) {
17162          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17163       } else if (!strcasecmp(v->name, "progzone")) {
17164          ast_copy_string(progzone, v->value, sizeof(progzone));
17165       } else if (!strcasecmp(v->name, "mohinterpret")
17166          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17167          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17168       } else if (!strcasecmp(v->name, "mohsuggest")) {
17169          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17170       } else if (!strcasecmp(v->name, "parkinglot")) {
17171          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17172       } else if (!strcasecmp(v->name, "stripmsd")) {
17173          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17174          confp->chan.stripmsd = atoi(v->value);
17175       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17176          numbufs = atoi(v->value);
17177       } else if (!strcasecmp(v->name, "group")) {
17178          confp->chan.group = ast_get_group(v->value);
17179       } else if (!strcasecmp(v->name, "callgroup")) {
17180          if (!strcasecmp(v->value, "none"))
17181             confp->chan.callgroup = 0;
17182          else
17183             confp->chan.callgroup = ast_get_group(v->value);
17184       } else if (!strcasecmp(v->name, "pickupgroup")) {
17185          if (!strcasecmp(v->value, "none"))
17186             confp->chan.pickupgroup = 0;
17187          else
17188             confp->chan.pickupgroup = ast_get_group(v->value);
17189       } else if (!strcasecmp(v->name, "setvar")) {
17190          char *varname = ast_strdupa(v->value), *varval = NULL;
17191          struct ast_variable *tmpvar;
17192          if (varname && (varval = strchr(varname, '='))) {
17193             *varval++ = '\0';
17194             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17195                tmpvar->next = confp->chan.vars;
17196                confp->chan.vars = tmpvar;
17197             }
17198          }
17199       } else if (!strcasecmp(v->name, "immediate")) {
17200          confp->chan.immediate = ast_true(v->value);
17201       } else if (!strcasecmp(v->name, "transfertobusy")) {
17202          confp->chan.transfertobusy = ast_true(v->value);
17203       } else if (!strcasecmp(v->name, "mwimonitor")) {
17204          confp->chan.mwimonitor_neon = 0;
17205          confp->chan.mwimonitor_fsk = 0;
17206          confp->chan.mwimonitor_rpas = 0;
17207          if (strcasestr(v->value, "fsk")) {
17208             confp->chan.mwimonitor_fsk = 1;
17209          }
17210          if (strcasestr(v->value, "rpas")) {
17211             confp->chan.mwimonitor_rpas = 1;
17212          }
17213          if (strcasestr(v->value, "neon")) {
17214             confp->chan.mwimonitor_neon = 1;
17215          }
17216          /* If set to true or yes, assume that simple fsk is desired */
17217          if (ast_true(v->value)) {
17218             confp->chan.mwimonitor_fsk = 1;
17219          }
17220       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17221          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17222             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17223          }
17224       } else if (!strcasecmp(v->name, "rxgain")) {
17225          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17226             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17227          }
17228       } else if (!strcasecmp(v->name, "txgain")) {
17229          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17230             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17231          }
17232       } else if (!strcasecmp(v->name, "txdrc")) {
17233          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17234             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17235          }
17236       } else if (!strcasecmp(v->name, "rxdrc")) {
17237          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17238             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17239          }
17240       } else if (!strcasecmp(v->name, "tonezone")) {
17241          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17242             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17243          }
17244       } else if (!strcasecmp(v->name, "callerid")) {
17245          if (!strcasecmp(v->value, "asreceived")) {
17246             confp->chan.cid_num[0] = '\0';
17247             confp->chan.cid_name[0] = '\0';
17248          } else {
17249             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17250          }
17251       } else if (!strcasecmp(v->name, "fullname")) {
17252          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17253       } else if (!strcasecmp(v->name, "cid_number")) {
17254          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17255       } else if (!strcasecmp(v->name, "cid_tag")) {
17256          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17257       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17258          confp->chan.dahditrcallerid = ast_true(v->value);
17259       } else if (!strcasecmp(v->name, "restrictcid")) {
17260          confp->chan.restrictcid = ast_true(v->value);
17261       } else if (!strcasecmp(v->name, "usecallingpres")) {
17262          confp->chan.use_callingpres = ast_true(v->value);
17263       } else if (!strcasecmp(v->name, "accountcode")) {
17264          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17265       } else if (!strcasecmp(v->name, "amaflags")) {
17266          y = ast_cdr_amaflags2int(v->value);
17267          if (y < 0)
17268             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17269          else
17270             confp->chan.amaflags = y;
17271       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17272          confp->chan.polarityonanswerdelay = atoi(v->value);
17273       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17274          confp->chan.answeronpolarityswitch = ast_true(v->value);
17275       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17276          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17277       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17278          confp->chan.sendcalleridafter = atoi(v->value);
17279       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17280          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17281       } else if (ast_cc_is_config_param(v->name)) {
17282          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17283       } else if (!strcasecmp(v->name, "mwisendtype")) {
17284 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17285          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17286             mwisend_rpas = 1;
17287          } else {
17288             mwisend_rpas = 0;
17289          }
17290 #else
17291          /* Default is fsk, to turn it off you must specify nofsk */
17292          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17293          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17294             confp->chan.mwisend_fsk = 0;
17295          } else {             /* Default FSK */
17296             confp->chan.mwisend_fsk = 1;
17297          }
17298          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17299             confp->chan.mwisend_rpas = 1;
17300          } else {
17301             confp->chan.mwisend_rpas = 0;
17302          }
17303          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17304             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17305          }
17306          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17307             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17308          }
17309          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17310             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17311          }
17312 #endif
17313       } else if (reload != 1) {
17314           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17315             int orig_radio = confp->chan.radio;
17316             int orig_outsigmod = confp->chan.outsigmod;
17317             int orig_auto = confp->is_sig_auto;
17318 
17319             confp->chan.radio = 0;
17320             confp->chan.outsigmod = -1;
17321             confp->is_sig_auto = 0;
17322             if (!strcasecmp(v->value, "em")) {
17323                confp->chan.sig = SIG_EM;
17324             } else if (!strcasecmp(v->value, "em_e1")) {
17325                confp->chan.sig = SIG_EM_E1;
17326             } else if (!strcasecmp(v->value, "em_w")) {
17327                confp->chan.sig = SIG_EMWINK;
17328             } else if (!strcasecmp(v->value, "fxs_ls")) {
17329                confp->chan.sig = SIG_FXSLS;
17330             } else if (!strcasecmp(v->value, "fxs_gs")) {
17331                confp->chan.sig = SIG_FXSGS;
17332             } else if (!strcasecmp(v->value, "fxs_ks")) {
17333                confp->chan.sig = SIG_FXSKS;
17334             } else if (!strcasecmp(v->value, "fxo_ls")) {
17335                confp->chan.sig = SIG_FXOLS;
17336             } else if (!strcasecmp(v->value, "fxo_gs")) {
17337                confp->chan.sig = SIG_FXOGS;
17338             } else if (!strcasecmp(v->value, "fxo_ks")) {
17339                confp->chan.sig = SIG_FXOKS;
17340             } else if (!strcasecmp(v->value, "fxs_rx")) {
17341                confp->chan.sig = SIG_FXSKS;
17342                confp->chan.radio = 1;
17343             } else if (!strcasecmp(v->value, "fxo_rx")) {
17344                confp->chan.sig = SIG_FXOLS;
17345                confp->chan.radio = 1;
17346             } else if (!strcasecmp(v->value, "fxs_tx")) {
17347                confp->chan.sig = SIG_FXSLS;
17348                confp->chan.radio = 1;
17349             } else if (!strcasecmp(v->value, "fxo_tx")) {
17350                confp->chan.sig = SIG_FXOGS;
17351                confp->chan.radio = 1;
17352             } else if (!strcasecmp(v->value, "em_rx")) {
17353                confp->chan.sig = SIG_EM;
17354                confp->chan.radio = 1;
17355             } else if (!strcasecmp(v->value, "em_tx")) {
17356                confp->chan.sig = SIG_EM;
17357                confp->chan.radio = 1;
17358             } else if (!strcasecmp(v->value, "em_rxtx")) {
17359                confp->chan.sig = SIG_EM;
17360                confp->chan.radio = 2;
17361             } else if (!strcasecmp(v->value, "em_txrx")) {
17362                confp->chan.sig = SIG_EM;
17363                confp->chan.radio = 2;
17364             } else if (!strcasecmp(v->value, "sf")) {
17365                confp->chan.sig = SIG_SF;
17366             } else if (!strcasecmp(v->value, "sf_w")) {
17367                confp->chan.sig = SIG_SFWINK;
17368             } else if (!strcasecmp(v->value, "sf_featd")) {
17369                confp->chan.sig = SIG_FEATD;
17370             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17371                confp->chan.sig = SIG_FEATDMF;
17372             } else if (!strcasecmp(v->value, "sf_featb")) {
17373                confp->chan.sig = SIG_SF_FEATB;
17374             } else if (!strcasecmp(v->value, "sf")) {
17375                confp->chan.sig = SIG_SF;
17376             } else if (!strcasecmp(v->value, "sf_rx")) {
17377                confp->chan.sig = SIG_SF;
17378                confp->chan.radio = 1;
17379             } else if (!strcasecmp(v->value, "sf_tx")) {
17380                confp->chan.sig = SIG_SF;
17381                confp->chan.radio = 1;
17382             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17383                confp->chan.sig = SIG_SF;
17384                confp->chan.radio = 2;
17385             } else if (!strcasecmp(v->value, "sf_txrx")) {
17386                confp->chan.sig = SIG_SF;
17387                confp->chan.radio = 2;
17388             } else if (!strcasecmp(v->value, "featd")) {
17389                confp->chan.sig = SIG_FEATD;
17390             } else if (!strcasecmp(v->value, "featdmf")) {
17391                confp->chan.sig = SIG_FEATDMF;
17392             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17393                confp->chan.sig = SIG_FEATDMF_TA;
17394             } else if (!strcasecmp(v->value, "e911")) {
17395                confp->chan.sig = SIG_E911;
17396             } else if (!strcasecmp(v->value, "fgccama")) {
17397                confp->chan.sig = SIG_FGC_CAMA;
17398             } else if (!strcasecmp(v->value, "fgccamamf")) {
17399                confp->chan.sig = SIG_FGC_CAMAMF;
17400             } else if (!strcasecmp(v->value, "featb")) {
17401                confp->chan.sig = SIG_FEATB;
17402 #ifdef HAVE_PRI
17403             } else if (!strcasecmp(v->value, "pri_net")) {
17404                confp->chan.sig = SIG_PRI;
17405                confp->pri.pri.nodetype = PRI_NETWORK;
17406             } else if (!strcasecmp(v->value, "pri_cpe")) {
17407                confp->chan.sig = SIG_PRI;
17408                confp->pri.pri.nodetype = PRI_CPE;
17409             } else if (!strcasecmp(v->value, "bri_cpe")) {
17410                confp->chan.sig = SIG_BRI;
17411                confp->pri.pri.nodetype = PRI_CPE;
17412             } else if (!strcasecmp(v->value, "bri_net")) {
17413                confp->chan.sig = SIG_BRI;
17414                confp->pri.pri.nodetype = PRI_NETWORK;
17415             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17416                confp->chan.sig = SIG_BRI_PTMP;
17417                confp->pri.pri.nodetype = PRI_CPE;
17418             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17419 #if defined(HAVE_PRI_CALL_HOLD)
17420                confp->chan.sig = SIG_BRI_PTMP;
17421                confp->pri.pri.nodetype = PRI_NETWORK;
17422 #else
17423                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17424 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17425 #endif
17426 #if defined(HAVE_SS7)
17427             } else if (!strcasecmp(v->value, "ss7")) {
17428                confp->chan.sig = SIG_SS7;
17429 #endif   /* defined(HAVE_SS7) */
17430 #ifdef HAVE_OPENR2
17431             } else if (!strcasecmp(v->value, "mfcr2")) {
17432                confp->chan.sig = SIG_MFCR2;
17433 #endif
17434             } else if (!strcasecmp(v->value, "auto")) {
17435                confp->is_sig_auto = 1;
17436             } else {
17437                confp->chan.outsigmod = orig_outsigmod;
17438                confp->chan.radio = orig_radio;
17439                confp->is_sig_auto = orig_auto;
17440                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17441             }
17442           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17443             if (!strcasecmp(v->value, "em")) {
17444                confp->chan.outsigmod = SIG_EM;
17445             } else if (!strcasecmp(v->value, "em_e1")) {
17446                confp->chan.outsigmod = SIG_EM_E1;
17447             } else if (!strcasecmp(v->value, "em_w")) {
17448                confp->chan.outsigmod = SIG_EMWINK;
17449             } else if (!strcasecmp(v->value, "sf")) {
17450                confp->chan.outsigmod = SIG_SF;
17451             } else if (!strcasecmp(v->value, "sf_w")) {
17452                confp->chan.outsigmod = SIG_SFWINK;
17453             } else if (!strcasecmp(v->value, "sf_featd")) {
17454                confp->chan.outsigmod = SIG_FEATD;
17455             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17456                confp->chan.outsigmod = SIG_FEATDMF;
17457             } else if (!strcasecmp(v->value, "sf_featb")) {
17458                confp->chan.outsigmod = SIG_SF_FEATB;
17459             } else if (!strcasecmp(v->value, "sf")) {
17460                confp->chan.outsigmod = SIG_SF;
17461             } else if (!strcasecmp(v->value, "featd")) {
17462                confp->chan.outsigmod = SIG_FEATD;
17463             } else if (!strcasecmp(v->value, "featdmf")) {
17464                confp->chan.outsigmod = SIG_FEATDMF;
17465             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17466                confp->chan.outsigmod = SIG_FEATDMF_TA;
17467             } else if (!strcasecmp(v->value, "e911")) {
17468                confp->chan.outsigmod = SIG_E911;
17469             } else if (!strcasecmp(v->value, "fgccama")) {
17470                confp->chan.outsigmod = SIG_FGC_CAMA;
17471             } else if (!strcasecmp(v->value, "fgccamamf")) {
17472                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17473             } else if (!strcasecmp(v->value, "featb")) {
17474                confp->chan.outsigmod = SIG_FEATB;
17475             } else {
17476                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17477             }
17478 #ifdef HAVE_PRI
17479          } else if (!strcasecmp(v->name, "pridialplan")) {
17480             if (!strcasecmp(v->value, "national")) {
17481                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17482             } else if (!strcasecmp(v->value, "unknown")) {
17483                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17484             } else if (!strcasecmp(v->value, "private")) {
17485                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17486             } else if (!strcasecmp(v->value, "international")) {
17487                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17488             } else if (!strcasecmp(v->value, "local")) {
17489                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17490             } else if (!strcasecmp(v->value, "dynamic")) {
17491                confp->pri.pri.dialplan = -1;
17492             } else if (!strcasecmp(v->value, "redundant")) {
17493                confp->pri.pri.dialplan = -2;
17494             } else {
17495                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17496             }
17497          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17498             if (!strcasecmp(v->value, "national")) {
17499                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17500             } else if (!strcasecmp(v->value, "unknown")) {
17501                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17502             } else if (!strcasecmp(v->value, "private")) {
17503                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17504             } else if (!strcasecmp(v->value, "international")) {
17505                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17506             } else if (!strcasecmp(v->value, "local")) {
17507                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17508             } else if (!strcasecmp(v->value, "dynamic")) {
17509                confp->pri.pri.localdialplan = -1;
17510             } else if (!strcasecmp(v->value, "redundant")) {
17511                confp->pri.pri.localdialplan = -2;
17512             } else {
17513                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17514             }
17515          } else if (!strcasecmp(v->name, "switchtype")) {
17516             if (!strcasecmp(v->value, "national"))
17517                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17518             else if (!strcasecmp(v->value, "ni1"))
17519                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17520             else if (!strcasecmp(v->value, "dms100"))
17521                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17522             else if (!strcasecmp(v->value, "4ess"))
17523                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17524             else if (!strcasecmp(v->value, "5ess"))
17525                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17526             else if (!strcasecmp(v->value, "euroisdn"))
17527                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17528             else if (!strcasecmp(v->value, "qsig"))
17529                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17530             else {
17531                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17532                return -1;
17533             }
17534          } else if (!strcasecmp(v->name, "msn")) {
17535             ast_copy_string(confp->pri.pri.msn_list, v->value,
17536                sizeof(confp->pri.pri.msn_list));
17537          } else if (!strcasecmp(v->name, "nsf")) {
17538             if (!strcasecmp(v->value, "sdn"))
17539                confp->pri.pri.nsf = PRI_NSF_SDN;
17540             else if (!strcasecmp(v->value, "megacom"))
17541                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17542             else if (!strcasecmp(v->value, "tollfreemegacom"))
17543                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17544             else if (!strcasecmp(v->value, "accunet"))
17545                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17546             else if (!strcasecmp(v->value, "none"))
17547                confp->pri.pri.nsf = PRI_NSF_NONE;
17548             else {
17549                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17550                confp->pri.pri.nsf = PRI_NSF_NONE;
17551             }
17552          } else if (!strcasecmp(v->name, "priindication")) {
17553             if (!strcasecmp(v->value, "outofband"))
17554                confp->chan.priindication_oob = 1;
17555             else if (!strcasecmp(v->value, "inband"))
17556                confp->chan.priindication_oob = 0;
17557             else
17558                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17559                   v->value, v->lineno);
17560          } else if (!strcasecmp(v->name, "priexclusive")) {
17561             confp->chan.priexclusive = ast_true(v->value);
17562          } else if (!strcasecmp(v->name, "internationalprefix")) {
17563             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17564          } else if (!strcasecmp(v->name, "nationalprefix")) {
17565             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17566          } else if (!strcasecmp(v->name, "localprefix")) {
17567             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17568          } else if (!strcasecmp(v->name, "privateprefix")) {
17569             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17570          } else if (!strcasecmp(v->name, "unknownprefix")) {
17571             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17572          } else if (!strcasecmp(v->name, "resetinterval")) {
17573             if (!strcasecmp(v->value, "never"))
17574                confp->pri.pri.resetinterval = -1;
17575             else if (atoi(v->value) >= 60)
17576                confp->pri.pri.resetinterval = atoi(v->value);
17577             else
17578                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17579                   v->value, v->lineno);
17580          } else if (!strcasecmp(v->name, "minunused")) {
17581             confp->pri.pri.minunused = atoi(v->value);
17582          } else if (!strcasecmp(v->name, "minidle")) {
17583             confp->pri.pri.minidle = atoi(v->value);
17584          } else if (!strcasecmp(v->name, "idleext")) {
17585             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17586          } else if (!strcasecmp(v->name, "idledial")) {
17587             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17588          } else if (!strcasecmp(v->name, "overlapdial")) {
17589             if (ast_true(v->value)) {
17590                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17591             } else if (!strcasecmp(v->value, "incoming")) {
17592                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17593             } else if (!strcasecmp(v->value, "outgoing")) {
17594                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17595             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17596                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17597             } else {
17598                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17599             }
17600 #ifdef HAVE_PRI_PROG_W_CAUSE
17601          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17602             if (!strcasecmp(v->value, "logical")) {
17603                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17604             } else if (!strcasecmp(v->value, "physical")) {
17605                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17606             } else {
17607                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17608             }
17609 #endif
17610          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17611             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17612 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17613          } else if (!strcasecmp(v->name, "service_message_support")) {
17614             /* assuming switchtype for this channel group has been configured already */
17615             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17616                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17617                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17618                confp->pri.pri.enable_service_message_support = 1;
17619             } else {
17620                confp->pri.pri.enable_service_message_support = 0;
17621             }
17622 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17623 #ifdef HAVE_PRI_INBANDDISCONNECT
17624          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17625             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17626 #endif
17627          } else if (!strcasecmp(v->name, "pritimer")) {
17628 #ifdef PRI_GETSET_TIMERS
17629             char tmp[20];
17630             char *timerc;
17631             char *c;
17632             int timer;
17633             int timeridx;
17634 
17635             ast_copy_string(tmp, v->value, sizeof(tmp));
17636             c = tmp;
17637             timerc = strsep(&c, ",");
17638             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17639                timeridx = pri_timer2idx(timerc);
17640                timer = atoi(c);
17641                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17642                   ast_log(LOG_WARNING,
17643                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17644                      v->lineno);
17645                } else if (!timer) {
17646                   ast_log(LOG_WARNING,
17647                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17648                      c, timerc, v->lineno);
17649                } else {
17650                   confp->pri.pri.pritimers[timeridx] = timer;
17651                }
17652             } else {
17653                ast_log(LOG_WARNING,
17654                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17655                   v->value, v->lineno);
17656             }
17657 #endif /* PRI_GETSET_TIMERS */
17658          } else if (!strcasecmp(v->name, "facilityenable")) {
17659             confp->pri.pri.facilityenable = ast_true(v->value);
17660 #if defined(HAVE_PRI_AOC_EVENTS)
17661          } else if (!strcasecmp(v->name, "aoc_enable")) {
17662             confp->pri.pri.aoc_passthrough_flag = 0;
17663             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17664                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17665             }
17666             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17667                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17668             }
17669             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17670                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17671             }
17672          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17673             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17674 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17675 #if defined(HAVE_PRI_CALL_HOLD)
17676          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17677             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17678 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17679 #if defined(HAVE_PRI_CCSS)
17680          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17681             if (!strcasecmp(v->value, "global")) {
17682                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17683             } else if (!strcasecmp(v->value, "specific")) {
17684                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17685             } else {
17686                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17687             }
17688          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17689             if (!strcasecmp(v->value, "release")) {
17690                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17691             } else if (!strcasecmp(v->value, "retain")) {
17692                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17693             } else if (!strcasecmp(v->value, "do_not_care")) {
17694                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17695             } else {
17696                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17697             }
17698          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17699             if (!strcasecmp(v->value, "release")) {
17700                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17701             } else if (!strcasecmp(v->value, "retain")) {
17702                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17703             } else {
17704                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17705             }
17706 #endif   /* defined(HAVE_PRI_CCSS) */
17707 #if defined(HAVE_PRI_CALL_WAITING)
17708          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17709             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17710             if (confp->pri.pri.max_call_waiting_calls < 0) {
17711                /* Negative values are not allowed. */
17712                confp->pri.pri.max_call_waiting_calls = 0;
17713             }
17714          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17715             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17716 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17717 #if defined(HAVE_PRI_MWI)
17718          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17719             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17720                sizeof(confp->pri.pri.mwi_mailboxes));
17721 #endif   /* defined(HAVE_PRI_MWI) */
17722          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17723             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17724          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17725             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17726          } else if (!strcasecmp(v->name, "layer1_presence")) {
17727             if (!strcasecmp(v->value, "required")) {
17728                confp->pri.pri.layer1_ignored = 0;
17729             } else if (!strcasecmp(v->value, "ignore")) {
17730                confp->pri.pri.layer1_ignored = 1;
17731             } else {
17732                /* Default */
17733                confp->pri.pri.layer1_ignored = 0;
17734             }
17735 #if defined(HAVE_PRI_L2_PERSISTENCE)
17736          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17737             if (!strcasecmp(v->value, "keep_up")) {
17738                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17739             } else if (!strcasecmp(v->value, "leave_down")) {
17740                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17741             } else {
17742                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17743             }
17744 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17745 #endif /* HAVE_PRI */
17746 #if defined(HAVE_SS7)
17747          } else if (!strcasecmp(v->name, "ss7type")) {
17748             if (!strcasecmp(v->value, "itu")) {
17749                cur_ss7type = SS7_ITU;
17750             } else if (!strcasecmp(v->value, "ansi")) {
17751                cur_ss7type = SS7_ANSI;
17752             } else
17753                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17754          } else if (!strcasecmp(v->name, "linkset")) {
17755             cur_linkset = atoi(v->value);
17756          } else if (!strcasecmp(v->name, "pointcode")) {
17757             cur_pointcode = parse_pointcode(v->value);
17758          } else if (!strcasecmp(v->name, "adjpointcode")) {
17759             cur_adjpointcode = parse_pointcode(v->value);
17760          } else if (!strcasecmp(v->name, "defaultdpc")) {
17761             cur_defaultdpc = parse_pointcode(v->value);
17762          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17763             cur_cicbeginswith = atoi(v->value);
17764          } else if (!strcasecmp(v->name, "networkindicator")) {
17765             if (!strcasecmp(v->value, "national"))
17766                cur_networkindicator = SS7_NI_NAT;
17767             else if (!strcasecmp(v->value, "national_spare"))
17768                cur_networkindicator = SS7_NI_NAT_SPARE;
17769             else if (!strcasecmp(v->value, "international"))
17770                cur_networkindicator = SS7_NI_INT;
17771             else if (!strcasecmp(v->value, "international_spare"))
17772                cur_networkindicator = SS7_NI_INT_SPARE;
17773             else
17774                cur_networkindicator = -1;
17775          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17776             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17777          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17778             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17779          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17780             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17781          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17782             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17783          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17784             if (!strcasecmp(v->value, "national")) {
17785                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17786             } else if (!strcasecmp(v->value, "international")) {
17787                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17788             } else if (!strcasecmp(v->value, "subscriber")) {
17789                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17790             } else if (!strcasecmp(v->value, "unknown")) {
17791                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17792             } else if (!strcasecmp(v->value, "dynamic")) {
17793                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17794             } else {
17795                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17796             }
17797          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17798             if (!strcasecmp(v->value, "national")) {
17799                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17800             } else if (!strcasecmp(v->value, "international")) {
17801                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17802             } else if (!strcasecmp(v->value, "subscriber")) {
17803                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17804             } else if (!strcasecmp(v->value, "unknown")) {
17805                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17806             } else if (!strcasecmp(v->value, "dynamic")) {
17807                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17808             } else {
17809                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17810             }
17811          } else if (!strcasecmp(v->name, "sigchan")) {
17812             int sigchan, res;
17813             sigchan = atoi(v->value);
17814             res = linkset_addsigchan(sigchan);
17815             if (res < 0)
17816                return -1;
17817 
17818          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17819             struct dahdi_ss7 *link;
17820             link = ss7_resolve_linkset(cur_linkset);
17821             if (!link) {
17822                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17823                return -1;
17824             }
17825             if (ast_true(v->value))
17826                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17827 #endif   /* defined(HAVE_SS7) */
17828 #ifdef HAVE_OPENR2
17829          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17830             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17831             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);
17832          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17833             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17834          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17835             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17836             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17837                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17838                confp->mfcr2.variant = OR2_VAR_ITU;
17839             }
17840          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17841             confp->mfcr2.mfback_timeout = atoi(v->value);
17842             if (!confp->mfcr2.mfback_timeout) {
17843                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17844                confp->mfcr2.mfback_timeout = -1;
17845             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17846                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17847             }
17848          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17849             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17850             if (confp->mfcr2.metering_pulse_timeout > 500) {
17851                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17852             }
17853          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17854             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17855          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17856             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17857          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17858             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17859          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17860             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17861          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17862             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17863          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17864             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17865          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17866             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17867 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17868          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17869             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17870 #endif
17871          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17872             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17873          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17874             confp->mfcr2.max_ani = atoi(v->value);
17875             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17876                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17877             }
17878          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17879             confp->mfcr2.max_dnis = atoi(v->value);
17880             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17881                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17882             }
17883          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17884             confp->mfcr2.category = openr2_proto_get_category(v->value);
17885             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17886                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17887                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17888                      v->value, v->lineno);
17889             }
17890          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17891             openr2_log_level_t tmplevel;
17892             char *clevel;
17893             char *logval = ast_strdupa(v->value);
17894             while (logval) {
17895                clevel = strsep(&logval,",");
17896                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17897                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17898                   continue;
17899                }
17900                confp->mfcr2.loglevel |= tmplevel;
17901             }
17902 #endif /* HAVE_OPENR2 */
17903          } else if (!strcasecmp(v->name, "cadence")) {
17904             /* setup to scan our argument */
17905             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17906             int i;
17907             struct dahdi_ring_cadence new_cadence;
17908             int cid_location = -1;
17909             int firstcadencepos = 0;
17910             char original_args[80];
17911             int cadence_is_ok = 1;
17912 
17913             ast_copy_string(original_args, v->value, sizeof(original_args));
17914             /* 16 cadences allowed (8 pairs) */
17915             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]);
17916 
17917             /* Cadence must be even (on/off) */
17918             if (element_count % 2 == 1) {
17919                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17920                cadence_is_ok = 0;
17921             }
17922 
17923             /* Ring cadences cannot be negative */
17924             for (i = 0; i < element_count; i++) {
17925                if (c[i] == 0) {
17926                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17927                   cadence_is_ok = 0;
17928                   break;
17929                } else if (c[i] < 0) {
17930                   if (i % 2 == 1) {
17931                      /* Silence duration, negative possibly okay */
17932                      if (cid_location == -1) {
17933                         cid_location = i;
17934                         c[i] *= -1;
17935                      } else {
17936                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17937                         cadence_is_ok = 0;
17938                         break;
17939                      }
17940                   } else {
17941                      if (firstcadencepos == 0) {
17942                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17943                                  /* duration will be passed negative to the DAHDI driver */
17944                      } else {
17945                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17946                         cadence_is_ok = 0;
17947                         break;
17948                      }
17949                   }
17950                }
17951             }
17952 
17953             /* Substitute our scanned cadence */
17954             for (i = 0; i < 16; i++) {
17955                new_cadence.ringcadence[i] = c[i];
17956             }
17957 
17958             if (cadence_is_ok) {
17959                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17960                if (element_count < 2) {
17961                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17962                } else {
17963                   if (cid_location == -1) {
17964                      /* user didn't say; default to first pause */
17965                      cid_location = 1;
17966                   } else {
17967                      /* convert element_index to cidrings value */
17968                      cid_location = (cid_location + 1) / 2;
17969                   }
17970                   /* ---we like their cadence; try to install it--- */
17971                   if (!user_has_defined_cadences++)
17972                      /* this is the first user-defined cadence; clear the default user cadences */
17973                      num_cadence = 0;
17974                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17975                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17976                   else {
17977                      cadences[num_cadence] = new_cadence;
17978                      cidrings[num_cadence++] = cid_location;
17979                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17980                   }
17981                }
17982             }
17983          } else if (!strcasecmp(v->name, "ringtimeout")) {
17984             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17985          } else if (!strcasecmp(v->name, "prewink")) {
17986             confp->timing.prewinktime = atoi(v->value);
17987          } else if (!strcasecmp(v->name, "preflash")) {
17988             confp->timing.preflashtime = atoi(v->value);
17989          } else if (!strcasecmp(v->name, "wink")) {
17990             confp->timing.winktime = atoi(v->value);
17991          } else if (!strcasecmp(v->name, "flash")) {
17992             confp->timing.flashtime = atoi(v->value);
17993          } else if (!strcasecmp(v->name, "start")) {
17994             confp->timing.starttime = atoi(v->value);
17995          } else if (!strcasecmp(v->name, "rxwink")) {
17996             confp->timing.rxwinktime = atoi(v->value);
17997          } else if (!strcasecmp(v->name, "rxflash")) {
17998             confp->timing.rxflashtime = atoi(v->value);
17999          } else if (!strcasecmp(v->name, "debounce")) {
18000             confp->timing.debouncetime = atoi(v->value);
18001          } else if (!strcasecmp(v->name, "toneduration")) {
18002             int toneduration;
18003             int ctlfd;
18004             int res;
18005             struct dahdi_dialparams dps;
18006 
18007             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18008             if (ctlfd == -1) {
18009                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18010                return -1;
18011             }
18012 
18013             toneduration = atoi(v->value);
18014             if (toneduration > -1) {
18015                memset(&dps, 0, sizeof(dps));
18016 
18017                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18018                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18019                if (res < 0) {
18020                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18021                   close(ctlfd);
18022                   return -1;
18023                }
18024             }
18025             close(ctlfd);
18026          } else if (!strcasecmp(v->name, "defaultcic")) {
18027             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18028          } else if (!strcasecmp(v->name, "defaultozz")) {
18029             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18030          } else if (!strcasecmp(v->name, "mwilevel")) {
18031             mwilevel = atoi(v->value);
18032          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18033             dtmfcid_level = atoi(v->value);
18034          } else if (!strcasecmp(v->name, "reportalarms")) {
18035             if (!strcasecmp(v->value, "all"))
18036                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18037             if (!strcasecmp(v->value, "none"))
18038                report_alarms = 0;
18039             else if (!strcasecmp(v->value, "channels"))
18040                report_alarms = REPORT_CHANNEL_ALARMS;
18041             else if (!strcasecmp(v->value, "spans"))
18042                report_alarms = REPORT_SPAN_ALARMS;
18043           }
18044       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18045          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18046    }
18047 
18048    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18049    if (confp->chan.vars) {
18050       ast_variables_destroy(confp->chan.vars);
18051       confp->chan.vars = NULL;
18052    }
18053 
18054    if (dahdichan) {
18055       /* Process the deferred dahdichan value. */
18056       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18057          &found_pseudo)) {
18058          if (confp->ignore_failed_channels) {
18059             ast_log(LOG_WARNING,
18060                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18061                dahdichan->value);
18062          } else {
18063             return -1;
18064          }
18065       }
18066    }
18067 
18068    /* mark the first channels of each DAHDI span to watch for their span alarms */
18069    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18070       if (!tmp->destroy && tmp->span != y) {
18071          tmp->manages_span_alarms = 1;
18072          y = tmp->span; 
18073       } else {
18074          tmp->manages_span_alarms = 0;
18075       }
18076    }
18077 
18078    /*< \todo why check for the pseudo in the per-channel section.
18079     * Any actual use for manual setup of the pseudo channel? */
18080    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18081       /* use the default configuration for a channel, so
18082          that any settings from real configured channels
18083          don't "leak" into the pseudo channel config
18084       */
18085       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18086 
18087       if (conf.chan.cc_params) {
18088          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18089       } else {
18090          tmp = NULL;
18091       }
18092       if (tmp) {
18093          ast_verb(3, "Automatically generated pseudo channel\n");
18094       } else {
18095          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18096       }
18097       ast_cc_config_params_destroy(conf.chan.cc_params);
18098    }
18099    return 0;
18100 }
18101 
18102 /*!
18103  * \internal
18104  * \brief Deep copy struct dahdi_chan_conf.
18105  * \since 1.8
18106  *
18107  * \param dest Destination.
18108  * \param src Source.
18109  *
18110  * \return Nothing
18111  */
18112 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18113 {
18114    struct ast_cc_config_params *cc_params;
18115 
18116    cc_params = dest->chan.cc_params;
18117    *dest = *src;
18118    dest->chan.cc_params = cc_params;
18119    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18120 }
18121 
18122 /*!
18123  * \internal
18124  * \brief Setup DAHDI channel driver.
18125  *
18126  * \param reload enum: load_module(0), reload(1), restart(2).
18127  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18128  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18129  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18130  *
18131  * \retval 0 on success.
18132  * \retval -1 on error.
18133  */
18134 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18135 {
18136    struct ast_config *cfg;
18137    struct ast_config *ucfg;
18138    struct ast_variable *v;
18139    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18140    const char *chans;
18141    const char *cat;
18142    int res;
18143 
18144 #ifdef HAVE_PRI
18145    char *c;
18146    int spanno;
18147    int i;
18148    int logicalspan;
18149    int trunkgroup;
18150    int dchannels[SIG_PRI_NUM_DCHANS];
18151 #endif
18152    int have_cfg_now;
18153    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18154 
18155    cfg = ast_config_load(config, config_flags);
18156    have_cfg_now = !!cfg;
18157    if (!cfg) {
18158       /* Error if we have no config file */
18159       if (had_cfg_before) {
18160          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18161          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18162       }
18163       cfg = ast_config_new();/* Dummy config */
18164       if (!cfg) {
18165          return 0;
18166       }
18167       ucfg = ast_config_load("users.conf", config_flags);
18168       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18169          ast_config_destroy(cfg);
18170          return 0;
18171       }
18172       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18173          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18174          ast_config_destroy(cfg);
18175          return 0;
18176       }
18177    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18178       ucfg = ast_config_load("users.conf", config_flags);
18179       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18180          return 0;
18181       }
18182       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18183          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18184          return 0;
18185       }
18186       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18187       cfg = ast_config_load(config, config_flags);
18188       have_cfg_now = !!cfg;
18189       if (!cfg) {
18190          if (had_cfg_before) {
18191             /* We should have been able to load the config. */
18192             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18193             ast_config_destroy(ucfg);
18194             return 0;
18195          }
18196          cfg = ast_config_new();/* Dummy config */
18197          if (!cfg) {
18198             ast_config_destroy(ucfg);
18199             return 0;
18200          }
18201       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18202          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18203          ast_config_destroy(ucfg);
18204          return 0;
18205       }
18206    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18207       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18208       return 0;
18209    } else {
18210       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18211       ucfg = ast_config_load("users.conf", config_flags);
18212       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18213          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18214          ast_config_destroy(cfg);
18215          return 0;
18216       }
18217    }
18218    had_cfg_before = have_cfg_now;
18219 
18220    /* It's a little silly to lock it, but we might as well just to be sure */
18221    ast_mutex_lock(&iflock);
18222 #ifdef HAVE_PRI
18223    if (reload != 1) {
18224       /* Process trunkgroups first */
18225       v = ast_variable_browse(cfg, "trunkgroups");
18226       while (v) {
18227          if (!strcasecmp(v->name, "trunkgroup")) {
18228             trunkgroup = atoi(v->value);
18229             if (trunkgroup > 0) {
18230                if ((c = strchr(v->value, ','))) {
18231                   i = 0;
18232                   memset(dchannels, 0, sizeof(dchannels));
18233                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18234                      dchannels[i] = atoi(c + 1);
18235                      if (dchannels[i] < 0) {
18236                         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);
18237                      } else
18238                         i++;
18239                      c = strchr(c + 1, ',');
18240                   }
18241                   if (i) {
18242                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18243                         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);
18244                   } else
18245                         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");
18246                   } else
18247                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18248                } else
18249                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18250             } else
18251                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18252          } else if (!strcasecmp(v->name, "spanmap")) {
18253             spanno = atoi(v->value);
18254             if (spanno > 0) {
18255                if ((c = strchr(v->value, ','))) {
18256                   trunkgroup = atoi(c + 1);
18257                   if (trunkgroup > 0) {
18258                      if ((c = strchr(c + 1, ',')))
18259                         logicalspan = atoi(c + 1);
18260                      else
18261                         logicalspan = 0;
18262                      if (logicalspan >= 0) {
18263                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18264                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18265                      } else
18266                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18267                      } else
18268                         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);
18269                   } else
18270                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18271                } else
18272                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18273             } else
18274                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18275          } else {
18276             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18277          }
18278          v = v->next;
18279       }
18280    }
18281 #endif
18282 
18283    /* Copy the default jb config over global_jbconf */
18284    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18285 
18286    mwimonitornotify[0] = '\0';
18287 
18288    v = ast_variable_browse(cfg, "channels");
18289    if ((res = process_dahdi(base_conf,
18290       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18291       v, reload, 0))) {
18292       ast_mutex_unlock(&iflock);
18293       ast_config_destroy(cfg);
18294       if (ucfg) {
18295          ast_config_destroy(ucfg);
18296       }
18297       return res;
18298    }
18299 
18300    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18301    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18302       /* [channels] and [trunkgroups] are used. Let's also reserve
18303        * [globals] and [general] for future use
18304        */
18305       if (!strcasecmp(cat, "general") ||
18306          !strcasecmp(cat, "trunkgroups") ||
18307          !strcasecmp(cat, "globals") ||
18308          !strcasecmp(cat, "channels")) {
18309          continue;
18310       }
18311 
18312       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18313       if (ast_strlen_zero(chans)) {
18314          /* Section is useless without a dahdichan value present. */
18315          continue;
18316       }
18317 
18318       /* Copy base_conf to conf. */
18319       deep_copy_dahdi_chan_conf(conf, base_conf);
18320 
18321       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18322          ast_mutex_unlock(&iflock);
18323          ast_config_destroy(cfg);
18324          if (ucfg) {
18325             ast_config_destroy(ucfg);
18326          }
18327          return res;
18328       }
18329    }
18330 
18331    ast_config_destroy(cfg);
18332 
18333    if (ucfg) {
18334       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18335       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18336       process_dahdi(base_conf,
18337          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18338          ast_variable_browse(ucfg, "general"), 1, 0);
18339 
18340       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18341          if (!strcasecmp(cat, "general")) {
18342             continue;
18343          }
18344 
18345          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18346          if (ast_strlen_zero(chans)) {
18347             /* Section is useless without a dahdichan value present. */
18348             continue;
18349          }
18350 
18351          /* Copy base_conf to conf. */
18352          deep_copy_dahdi_chan_conf(conf, base_conf);
18353 
18354          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18355             ast_config_destroy(ucfg);
18356             ast_mutex_unlock(&iflock);
18357             return res;
18358          }
18359       }
18360       ast_config_destroy(ucfg);
18361    }
18362    ast_mutex_unlock(&iflock);
18363 
18364 #ifdef HAVE_PRI
18365    if (reload != 1) {
18366       int x;
18367       for (x = 0; x < NUM_SPANS; x++) {
18368          if (pris[x].pri.pvts[0]) {
18369             prepare_pri(pris + x);
18370             if (sig_pri_start_pri(&pris[x].pri)) {
18371                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18372                return -1;
18373             } else
18374                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18375          }
18376       }
18377    }
18378 #endif
18379 #if defined(HAVE_SS7)
18380    if (reload != 1) {
18381       int x;
18382       for (x = 0; x < NUM_SPANS; x++) {
18383          if (linksets[x].ss7.ss7) {
18384             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18385             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18386                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18387                return -1;
18388             } else
18389                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18390          }
18391       }
18392    }
18393 #endif   /* defined(HAVE_SS7) */
18394 #ifdef HAVE_OPENR2
18395    if (reload != 1) {
18396       int x;
18397       for (x = 0; x < r2links_count; x++) {
18398          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18399             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18400             return -1;
18401          } else {
18402             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18403          }
18404       }
18405    }
18406 #endif
18407    /* And start the monitor for the first time */
18408    restart_monitor();
18409    return 0;
18410 }
18411 
18412 /*!
18413  * \internal
18414  * \brief Setup DAHDI channel driver.
18415  *
18416  * \param reload enum: load_module(0), reload(1), restart(2).
18417  *
18418  * \retval 0 on success.
18419  * \retval -1 on error.
18420  */
18421 static int setup_dahdi(int reload)
18422 {
18423    int res;
18424    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18425    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18426    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18427 
18428    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18429       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18430    } else {
18431       res = -1;
18432    }
18433    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18434    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18435    ast_cc_config_params_destroy(conf.chan.cc_params);
18436 
18437    return res;
18438 }
18439 
18440 /*!
18441  * \internal
18442  * \brief Callback used to generate the dahdi status tree.
18443  * \param[in] search The search pattern tree.
18444  * \retval NULL on error.
18445  * \retval non-NULL The generated tree.
18446  */
18447 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18448       struct ast_data *data_root)
18449 {
18450    int ctl, res, span;
18451    struct ast_data *data_span, *data_alarms;
18452    struct dahdi_spaninfo s;
18453 
18454    ctl = open("/dev/dahdi/ctl", O_RDWR);
18455    if (ctl < 0) {
18456       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18457       return -1;
18458    }
18459    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18460       s.spanno = span;
18461       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18462       if (res) {
18463          continue;
18464       }
18465 
18466       data_span = ast_data_add_node(data_root, "span");
18467       if (!data_span) {
18468          continue;
18469       }
18470       ast_data_add_str(data_span, "description", s.desc);
18471 
18472       /* insert the alarms status */
18473       data_alarms = ast_data_add_node(data_span, "alarms");
18474       if (!data_alarms) {
18475          continue;
18476       }
18477 
18478       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18479       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18480       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18481       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18482       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18483       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18484 
18485       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18486       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18487       ast_data_add_int(data_span, "crc4", s.crc4count);
18488       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18489                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18490                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18491                      "CAS");
18492       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18493                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18494                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18495                      "Unknown");
18496       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18497                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18498                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18499       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18500 
18501       /* if this span doesn't match remove it. */
18502       if (!ast_data_search_match(search, data_span)) {
18503          ast_data_remove_node(data_root, data_span);
18504       }
18505    }
18506    close(ctl);
18507 
18508    return 0;
18509 }
18510 
18511 /*!
18512  * \internal
18513  * \brief Callback used to generate the dahdi channels tree.
18514  * \param[in] search The search pattern tree.
18515  * \retval NULL on error.
18516  * \retval non-NULL The generated tree.
18517  */
18518 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18519       struct ast_data *data_root)
18520 {
18521    struct dahdi_pvt *tmp;
18522    struct ast_data *data_channel;
18523 
18524    ast_mutex_lock(&iflock);
18525    for (tmp = iflist; tmp; tmp = tmp->next) {
18526       data_channel = ast_data_add_node(data_root, "channel");
18527       if (!data_channel) {
18528          continue;
18529       }
18530 
18531       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18532 
18533       /* if this channel doesn't match remove it. */
18534       if (!ast_data_search_match(search, data_channel)) {
18535          ast_data_remove_node(data_root, data_channel);
18536       }
18537    }
18538    ast_mutex_unlock(&iflock);
18539 
18540    return 0;
18541 }
18542 
18543 /*!
18544  * \internal
18545  * \brief Callback used to generate the dahdi channels tree.
18546  * \param[in] search The search pattern tree.
18547  * \retval NULL on error.
18548  * \retval non-NULL The generated tree.
18549  */
18550 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18551       struct ast_data *data_root)
18552 {
18553    int pseudo_fd = -1;
18554    struct dahdi_versioninfo vi = {
18555       .version = "Unknown",
18556       .echo_canceller = "Unknown"
18557    };
18558 
18559    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18560       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18561       return -1;
18562    }
18563 
18564    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18565       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18566    }
18567 
18568    close(pseudo_fd);
18569 
18570    ast_data_add_str(data_root, "value", vi.version);
18571    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18572 
18573    return 0;
18574 }
18575 
18576 static const struct ast_data_handler dahdi_status_data_provider = {
18577    .version = AST_DATA_HANDLER_VERSION,
18578    .get = dahdi_status_data_provider_get
18579 };
18580 
18581 static const struct ast_data_handler dahdi_channels_data_provider = {
18582    .version = AST_DATA_HANDLER_VERSION,
18583    .get = dahdi_channels_data_provider_get
18584 };
18585 
18586 static const struct ast_data_handler dahdi_version_data_provider = {
18587    .version = AST_DATA_HANDLER_VERSION,
18588    .get = dahdi_version_data_provider_get
18589 };
18590 
18591 static const struct ast_data_entry dahdi_data_providers[] = {
18592    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18593    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18594    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18595 };
18596 
18597 static int load_module(void)
18598 {
18599    int res;
18600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18601    int y;
18602 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18603 
18604 #ifdef HAVE_PRI
18605    memset(pris, 0, sizeof(pris));
18606    for (y = 0; y < NUM_SPANS; y++) {
18607       sig_pri_init_pri(&pris[y].pri);
18608    }
18609    pri_set_error(dahdi_pri_error);
18610    pri_set_message(dahdi_pri_message);
18611    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18612 #ifdef HAVE_PRI_PROG_W_CAUSE
18613    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18614 #endif
18615 #if defined(HAVE_PRI_CCSS)
18616    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18617       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18618       __unload_module();
18619       return AST_MODULE_LOAD_FAILURE;
18620    }
18621 #endif   /* defined(HAVE_PRI_CCSS) */
18622    if (sig_pri_load(
18623 #if defined(HAVE_PRI_CCSS)
18624       dahdi_pri_cc_type
18625 #else
18626       NULL
18627 #endif   /* defined(HAVE_PRI_CCSS) */
18628       )) {
18629       __unload_module();
18630       return AST_MODULE_LOAD_FAILURE;
18631    }
18632 #endif
18633 #if defined(HAVE_SS7)
18634    memset(linksets, 0, sizeof(linksets));
18635    for (y = 0; y < NUM_SPANS; y++) {
18636       sig_ss7_init_linkset(&linksets[y].ss7);
18637    }
18638    ss7_set_error(dahdi_ss7_error);
18639    ss7_set_message(dahdi_ss7_message);
18640 #endif   /* defined(HAVE_SS7) */
18641    res = setup_dahdi(0);
18642    /* Make sure we can register our DAHDI channel type */
18643    if (res)
18644       return AST_MODULE_LOAD_DECLINE;
18645    if (ast_channel_register(&dahdi_tech)) {
18646       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18647       __unload_module();
18648       return AST_MODULE_LOAD_FAILURE;
18649    }
18650 #ifdef HAVE_PRI
18651    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18652 #endif
18653 #if defined(HAVE_SS7)
18654    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18655 #endif   /* defined(HAVE_SS7) */
18656 #ifdef HAVE_OPENR2
18657    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18658    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18659 #endif
18660 
18661    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18662    /* register all the data providers */
18663    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18664    memset(round_robin, 0, sizeof(round_robin));
18665    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18666    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18667    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18668    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18669    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18670    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18671    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18672 
18673    ast_cond_init(&ss_thread_complete, NULL);
18674 
18675    return res;
18676 }
18677 
18678 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18679 {
18680 #define  END_SILENCE_LEN 400
18681 #define  HEADER_MS 50
18682 #define  TRAILER_MS 5
18683 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18684 #define  ASCII_BYTES_PER_CHAR 80
18685 
18686    unsigned char *buf,*mybuf;
18687    struct dahdi_pvt *p = c->tech_pvt;
18688    struct pollfd fds[1];
18689    int size,res,fd,len,x;
18690    int bytes=0;
18691    /* Initial carrier (imaginary) */
18692    float cr = 1.0;
18693    float ci = 0.0;
18694    float scont = 0.0;
18695    int idx;
18696 
18697    idx = dahdi_get_index(c, p, 0);
18698    if (idx < 0) {
18699       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18700       return -1;
18701    }
18702    if (!text[0]) return(0); /* if nothing to send, don't */
18703    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18704    if (p->mate)
18705       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18706    else
18707       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18708    if (!buf)
18709       return -1;
18710    mybuf = buf;
18711    if (p->mate) {
18712       int codec = AST_LAW(p);
18713       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18714          PUT_CLID_MARKMS;
18715       }
18716       /* Put actual message */
18717       for (x = 0; text[x]; x++) {
18718          PUT_CLID(text[x]);
18719       }
18720       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18721          PUT_CLID_MARKMS;
18722       }
18723       len = bytes;
18724       buf = mybuf;
18725    } else {
18726       len = tdd_generate(p->tdd, buf, text);
18727       if (len < 1) {
18728          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18729          ast_free(mybuf);
18730          return -1;
18731       }
18732    }
18733    memset(buf + len, 0x7f, END_SILENCE_LEN);
18734    len += END_SILENCE_LEN;
18735    fd = p->subs[idx].dfd;
18736    while (len) {
18737       if (ast_check_hangup(c)) {
18738          ast_free(mybuf);
18739          return -1;
18740       }
18741       size = len;
18742       if (size > READ_SIZE)
18743          size = READ_SIZE;
18744       fds[0].fd = fd;
18745       fds[0].events = POLLOUT | POLLPRI;
18746       fds[0].revents = 0;
18747       res = poll(fds, 1, -1);
18748       if (!res) {
18749          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18750          continue;
18751       }
18752       /* if got exception */
18753       if (fds[0].revents & POLLPRI) {
18754          ast_free(mybuf);
18755          return -1;
18756       }
18757       if (!(fds[0].revents & POLLOUT)) {
18758          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18759          continue;
18760       }
18761       res = write(fd, buf, size);
18762       if (res != size) {
18763          if (res == -1) {
18764             ast_free(mybuf);
18765             return -1;
18766          }
18767          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18768          break;
18769       }
18770       len -= size;
18771       buf += size;
18772    }
18773    ast_free(mybuf);
18774    return(0);
18775 }
18776 
18777 
18778 static int reload(void)
18779 {
18780    int res = 0;
18781 
18782    res = setup_dahdi(1);
18783    if (res) {
18784       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18785       return -1;
18786    }
18787    return 0;
18788 }
18789 
18790 /* This is a workaround so that menuselect displays a proper description
18791  * AST_MODULE_INFO(, , "DAHDI Telephony"
18792  */
18793 
18794 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18795    .load = load_module,
18796    .unload = unload_module,
18797    .reload = reload,
18798    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18799       .nonoptreq = "res_smdi",
18800    );

Generated on 3 Apr 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1