Wed Nov 28 2012 04:18:04

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: 371590 $")
00053 
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064 
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068 /* Analog signaling is currently still present in chan_dahdi for use with
00069  * radio. Sig_analog does not currently handle any radio operations. If
00070  * radio only uses analog signaling, then the radio handling logic could
00071  * be placed in sig_analog and the duplicated code could be removed.
00072  */
00073 
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif   /* defined(HAVE_PRI) */
00080 
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif   /* defined(HAVE_SS7) */
00087 
00088 #ifdef HAVE_OPENR2
00089 /* put this here until sig_mfcr2 comes along */
00090 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00091 #include <openr2.h>
00092 #endif
00093 
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128 
00129 /*** DOCUMENTATION
00130    <application name="DAHDISendKeypadFacility" language="en_US">
00131       <synopsis>
00132          Send digits out of band over a PRI.
00133       </synopsis>
00134       <syntax>
00135          <parameter name="digits" required="true" />
00136       </syntax>
00137       <description>
00138          <para>This application will send the given string of digits in a Keypad
00139          Facility IE over the current channel.</para>
00140       </description>
00141    </application>
00142    <application name="DAHDISendCallreroutingFacility" language="en_US">
00143       <synopsis>
00144          Send an ISDN call rerouting/deflection facility message.
00145       </synopsis>
00146       <syntax argsep=",">
00147          <parameter name="destination" required="true">
00148             <para>Destination number.</para>
00149          </parameter>
00150          <parameter name="original">
00151             <para>Original called number.</para>
00152          </parameter>
00153          <parameter name="reason">
00154             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00155          </parameter>
00156       </syntax>
00157       <description>
00158          <para>This application will send an ISDN switch specific call
00159          rerouting/deflection facility message over the current channel.
00160          Supported switches depend upon the version of libpri in use.</para>
00161       </description>
00162    </application>
00163    <application name="DAHDIAcceptR2Call" language="en_US">
00164       <synopsis>
00165          Accept an R2 call if its not already accepted (you still need to answer it)
00166       </synopsis>
00167       <syntax>
00168          <parameter name="charge" required="true">
00169             <para>Yes or No.</para>
00170             <para>Whether you want to accept the call with charge or without charge.</para>
00171          </parameter>
00172       </syntax>
00173       <description>
00174          <para>This application will Accept the R2 call either with charge or no charge.</para>
00175       </description>
00176    </application>
00177    <manager name="DAHDITransfer" language="en_US">
00178       <synopsis>
00179          Transfer DAHDI Channel.
00180       </synopsis>
00181       <syntax>
00182          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00183          <parameter name="DAHDIChannel" required="true">
00184             <para>DAHDI channel number to transfer.</para>
00185          </parameter>
00186       </syntax>
00187       <description>
00188          <para>Simulate a flash hook event by the user connected to the channel.</para>
00189          <note><para>Valid only for analog channels.</para></note>
00190       </description>
00191    </manager>
00192    <manager name="DAHDIHangup" language="en_US">
00193       <synopsis>
00194          Hangup DAHDI Channel.
00195       </synopsis>
00196       <syntax>
00197          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00198          <parameter name="DAHDIChannel" required="true">
00199             <para>DAHDI channel number to hangup.</para>
00200          </parameter>
00201       </syntax>
00202       <description>
00203          <para>Simulate an on-hook event by the user connected to the channel.</para>
00204          <note><para>Valid only for analog channels.</para></note>
00205       </description>
00206    </manager>
00207    <manager name="DAHDIDialOffhook" language="en_US">
00208       <synopsis>
00209          Dial over DAHDI channel while offhook.
00210       </synopsis>
00211       <syntax>
00212          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00213          <parameter name="DAHDIChannel" required="true">
00214             <para>DAHDI channel number to dial digits.</para>
00215          </parameter>
00216          <parameter name="Number" required="true">
00217             <para>Digits to dial.</para>
00218          </parameter>
00219       </syntax>
00220       <description>
00221          <para>Generate DTMF control frames to the bridged peer.</para>
00222       </description>
00223    </manager>
00224    <manager name="DAHDIDNDon" language="en_US">
00225       <synopsis>
00226          Toggle DAHDI channel Do Not Disturb status ON.
00227       </synopsis>
00228       <syntax>
00229          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00230          <parameter name="DAHDIChannel" required="true">
00231             <para>DAHDI channel number to set DND on.</para>
00232          </parameter>
00233       </syntax>
00234       <description>
00235          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00236          <note><para>Feature only supported by analog channels.</para></note>
00237       </description>
00238    </manager>
00239    <manager name="DAHDIDNDoff" language="en_US">
00240       <synopsis>
00241          Toggle DAHDI channel Do Not Disturb status OFF.
00242       </synopsis>
00243       <syntax>
00244          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00245          <parameter name="DAHDIChannel" required="true">
00246             <para>DAHDI channel number to set DND off.</para>
00247          </parameter>
00248       </syntax>
00249       <description>
00250          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00251          <note><para>Feature only supported by analog channels.</para></note>
00252       </description>
00253    </manager>
00254    <manager name="DAHDIShowChannels" language="en_US">
00255       <synopsis>
00256          Show status of DAHDI channels.
00257       </synopsis>
00258       <syntax>
00259          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00260          <parameter name="DAHDIChannel">
00261             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00262          </parameter>
00263       </syntax>
00264       <description>
00265          <para>Similar to the CLI command "dahdi show channels".</para>
00266       </description>
00267    </manager>
00268    <manager name="DAHDIRestart" language="en_US">
00269       <synopsis>
00270          Fully Restart DAHDI channels (terminates calls).
00271       </synopsis>
00272       <syntax>
00273          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00274       </syntax>
00275       <description>
00276          <para>Equivalent to the CLI command "dahdi restart".</para>
00277       </description>
00278    </manager>
00279  ***/
00280 
00281 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00282 
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293 
00294 /*! Global jitterbuffer configuration - by default, jb is disabled
00295  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298    .flags = 0,
00299    .max_size = 200,
00300    .resync_threshold = 1000,
00301    .impl = "fixed",
00302    .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305 
00306 /*!
00307  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00308  * the user hangs up to reset the state machine so ring works properly.
00309  * This is used to be able to support kewlstart by putting the zhone in
00310  * groundstart mode since their forward disconnect supervision is entirely
00311  * broken even though their documentation says it isn't and their support
00312  * is entirely unwilling to provide any assistance with their channel banks
00313  * even though their web site says they support their products for life.
00314  */
00315 /* #define ZHONE_HACK */
00316 
00317 /*! \brief Typically, how many rings before we should send Caller*ID */
00318 #define DEFAULT_CIDRINGS 1
00319 
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321 
00322 
00323 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00324 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00325 
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328    " w/"
00329    #if defined(HAVE_PRI)
00330       "PRI"
00331    #endif   /* defined(HAVE_PRI) */
00332    #if defined(HAVE_SS7)
00333       #if defined(HAVE_PRI)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) */
00336       "SS7"
00337    #endif   /* defined(HAVE_SS7) */
00338    #if defined(HAVE_OPENR2)
00339       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340       " & "
00341       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00342       "MFC/R2"
00343    #endif   /* defined(HAVE_OPENR2) */
00344 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00345 ;
00346 
00347 static const char config[] = "chan_dahdi.conf";
00348 
00349 #define SIG_EM    DAHDI_SIG_EM
00350 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00354 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00357 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI      DAHDI_SIG_CLEAR
00365 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2    DAHDI_SIG_CAS
00369 #define  SIG_SF      DAHDI_SIG_SF
00370 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375 
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS       32
00380 #endif
00381 
00382 #define CHAN_PSEUDO  -2
00383 
00384 #define CALLPROGRESS_PROGRESS    1
00385 #define CALLPROGRESS_FAX_OUTGOING   2
00386 #define CALLPROGRESS_FAX_INCOMING   4
00387 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388 
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392 
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00395    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00396    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00397    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00398 };
00399 
00400 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00401  * is 1, the second pause is 2 and so on.
00402  */
00403 
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405    2,                            /*!< Right after first long ring */
00406    4,                            /*!< Right after long part */
00407    3,                            /*!< After third chirp */
00408    2,                            /*!< Second spell */
00409 };
00410 
00411 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413 
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416 
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00419 
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422 
00423 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int  mwisend_rpas = 0;
00427 #endif
00428 
00429 static char progzone[10] = "";
00430 
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433 
00434 static int numbufs = 4;
00435 
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438 
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS    2 
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442 
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447 
00448 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00449 static int firstdigittimeout = 16000;
00450 
00451 /*! \brief How long to wait for following digits (FXO logic) */
00452 static int gendigittimeout = 8000;
00453 
00454 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00455 static int matchdigittimeout = 3000;
00456 
00457 /*! \brief Protect the interface list (of dahdi_pvt's) */
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459 
00460 
00461 static int ifcount = 0;
00462 
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466 
00467 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00468    when it's doing something critical. */
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470 
00471 /*! \brief This is the thread for the monitor which checks for input on the channels
00472    which are not currently in use. */
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479 
00480 static int restart_monitor(void);
00481 
00482 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00483 
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485 
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488    /* This module does not handle MWI in an event-based manner.  However, it
00489     * subscribes to MWI for each mailbox that is configured so that the core
00490     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00491     * event cache instead of checking the mailbox directly. */
00492 }
00493 
00494 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00495 static inline int dahdi_get_event(int fd)
00496 {
00497    int j;
00498    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499       return -1;
00500    return j;
00501 }
00502 
00503 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506    int i, j = 0;
00507    i = DAHDI_IOMUX_SIGEVENT;
00508    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509       return -1;
00510    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511       return -1;
00512    return j;
00513 }
00514 
00515 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00516 #define READ_SIZE 160
00517 
00518 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00519 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00520 
00521 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00522 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00523 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00524 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00525 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00526 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00527 
00528 struct dahdi_pvt;
00529 
00530 /*!
00531  * \brief Configured ring timeout base.
00532  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00533  */
00534 static int ringt_base = DEFAULT_RINGT;
00535 
00536 #if defined(HAVE_SS7)
00537 
00538 struct dahdi_ss7 {
00539    struct sig_ss7_linkset ss7;
00540 };
00541 
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543 
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif   /* defined(HAVE_SS7) */
00552 
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2 {
00555    pthread_t r2master;            /*!< Thread of master */
00556    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00557    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00558    int numchans;                          /*!< Number of channels in this R2 block */
00559    int monitored_count;                   /*!< Number of channels being monitored */
00560 };
00561 
00562 struct dahdi_mfcr2_conf {
00563    openr2_variant_t variant;
00564    int mfback_timeout;
00565    int metering_pulse_timeout;
00566    int max_ani;
00567    int max_dnis;
00568    signed int get_ani_first:2;
00569 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00570    signed int skip_category_request:2;
00571 #endif
00572    unsigned int call_files:1;
00573    unsigned int allow_collect_calls:1;
00574    unsigned int charge_calls:1;
00575    unsigned int accept_on_offer:1;
00576    unsigned int forced_release:1;
00577    unsigned int double_answer:1;
00578    signed int immediate_accept:2;
00579    char logdir[OR2_MAX_PATH];
00580    char r2proto_file[OR2_MAX_PATH];
00581    openr2_log_level_t loglevel;
00582    openr2_calling_party_category_t category;
00583 };
00584 
00585 /* malloc'd array of malloc'd r2links */
00586 static struct dahdi_mfcr2 **r2links;
00587 /* how many r2links have been malloc'd */
00588 static int r2links_count = 0;
00589 
00590 #endif /* HAVE_OPENR2 */
00591 
00592 #ifdef HAVE_PRI
00593 
00594 struct dahdi_pri {
00595    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00596    int mastertrunkgroup;               /*!< What trunk group is our master */
00597    int prilogicalspan;                 /*!< Logical span number within trunk group */
00598    struct sig_pri_span pri;
00599 };
00600 
00601 static struct dahdi_pri pris[NUM_SPANS];
00602 
00603 #if defined(HAVE_PRI_CCSS)
00604 /*! DAHDI PRI CCSS agent and monitor type name. */
00605 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00606 #endif   /* defined(HAVE_PRI_CCSS) */
00607 
00608 #else
00609 /*! Shut up the compiler */
00610 struct dahdi_pri;
00611 #endif
00612 
00613 #define SUB_REAL  0        /*!< Active call */
00614 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00615 #define SUB_THREEWAY 2        /*!< Three-way call */
00616 
00617 /* Polarity states */
00618 #define POLARITY_IDLE   0
00619 #define POLARITY_REV    1
00620 
00621 
00622 struct distRingData {
00623    int ring[3];
00624    int range;
00625 };
00626 struct ringContextData {
00627    char contextData[AST_MAX_CONTEXT];
00628 };
00629 struct dahdi_distRings {
00630    struct distRingData ringnum[3];
00631    struct ringContextData ringContext[3];
00632 };
00633 
00634 static const char * const subnames[] = {
00635    "Real",
00636    "Callwait",
00637    "Threeway"
00638 };
00639 
00640 struct dahdi_subchannel {
00641    int dfd;
00642    struct ast_channel *owner;
00643    int chan;
00644    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00645    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00646    unsigned int needringing:1;
00647    unsigned int needbusy:1;
00648    unsigned int needcongestion:1;
00649    unsigned int needanswer:1;
00650    unsigned int needflash:1;
00651    unsigned int needhold:1;
00652    unsigned int needunhold:1;
00653    unsigned int linear:1;
00654    unsigned int inthreeway:1;
00655    struct dahdi_confinfo curconf;
00656 };
00657 
00658 #define CONF_USER_REAL     (1 << 0)
00659 #define CONF_USER_THIRDCALL   (1 << 1)
00660 
00661 #define MAX_SLAVES   4
00662 
00663 /* States for sending MWI message
00664  * First three states are required for send Ring Pulse Alert Signal
00665  */
00666 typedef enum {
00667    MWI_SEND_NULL = 0,
00668    MWI_SEND_SA,
00669    MWI_SEND_SA_WAIT,
00670    MWI_SEND_PAUSE,
00671    MWI_SEND_SPILL,
00672    MWI_SEND_CLEANUP,
00673    MWI_SEND_DONE,
00674 } mwisend_states;
00675 
00676 struct mwisend_info {
00677    struct   timeval  pause;
00678    mwisend_states    mwisend_current;
00679 };
00680 
00681 /*! Specify the lists dahdi_pvt can be put in. */
00682 enum DAHDI_IFLIST {
00683    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00684    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00685 #if defined(HAVE_PRI)
00686    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00687 #endif   /* defined(HAVE_PRI) */
00688 };
00689 
00690 struct dahdi_pvt {
00691    ast_mutex_t lock;             /*!< Channel private lock. */
00692    struct callerid_state *cs;
00693    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00694                      /*!< Up to three channels can be associated with this call */
00695 
00696    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00697    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00698    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00699 
00700    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00701    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00702    int inconference;          /*!< If our real should be in the conference */
00703 
00704    int bufsize;                /*!< Size of the buffers */
00705    int buf_no;             /*!< Number of buffers */
00706    int buf_policy;            /*!< Buffer policy */
00707    int faxbuf_no;              /*!< Number of Fax buffers */
00708    int faxbuf_policy;          /*!< Fax buffer policy */
00709    int sig;             /*!< Signalling style */
00710    /*!
00711     * \brief Nonzero if the signaling type is sent over a radio.
00712     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00713     */
00714    int radio;
00715    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00716    int oprmode;               /*!< "Operator Services" mode */
00717    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00718    /*! \brief Amount of gain to increase during caller id */
00719    float cid_rxgain;
00720    /*! \brief Rx gain set by chan_dahdi.conf */
00721    float rxgain;
00722    /*! \brief Tx gain set by chan_dahdi.conf */
00723    float txgain;
00724 
00725    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00726    float rxdrc;
00727    
00728    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00729    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00730    struct dahdi_pvt *next;          /*!< Next channel in list */
00731    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00732 
00733    /* flags */
00734 
00735    /*!
00736     * \brief TRUE if ADSI (Analog Display Services Interface) available
00737     * \note Set from the "adsi" value read in from chan_dahdi.conf
00738     */
00739    unsigned int adsi:1;
00740    /*!
00741     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00742     * call is answered by the remote party.
00743     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00744     */
00745    unsigned int answeronpolarityswitch:1;
00746    /*!
00747     * \brief TRUE if busy detection is enabled.
00748     * (Listens for the beep-beep busy pattern.)
00749     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00750     */
00751    unsigned int busydetect:1;
00752    /*!
00753     * \brief TRUE if call return is enabled.
00754     * (*69, if your dialplan doesn't catch this first)
00755     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00756     */
00757    unsigned int callreturn:1;
00758    /*!
00759     * \brief TRUE if busy extensions will hear the call-waiting tone
00760     * and can use hook-flash to switch between callers.
00761     * \note Can be disabled by dialing *70.
00762     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00763     */
00764    unsigned int callwaiting:1;
00765    /*!
00766     * \brief TRUE if send caller ID for Call Waiting
00767     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00768     */
00769    unsigned int callwaitingcallerid:1;
00770    /*!
00771     * \brief TRUE if support for call forwarding enabled.
00772     * Dial *72 to enable call forwarding.
00773     * Dial *73 to disable call forwarding.
00774     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00775     */
00776    unsigned int cancallforward:1;
00777    /*!
00778     * \brief TRUE if support for call parking is enabled.
00779     * \note Set from the "canpark" value read in from chan_dahdi.conf
00780     */
00781    unsigned int canpark:1;
00782    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00783    unsigned int confirmanswer:1;
00784    /*!
00785     * \brief TRUE if the channel is to be destroyed on hangup.
00786     * (Used by pseudo channels.)
00787     */
00788    unsigned int destroy:1;
00789    unsigned int didtdd:1;           /*!< flag to say its done it once */
00790    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00791    unsigned int dialednone:1;
00792    /*!
00793     * \brief TRUE if in the process of dialing digits or sending something.
00794     * \note This is used as a receive squelch for ISDN until connected.
00795     */
00796    unsigned int dialing:1;
00797    /*! \brief TRUE if the transfer capability of the call is digital. */
00798    unsigned int digital:1;
00799    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00800    unsigned int dnd:1;
00801    /*! \brief XXX BOOLEAN Purpose??? */
00802    unsigned int echobreak:1;
00803    /*!
00804     * \brief TRUE if echo cancellation enabled when bridged.
00805     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00806     * \note Disabled if the echo canceller is not setup.
00807     */
00808    unsigned int echocanbridged:1;
00809    /*! \brief TRUE if echo cancellation is turned on. */
00810    unsigned int echocanon:1;
00811    /*! \brief TRUE if a fax tone has already been handled. */
00812    unsigned int faxhandled:1;
00813    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00814    unsigned int usefaxbuffers:1;
00815    /*! TRUE while buffer configuration override is in use */
00816    unsigned int bufferoverrideinuse:1;
00817    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00818    unsigned int firstradio:1;
00819    /*!
00820     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00821     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00822     */
00823    unsigned int hanguponpolarityswitch:1;
00824    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00825    unsigned int hardwaredtmf:1;
00826    /*!
00827     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00828     * \note Caller ID can be disabled by dialing *67.
00829     * \note Caller ID can be enabled by dialing *82.
00830     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00831     */
00832    unsigned int hidecallerid:1;
00833    /*!
00834     * \brief TRUE if hide just the name not the number for legacy PBX use.
00835     * \note Only applies to PRI channels.
00836     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00837     */
00838    unsigned int hidecalleridname:1;
00839    /*! \brief TRUE if DTMF detection is disabled. */
00840    unsigned int ignoredtmf:1;
00841    /*!
00842     * \brief TRUE if the channel should be answered immediately
00843     * without attempting to gather any digits.
00844     * \note Set from the "immediate" value read in from chan_dahdi.conf
00845     */
00846    unsigned int immediate:1;
00847    /*! \brief TRUE if in an alarm condition. */
00848    unsigned int inalarm:1;
00849    /*! \brief TRUE if TDD in MATE mode */
00850    unsigned int mate:1;
00851    /*! \brief TRUE if we originated the call leg. */
00852    unsigned int outgoing:1;
00853    /* unsigned int overlapdial:1;         unused and potentially confusing */
00854    /*!
00855     * \brief TRUE if busy extensions will hear the call-waiting tone
00856     * and can use hook-flash to switch between callers.
00857     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00858     */
00859    unsigned int permcallwaiting:1;
00860    /*!
00861     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00862     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00863     */
00864    unsigned int permhidecallerid:1;
00865    /*!
00866     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00867     * \note Set from the "priindication" value read in from chan_dahdi.conf
00868     */
00869    unsigned int priindication_oob:1;
00870    /*!
00871     * \brief TRUE if PRI B channels are always exclusively selected.
00872     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00873     */
00874    unsigned int priexclusive:1;
00875    /*!
00876     * \brief TRUE if we will pulse dial.
00877     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00878     */
00879    unsigned int pulse:1;
00880    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00881    unsigned int pulsedial:1;
00882    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00883    /*!
00884     * \brief TRUE if caller ID is restricted.
00885     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00886     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00887     */
00888    unsigned int restrictcid:1;
00889    /*!
00890     * \brief TRUE if three way calling is enabled
00891     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00892     */
00893    unsigned int threewaycalling:1;
00894    /*!
00895     * \brief TRUE if call transfer is enabled
00896     * \note For FXS ports (either direct analog or over T1/E1):
00897     *   Support flash-hook call transfer
00898     * \note For digital ports using ISDN PRI protocols:
00899     *   Support switch-side transfer (called 2BCT, RLT or other names)
00900     * \note Set from the "transfer" value read in from chan_dahdi.conf
00901     */
00902    unsigned int transfer:1;
00903    /*!
00904     * \brief TRUE if caller ID is used on this channel.
00905     * \note PRI and SS7 spans will save caller ID from the networking peer.
00906     * \note FXS ports will generate the caller ID spill.
00907     * \note FXO ports will listen for the caller ID spill.
00908     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00909     */
00910    unsigned int use_callerid:1;
00911    /*!
00912     * \brief TRUE if we will use the calling presentation setting
00913     * from the Asterisk channel for outgoing calls.
00914     * \note Only applies to PRI and SS7 channels.
00915     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00916     */
00917    unsigned int use_callingpres:1;
00918    /*!
00919     * \brief TRUE if distinctive rings are to be detected.
00920     * \note For FXO lines
00921     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00922     */
00923    unsigned int usedistinctiveringdetection:1;
00924    /*!
00925     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00926     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00927     */
00928    unsigned int dahditrcallerid:1;
00929    /*!
00930     * \brief TRUE if allowed to flash-transfer to busy channels.
00931     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00932     */
00933    unsigned int transfertobusy:1;
00934    /*!
00935     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00936     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00937     */
00938    unsigned int mwimonitor_neon:1;
00939    /*!
00940     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00941     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00942     */
00943    unsigned int mwimonitor_fsk:1;
00944    /*!
00945     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00946     * \note RPAS - Ring Pulse Alert Signal
00947     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00948     */
00949    unsigned int mwimonitor_rpas:1;
00950    /*! \brief TRUE if an MWI monitor thread is currently active */
00951    unsigned int mwimonitoractive:1;
00952    /*! \brief TRUE if a MWI message sending thread is active */
00953    unsigned int mwisendactive:1;
00954    /*!
00955     * \brief TRUE if channel is out of reset and ready
00956     * \note Set but not used.
00957     */
00958    unsigned int inservice:1;
00959    /*!
00960     * \brief TRUE if the channel is locally blocked.
00961     * \note Applies to SS7 and MFCR2 channels.
00962     */
00963    unsigned int locallyblocked:1;
00964    /*!
00965     * \brief TRUE if the channel is remotely blocked.
00966     * \note Applies to SS7 and MFCR2 channels.
00967     */
00968    unsigned int remotelyblocked:1;
00969    /*!
00970     * \brief TRUE if the channel alarms will be managed also as Span ones
00971     * \note Applies to all channels
00972     */
00973    unsigned int manages_span_alarms:1;
00974 
00975 #if defined(HAVE_PRI)
00976    struct sig_pri_span *pri;
00977    int logicalspan;
00978 #endif
00979    /*!
00980     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00981     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00982     */
00983    unsigned int use_smdi:1;
00984    struct mwisend_info mwisend_data;
00985    /*! \brief The SMDI interface to get SMDI messages from. */
00986    struct ast_smdi_interface *smdi_iface;
00987 
00988    /*! \brief Distinctive Ring data */
00989    struct dahdi_distRings drings;
00990 
00991    /*!
00992     * \brief The configured context for incoming calls.
00993     * \note The "context" string read in from chan_dahdi.conf
00994     */
00995    char context[AST_MAX_CONTEXT];
00996    /*!
00997     * \brief Saved context string.
00998     */
00999    char defcontext[AST_MAX_CONTEXT];
01000    /*! \brief Extension to use in the dialplan. */
01001    char exten[AST_MAX_EXTENSION];
01002    /*!
01003     * \brief Language configured for calls.
01004     * \note The "language" string read in from chan_dahdi.conf
01005     */
01006    char language[MAX_LANGUAGE];
01007    /*!
01008     * \brief The configured music-on-hold class to use for calls.
01009     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01010     */
01011    char mohinterpret[MAX_MUSICCLASS];
01012    /*!
01013     * \brief Suggested music-on-hold class for peer channel to use for calls.
01014     * \note The "mohsuggest" string read in from chan_dahdi.conf
01015     */
01016    char mohsuggest[MAX_MUSICCLASS];
01017    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01018 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01019    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01020    char cid_ani[AST_MAX_EXTENSION];
01021 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01022    /*! \brief Automatic Number Identification code from PRI */
01023    int cid_ani2;
01024    /*! \brief Caller ID number from an incoming call. */
01025    char cid_num[AST_MAX_EXTENSION];
01026    /*!
01027     * \brief Caller ID tag from incoming call
01028     * \note the "cid_tag" string read in from chan_dahdi.conf
01029     */
01030    char cid_tag[AST_MAX_EXTENSION];
01031    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01032    int cid_ton;
01033    /*! \brief Caller ID name from an incoming call. */
01034    char cid_name[AST_MAX_EXTENSION];
01035    /*! \brief Caller ID subaddress from an incoming call. */
01036    char cid_subaddr[AST_MAX_EXTENSION];
01037    char *origcid_num;            /*!< malloced original callerid */
01038    char *origcid_name;           /*!< malloced original callerid */
01039    /*! \brief Call waiting number. */
01040    char callwait_num[AST_MAX_EXTENSION];
01041    /*! \brief Call waiting name. */
01042    char callwait_name[AST_MAX_EXTENSION];
01043    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01044    char rdnis[AST_MAX_EXTENSION];
01045    /*! \brief Dialed Number Identifier */
01046    char dnid[AST_MAX_EXTENSION];
01047    /*!
01048     * \brief Bitmapped groups this belongs to.
01049     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01050     */
01051    ast_group_t group;
01052    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01053    int law_default;
01054    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01055    int law;
01056    int confno;             /*!< Our conference */
01057    int confusers;             /*!< Who is using our conference */
01058    int propconfno;               /*!< Propagated conference number */
01059    /*!
01060     * \brief Bitmapped call groups this belongs to.
01061     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01062     */
01063    ast_group_t callgroup;
01064    /*!
01065     * \brief Bitmapped pickup groups this belongs to.
01066     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01067     */
01068    ast_group_t pickupgroup;
01069    /*!
01070     * \brief Channel variable list with associated values to set when a channel is created.
01071     * \note The "setvar" strings read in from chan_dahdi.conf
01072     */
01073    struct ast_variable *vars;
01074    int channel;               /*!< Channel Number */
01075    int span;               /*!< Span number */
01076    time_t guardtime;          /*!< Must wait this much time before using for new call */
01077    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01078    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01079    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01080    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01081    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01082    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01083    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01084    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01085    /*! \brief Analog caller ID waveform sample buffer */
01086    unsigned char *cidspill;
01087    /*! \brief Position in the cidspill buffer to send out next. */
01088    int cidpos;
01089    /*! \brief Length of the cidspill buffer containing samples. */
01090    int cidlen;
01091    /*! \brief Ring timeout timer?? */
01092    int ringt;
01093    /*!
01094     * \brief Ring timeout base.
01095     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01096     */
01097    int ringt_base;
01098    /*!
01099     * \brief Number of most significant digits/characters to strip from the dialed number.
01100     * \note Feature is deprecated.  Use dialplan logic.
01101     * \note The characters are stripped before the PRI TON/NPI prefix
01102     * characters are processed.
01103     */
01104    int stripmsd;
01105    /*!
01106     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01107     * \note
01108     * After CAS is sent, the call waiting caller id will be sent if the phone
01109     * gives a positive reply.
01110     */
01111    int callwaitcas;
01112    /*! \brief Number of call waiting rings. */
01113    int callwaitrings;
01114    /*! \brief Echo cancel parameters. */
01115    struct {
01116       struct dahdi_echocanparams head;
01117       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01118    } echocancel;
01119    /*!
01120     * \brief Echo training time. 0 = disabled
01121     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01122     */
01123    int echotraining;
01124    /*! \brief Filled with 'w'.  XXX Purpose?? */
01125    char echorest[20];
01126    /*!
01127     * \brief Number of times to see "busy" tone before hanging up.
01128     * \note Set from the "busycount" value read in from chan_dahdi.conf
01129     */
01130    int busycount;
01131    /*!
01132     * \brief Length of "busy" tone on time.
01133     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01134     */
01135    int busy_tonelength;
01136    /*!
01137     * \brief Length of "busy" tone off time.
01138     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01139     */
01140    int busy_quietlength;
01141    /*!
01142     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01143     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01144     */
01145    int callprogress;
01146    /*!
01147     * \brief Number of milliseconds to wait for dialtone.
01148     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01149     */
01150    int waitfordialtone;
01151    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01152    struct timeval flashtime;        /*!< Last flash-hook time */
01153    /*! \brief Opaque DSP configuration structure. */
01154    struct ast_dsp *dsp;
01155    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01156    struct dahdi_dialoperation dop;
01157    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01158    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01159    char finaldial[64];
01160    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01161    int amaflags;              /*!< AMA Flags */
01162    struct tdd_state *tdd;           /*!< TDD flag */
01163    /*! \brief Accumulated call forwarding number. */
01164    char call_forward[AST_MAX_EXTENSION];
01165    /*!
01166     * \brief Voice mailbox location.
01167     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01168     */
01169    char mailbox[AST_MAX_EXTENSION];
01170    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01171    struct ast_event_sub *mwi_event_sub;
01172    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01173    char dialdest[256];
01174 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01175    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01176    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01177    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01178 #endif
01179    int distinctivering;          /*!< Which distinctivering to use */
01180    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01181    /*! \brief Holding place for event injected from outside normal operation. */
01182    int fake_event;
01183    /*!
01184     * \brief Minimal time period (ms) between the answer polarity
01185     * switch and hangup polarity switch.
01186     */
01187    int polarityonanswerdelay;
01188    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01189    struct timeval polaritydelaytv;
01190    /*!
01191     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01192     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01193     */
01194    int sendcalleridafter;
01195    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01196    int polarity;
01197    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01198    int dsp_features;
01199 #if defined(HAVE_SS7)
01200    /*! \brief SS7 control parameters */
01201    struct sig_ss7_linkset *ss7;
01202 #endif   /* defined(HAVE_SS7) */
01203 #ifdef HAVE_OPENR2
01204    struct dahdi_mfcr2 *mfcr2;
01205    openr2_chan_t *r2chan;
01206    openr2_calling_party_category_t mfcr2_recvd_category;
01207    openr2_calling_party_category_t mfcr2_category;
01208    int mfcr2_dnis_index;
01209    int mfcr2_ani_index;
01210    int mfcr2call:1;
01211    int mfcr2_answer_pending:1;
01212    int mfcr2_charge_calls:1;
01213    int mfcr2_allow_collect_calls:1;
01214    int mfcr2_forced_release:1;
01215    int mfcr2_dnis_matched:1;
01216    int mfcr2_call_accepted:1;
01217    int mfcr2_progress:1;
01218    int mfcr2_accept_on_offer:1;
01219 #endif
01220    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01221    char begindigit;
01222    /*! \brief TRUE if confrence is muted. */
01223    int muting;
01224    void *sig_pvt;
01225    struct ast_cc_config_params *cc_params;
01226    /* DAHDI channel names may differ greatly from the
01227     * string that was provided to an app such as Dial. We
01228     * need to save the original string passed to dahdi_request
01229     * for call completion purposes. This way, we can replicate
01230     * the original dialed string later.
01231     */
01232    char dialstring[AST_CHANNEL_NAME];
01233 };
01234 
01235 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01236    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01237    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01238    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01239    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01240    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01241    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01242    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01243    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01244    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01246    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01247    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01248    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01249    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01250    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01251    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01252    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01253    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01255    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01256    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01257    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01258    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01259    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01260    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01261    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01262    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01263    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01264    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01265    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01266    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01267    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01268    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01269    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01270    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01271    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01272    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01273    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01274    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01275    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01276    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01277    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01278    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01279    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01280    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01281    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01282    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01283    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01284    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01285    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01286    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01287    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01288    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01289    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01290    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01291    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01292    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01293    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01294    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01295    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01296    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01297    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01298    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01299    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01300    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01301    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01302    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01303 
01304 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01305 
01306 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01307 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01308 
01309 #if defined(HAVE_PRI)
01310 static struct dahdi_parms_pseudo {
01311    int buf_no;             /*!< Number of buffers */
01312    int buf_policy;            /*!< Buffer policy */
01313    int faxbuf_no;              /*!< Number of Fax buffers */
01314    int faxbuf_policy;          /*!< Fax buffer policy */
01315 } dahdi_pseudo_parms;
01316 #endif   /* defined(HAVE_PRI) */
01317 
01318 /*! \brief Channel configuration from chan_dahdi.conf .
01319  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01320  * Generally there is a field here for every possible configuration item.
01321  *
01322  * The state of fields is saved along the parsing and whenever a 'channel'
01323  * statement is reached, the current dahdi_chan_conf is used to configure the
01324  * channel (struct dahdi_pvt)
01325  *
01326  * \see dahdi_chan_init for the default values.
01327  */
01328 struct dahdi_chan_conf {
01329    struct dahdi_pvt chan;
01330 #ifdef HAVE_PRI
01331    struct dahdi_pri pri;
01332 #endif
01333 
01334 #if defined(HAVE_SS7)
01335    struct dahdi_ss7 ss7;
01336 #endif   /* defined(HAVE_SS7) */
01337 
01338 #ifdef HAVE_OPENR2
01339    struct dahdi_mfcr2_conf mfcr2;
01340 #endif
01341    struct dahdi_params timing;
01342    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01343    /*! Continue configuration even if a channel is not there. */
01344    int ignore_failed_channels;
01345 
01346    /*!
01347     * \brief The serial port to listen for SMDI data on
01348     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01349     */
01350    char smdi_port[SMDI_MAX_FILENAME_LEN];
01351 };
01352 
01353 /*! returns a new dahdi_chan_conf with default values (by-value) */
01354 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01355 {
01356    /* recall that if a field is not included here it is initialized
01357     * to 0 or equivalent
01358     */
01359    struct dahdi_chan_conf conf = {
01360 #ifdef HAVE_PRI
01361       .pri.pri = {
01362          .nsf = PRI_NSF_NONE,
01363          .switchtype = PRI_SWITCH_NI2,
01364          .dialplan = PRI_UNKNOWN + 1,
01365          .localdialplan = PRI_NATIONAL_ISDN + 1,
01366          .nodetype = PRI_CPE,
01367          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01368 
01369 #if defined(HAVE_PRI_CCSS)
01370          .cc_ptmp_recall_mode = 1,/* specificRecall */
01371          .cc_qsig_signaling_link_req = 1,/* retain */
01372          .cc_qsig_signaling_link_rsp = 1,/* retain */
01373 #endif   /* defined(HAVE_PRI_CCSS) */
01374 
01375          .minunused = 2,
01376          .idleext = "",
01377          .idledial = "",
01378          .internationalprefix = "",
01379          .nationalprefix = "",
01380          .localprefix = "",
01381          .privateprefix = "",
01382          .unknownprefix = "",
01383          .resetinterval = -1,
01384       },
01385 #endif
01386 #if defined(HAVE_SS7)
01387       .ss7.ss7 = {
01388          .called_nai = SS7_NAI_NATIONAL,
01389          .calling_nai = SS7_NAI_NATIONAL,
01390          .internationalprefix = "",
01391          .nationalprefix = "",
01392          .subscriberprefix = "",
01393          .unknownprefix = ""
01394       },
01395 #endif   /* defined(HAVE_SS7) */
01396 #ifdef HAVE_OPENR2
01397       .mfcr2 = {
01398          .variant = OR2_VAR_ITU,
01399          .mfback_timeout = -1,
01400          .metering_pulse_timeout = -1,
01401          .max_ani = 10,
01402          .max_dnis = 4,
01403          .get_ani_first = -1,
01404 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01405          .skip_category_request = -1,
01406 #endif
01407          .call_files = 0,
01408          .allow_collect_calls = 0,
01409          .charge_calls = 1,
01410          .accept_on_offer = 1,
01411          .forced_release = 0,
01412          .double_answer = 0,
01413          .immediate_accept = -1,
01414          .logdir = "",
01415          .r2proto_file = "",
01416          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01417          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01418       },
01419 #endif
01420       .chan = {
01421          .context = "default",
01422          .cid_num = "",
01423          .cid_name = "",
01424          .cid_tag = "",
01425          .mohinterpret = "default",
01426          .mohsuggest = "",
01427          .parkinglot = "",
01428          .transfertobusy = 1,
01429 
01430          .cid_signalling = CID_SIG_BELL,
01431          .cid_start = CID_START_RING,
01432          .dahditrcallerid = 0,
01433          .use_callerid = 1,
01434          .sig = -1,
01435          .outsigmod = -1,
01436 
01437          .cid_rxgain = +5.0,
01438 
01439          .tonezone = -1,
01440 
01441          .echocancel.head.tap_length = 1,
01442 
01443          .busycount = 3,
01444 
01445          .accountcode = "",
01446 
01447          .mailbox = "",
01448 
01449 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01450          .mwisend_fsk = 1,
01451 #endif
01452          .polarityonanswerdelay = 600,
01453 
01454          .sendcalleridafter = DEFAULT_CIDRINGS,
01455 
01456          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01457          .buf_no = numbufs,
01458          .usefaxbuffers = 0,
01459          .cc_params = ast_cc_config_params_init(),
01460       },
01461       .timing = {
01462          .prewinktime = -1,
01463          .preflashtime = -1,
01464          .winktime = -1,
01465          .flashtime = -1,
01466          .starttime = -1,
01467          .rxwinktime = -1,
01468          .rxflashtime = -1,
01469          .debouncetime = -1
01470       },
01471       .is_sig_auto = 1,
01472       .smdi_port = "/dev/ttyS0",
01473    };
01474 
01475    return conf;
01476 }
01477 
01478 
01479 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01480 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01481 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01482 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01483 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01484 static int dahdi_hangup(struct ast_channel *ast);
01485 static int dahdi_answer(struct ast_channel *ast);
01486 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01487 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01488 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01489 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01490 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01491 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01492 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01493 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01494 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01495 static int dahdi_devicestate(void *data);
01496 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01497 
01498 static const struct ast_channel_tech dahdi_tech = {
01499    .type = "DAHDI",
01500    .description = tdesc,
01501    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01502    .requester = dahdi_request,
01503    .send_digit_begin = dahdi_digit_begin,
01504    .send_digit_end = dahdi_digit_end,
01505    .send_text = dahdi_sendtext,
01506    .call = dahdi_call,
01507    .hangup = dahdi_hangup,
01508    .answer = dahdi_answer,
01509    .read = dahdi_read,
01510    .write = dahdi_write,
01511    .bridge = dahdi_bridge,
01512    .exception = dahdi_exception,
01513    .indicate = dahdi_indicate,
01514    .fixup = dahdi_fixup,
01515    .setoption = dahdi_setoption,
01516    .queryoption = dahdi_queryoption,
01517    .func_channel_read = dahdi_func_read,
01518    .func_channel_write = dahdi_func_write,
01519    .devicestate = dahdi_devicestate,
01520    .cc_callback = dahdi_cc_callback,
01521 };
01522 
01523 #define GET_CHANNEL(p) ((p)->channel)
01524 
01525 #define SIG_PRI_LIB_HANDLE_CASES \
01526    SIG_PRI:                \
01527    case SIG_BRI:              \
01528    case SIG_BRI_PTMP
01529 
01530 /*!
01531  * \internal
01532  * \brief Determine if sig_pri handles the signaling.
01533  * \since 1.8
01534  *
01535  * \param signaling Signaling to determine if is for sig_pri.
01536  *
01537  * \return TRUE if the signaling is for sig_pri.
01538  */
01539 static inline int dahdi_sig_pri_lib_handles(int signaling)
01540 {
01541    int handles;
01542 
01543    switch (signaling) {
01544    case SIG_PRI_LIB_HANDLE_CASES:
01545       handles = 1;
01546       break;
01547    default:
01548       handles = 0;
01549       break;
01550    }
01551 
01552    return handles;
01553 }
01554 
01555 static int analog_lib_handles(int signalling, int radio, int oprmode)
01556 {
01557    switch (signalling) {
01558    case SIG_FXOLS:
01559    case SIG_FXOGS:
01560    case SIG_FXOKS:
01561    case SIG_FXSLS:
01562    case SIG_FXSGS:
01563    case SIG_FXSKS:
01564    case SIG_EMWINK:
01565    case SIG_EM:
01566    case SIG_EM_E1:
01567    case SIG_FEATD:
01568    case SIG_FEATDMF:
01569    case SIG_E911:
01570    case SIG_FGC_CAMA:
01571    case SIG_FGC_CAMAMF:
01572    case SIG_FEATB:
01573    case SIG_SFWINK:
01574    case SIG_SF:
01575    case SIG_SF_FEATD:
01576    case SIG_SF_FEATDMF:
01577    case SIG_FEATDMF_TA:
01578    case SIG_SF_FEATB:
01579       break;
01580    default:
01581       /* The rest of the function should cover the remainder of signalling types */
01582       return 0;
01583    }
01584 
01585    if (radio) {
01586       return 0;
01587    }
01588 
01589    if (oprmode) {
01590       return 0;
01591    }
01592 
01593    return 1;
01594 }
01595 
01596 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01597 {
01598    switch (sig) {
01599    case SIG_FXOLS:
01600       return ANALOG_SIG_FXOLS;
01601    case SIG_FXOGS:
01602       return ANALOG_SIG_FXOGS;
01603    case SIG_FXOKS:
01604       return ANALOG_SIG_FXOKS;
01605    case SIG_FXSLS:
01606       return ANALOG_SIG_FXSLS;
01607    case SIG_FXSGS:
01608       return ANALOG_SIG_FXSGS;
01609    case SIG_FXSKS:
01610       return ANALOG_SIG_FXSKS;
01611    case SIG_EMWINK:
01612       return ANALOG_SIG_EMWINK;
01613    case SIG_EM:
01614       return ANALOG_SIG_EM;
01615    case SIG_EM_E1:
01616       return ANALOG_SIG_EM_E1;
01617    case SIG_FEATD:
01618       return ANALOG_SIG_FEATD;
01619    case SIG_FEATDMF:
01620       return ANALOG_SIG_FEATDMF;
01621    case SIG_E911:
01622       return SIG_E911;
01623    case SIG_FGC_CAMA:
01624       return ANALOG_SIG_FGC_CAMA;
01625    case SIG_FGC_CAMAMF:
01626       return ANALOG_SIG_FGC_CAMAMF;
01627    case SIG_FEATB:
01628       return ANALOG_SIG_FEATB;
01629    case SIG_SFWINK:
01630       return ANALOG_SIG_SFWINK;
01631    case SIG_SF:
01632       return ANALOG_SIG_SF;
01633    case SIG_SF_FEATD:
01634       return ANALOG_SIG_SF_FEATD;
01635    case SIG_SF_FEATDMF:
01636       return ANALOG_SIG_SF_FEATDMF;
01637    case SIG_FEATDMF_TA:
01638       return ANALOG_SIG_FEATDMF_TA;
01639    case SIG_SF_FEATB:
01640       return ANALOG_SIG_FEATB;
01641    default:
01642       return -1;
01643    }
01644 }
01645 
01646 
01647 static int analog_tone_to_dahditone(enum analog_tone tone)
01648 {
01649    switch (tone) {
01650    case ANALOG_TONE_RINGTONE:
01651       return DAHDI_TONE_RINGTONE;
01652    case ANALOG_TONE_STUTTER:
01653       return DAHDI_TONE_STUTTER;
01654    case ANALOG_TONE_CONGESTION:
01655       return DAHDI_TONE_CONGESTION;
01656    case ANALOG_TONE_DIALTONE:
01657       return DAHDI_TONE_DIALTONE;
01658    case ANALOG_TONE_DIALRECALL:
01659       return DAHDI_TONE_DIALRECALL;
01660    case ANALOG_TONE_INFO:
01661       return DAHDI_TONE_INFO;
01662    default:
01663       return -1;
01664    }
01665 }
01666 
01667 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01668 {
01669    int index;
01670 
01671    switch (analogsub) {
01672    case ANALOG_SUB_REAL:
01673       index = SUB_REAL;
01674       break;
01675    case ANALOG_SUB_CALLWAIT:
01676       index = SUB_CALLWAIT;
01677       break;
01678    case ANALOG_SUB_THREEWAY:
01679       index = SUB_THREEWAY;
01680       break;
01681    default:
01682       ast_log(LOG_ERROR, "Unidentified sub!\n");
01683       index = SUB_REAL;
01684    }
01685 
01686    return index;
01687 }
01688 
01689 static enum analog_event dahdievent_to_analogevent(int event);
01690 static int bump_gains(struct dahdi_pvt *p);
01691 static int dahdi_setlinear(int dfd, int linear);
01692 
01693 static int my_start_cid_detect(void *pvt, int cid_signalling)
01694 {
01695    struct dahdi_pvt *p = pvt;
01696    int index = SUB_REAL;
01697    p->cs = callerid_new(cid_signalling);
01698    if (!p->cs) {
01699       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01700       return -1;
01701    }
01702    bump_gains(p);
01703    dahdi_setlinear(p->subs[index].dfd, 0);
01704 
01705    return 0;
01706 }
01707 
01708 static int my_stop_cid_detect(void *pvt)
01709 {
01710    struct dahdi_pvt *p = pvt;
01711    int index = SUB_REAL;
01712    if (p->cs)
01713       callerid_free(p->cs);
01714    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01715    return 0;
01716 }
01717 
01718 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01719 {
01720    struct dahdi_pvt *p = pvt;
01721    struct analog_pvt *analog_p = p->sig_pvt;
01722    struct pollfd poller;
01723    char *name, *num;
01724    int index = SUB_REAL;
01725    int res;
01726    unsigned char buf[256];
01727    int flags;
01728 
01729    poller.fd = p->subs[SUB_REAL].dfd;
01730    poller.events = POLLPRI | POLLIN;
01731    poller.revents = 0;
01732 
01733    res = poll(&poller, 1, timeout);
01734 
01735    if (poller.revents & POLLPRI) {
01736       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01737       return 1;
01738    }
01739 
01740    if (poller.revents & POLLIN) {
01741       /*** NOTES ***/
01742       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01743        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01744        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01745        * a failure and die, and returning 2 means no event was received. */
01746       res = read(p->subs[index].dfd, buf, sizeof(buf));
01747       if (res < 0) {
01748          if (errno != ELAST) {
01749             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01750             callerid_free(p->cs);
01751             return -1;
01752          }
01753       }
01754 
01755       if (analog_p->ringt > 0) {
01756          if (!(--analog_p->ringt)) {
01757             /* only return if we timeout from a ring event */
01758             return -1;
01759          }
01760       }
01761 
01762       if (p->cid_signalling == CID_SIG_V23_JP) {
01763          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01764       } else {
01765          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01766       }
01767       if (res < 0) {
01768          /*
01769           * The previous diagnostic message output likely
01770           * explains why it failed.
01771           */
01772          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01773          return -1;
01774       }
01775 
01776       if (res == 1) {
01777          callerid_get(p->cs, &name, &num, &flags);
01778          if (name)
01779             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01780          if (num)
01781             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01782 
01783          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01784          return 0;
01785       }
01786    }
01787 
01788    *ev = ANALOG_EVENT_NONE;
01789    return 2;
01790 }
01791 
01792 static const char *event2str(int event);
01793 static int restore_gains(struct dahdi_pvt *p);
01794 
01795 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01796 {
01797    unsigned char buf[256];
01798    int distMatches;
01799    int curRingData[RING_PATTERNS];
01800    int receivedRingT;
01801    int counter1;
01802    int counter;
01803    int i;
01804    int res;
01805    int checkaftercid = 0;
01806 
01807    struct dahdi_pvt *p = pvt;
01808    struct analog_pvt *analog_p = p->sig_pvt;
01809 
01810    if (ringdata == NULL) {
01811       ringdata = curRingData;
01812    } else {
01813       checkaftercid = 1;
01814    }
01815 
01816    /* We must have a ring by now, so, if configured, lets try to listen for
01817     * distinctive ringing */
01818    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01819       /* Clear the current ring data array so we don't have old data in it. */
01820       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01821          ringdata[receivedRingT] = 0;
01822       receivedRingT = 0;
01823       if (checkaftercid && distinctiveringaftercid)
01824          ast_verb(3, "Detecting post-CID distinctive ring\n");
01825       /* Check to see if context is what it should be, if not set to be. */
01826       else if (strcmp(p->context,p->defcontext) != 0) {
01827          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01828          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01829       }
01830 
01831       for (;;) {
01832          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01833          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01834             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01835             ast_hangup(chan);
01836             return 1;
01837          }
01838          if (i & DAHDI_IOMUX_SIGEVENT) {
01839             res = dahdi_get_event(p->subs[idx].dfd);
01840             if (res == DAHDI_EVENT_NOALARM) {
01841                p->inalarm = 0;
01842                analog_p->inalarm = 0;
01843             }
01844             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01845             res = 0;
01846             /* Let us detect distinctive ring */
01847 
01848             ringdata[receivedRingT] = analog_p->ringt;
01849 
01850             if (analog_p->ringt < analog_p->ringt_base/2)
01851                break;
01852             /* Increment the ringT counter so we can match it against
01853                values in chan_dahdi.conf for distinctive ring */
01854             if (++receivedRingT == RING_PATTERNS)
01855                break;
01856          } else if (i & DAHDI_IOMUX_READ) {
01857             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01858             if (res < 0) {
01859                if (errno != ELAST) {
01860                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01861                   ast_hangup(chan);
01862                   return 1;
01863                }
01864                break;
01865             }
01866             if (analog_p->ringt > 0) {
01867                if (!(--analog_p->ringt)) {
01868                   res = -1;
01869                   break;
01870                }
01871             }
01872          }
01873       }
01874    }
01875    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01876       /* this only shows up if you have n of the dring patterns filled in */
01877       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01878       for (counter = 0; counter < 3; counter++) {
01879       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01880          distMatches = 0;
01881          /* this only shows up if you have n of the dring patterns filled in */
01882          ast_verb(3, "Checking %d,%d,%d\n",
01883                p->drings.ringnum[counter].ring[0],
01884                p->drings.ringnum[counter].ring[1],
01885                p->drings.ringnum[counter].ring[2]);
01886          for (counter1 = 0; counter1 < 3; counter1++) {
01887             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01888             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01889                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01890                ringdata[counter1]);
01891                distMatches++;
01892             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01893                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01894                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01895                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01896                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01897                distMatches++;
01898             }
01899          }
01900 
01901          if (distMatches == 3) {
01902             /* The ring matches, set the context to whatever is for distinctive ring.. */
01903             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01904             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01905             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01906             break;
01907          }
01908       }
01909    }
01910    /* Restore linear mode (if appropriate) for Caller*ID processing */
01911    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01912    restore_gains(p);
01913 
01914    return 0;
01915 }
01916 
01917 static int my_stop_callwait(void *pvt)
01918 {
01919    struct dahdi_pvt *p = pvt;
01920    p->callwaitingrepeat = 0;
01921    p->cidcwexpire = 0;
01922    p->cid_suppress_expire = 0;
01923 
01924    return 0;
01925 }
01926 
01927 static int send_callerid(struct dahdi_pvt *p);
01928 static int save_conference(struct dahdi_pvt *p);
01929 static int restore_conference(struct dahdi_pvt *p);
01930 
01931 static int my_callwait(void *pvt)
01932 {
01933    struct dahdi_pvt *p = pvt;
01934    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01935    if (p->cidspill) {
01936       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01937       ast_free(p->cidspill);
01938    }
01939 
01940    /*
01941     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01942     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01943     */
01944    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01945       return -1;
01946    save_conference(p);
01947    /* Silence */
01948    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01949    if (!p->callwaitrings && p->callwaitingcallerid) {
01950       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01951       p->callwaitcas = 1;
01952       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01953    } else {
01954       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01955       p->callwaitcas = 0;
01956       p->cidlen = 2400 + READ_SIZE * 4;
01957    }
01958    p->cidpos = 0;
01959    send_callerid(p);
01960 
01961    return 0;
01962 }
01963 
01964 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01965 {
01966    struct dahdi_pvt *p = pvt;
01967 
01968    ast_debug(2, "Starting cid spill\n");
01969 
01970    if (p->cidspill) {
01971       ast_log(LOG_WARNING, "cidspill already exists??\n");
01972       ast_free(p->cidspill);
01973    }
01974 
01975    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01976       if (cwcid == 0) {
01977          p->cidlen = ast_callerid_generate(p->cidspill,
01978             caller->id.name.str,
01979             caller->id.number.str,
01980             AST_LAW(p));
01981       } else {
01982          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01983             caller->id.name.str, caller->id.number.str);
01984          p->callwaitcas = 0;
01985          p->cidcwexpire = 0;
01986          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01987             caller->id.name.str,
01988             caller->id.number.str,
01989             AST_LAW(p));
01990          p->cidlen += READ_SIZE * 4;
01991       }
01992       p->cidpos = 0;
01993       p->cid_suppress_expire = 0;
01994       send_callerid(p);
01995    }
01996    return 0;
01997 }
01998 
01999 static int my_dsp_reset_and_flush_digits(void *pvt)
02000 {
02001    struct dahdi_pvt *p = pvt;
02002    if (p->dsp)
02003       ast_dsp_digitreset(p->dsp);
02004 
02005    return 0;
02006 }
02007 
02008 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02009 {
02010    struct dahdi_pvt *p = pvt;
02011 
02012    if (p->channel == CHAN_PSEUDO)
02013       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02014 
02015    if (mode == ANALOG_DIGITMODE_DTMF) {
02016       /* If we do hardware dtmf, no need for a DSP */
02017       if (p->hardwaredtmf) {
02018          if (p->dsp) {
02019             ast_dsp_free(p->dsp);
02020             p->dsp = NULL;
02021          }
02022          return 0;
02023       }
02024 
02025       if (!p->dsp) {
02026          p->dsp = ast_dsp_new();
02027          if (!p->dsp) {
02028             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029             return -1;
02030          }
02031       }
02032 
02033       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02034    } else if (mode == ANALOG_DIGITMODE_MF) {
02035       if (!p->dsp) {
02036          p->dsp = ast_dsp_new();
02037          if (!p->dsp) {
02038             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02039             return -1;
02040          }
02041       }
02042       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02043    }
02044    return 0;
02045 }
02046 
02047 static int dahdi_wink(struct dahdi_pvt *p, int index);
02048 
02049 static int my_wink(void *pvt, enum analog_sub sub)
02050 {
02051    struct dahdi_pvt *p = pvt;
02052    int index = analogsub_to_dahdisub(sub);
02053    if (index != SUB_REAL) {
02054       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02055    }
02056    return dahdi_wink(p, index);
02057 }
02058 
02059 static void wakeup_sub(struct dahdi_pvt *p, int a);
02060 
02061 static int reset_conf(struct dahdi_pvt *p);
02062 
02063 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02064 
02065 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02066 {
02067    struct ast_frame *f = *dest;
02068    struct dahdi_pvt *p = pvt;
02069    int idx = analogsub_to_dahdisub(analog_index);
02070 
02071    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02072       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02073       f->subclass.integer, f->subclass.integer, ast->name);
02074 
02075    if (f->subclass.integer == 'f') {
02076       if (f->frametype == AST_FRAME_DTMF_END) {
02077          /* Fax tone -- Handle and return NULL */
02078          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02079             /* If faxbuffers are configured, use them for the fax transmission */
02080             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02081                struct dahdi_bufferinfo bi = {
02082                   .txbufpolicy = p->faxbuf_policy,
02083                   .bufsize = p->bufsize,
02084                   .numbufs = p->faxbuf_no
02085                };
02086                int res;
02087 
02088                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02089                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02090                } else {
02091                   p->bufferoverrideinuse = 1;
02092                }
02093             }
02094             p->faxhandled = 1;
02095             if (p->dsp) {
02096                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02097                ast_dsp_set_features(p->dsp, p->dsp_features);
02098                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02099             }
02100             if (strcmp(ast->exten, "fax")) {
02101                const char *target_context = S_OR(ast->macrocontext, ast->context);
02102 
02103                /* We need to unlock 'ast' here because ast_exists_extension has the
02104                 * potential to start autoservice on the channel. Such action is prone
02105                 * to deadlock.
02106                 */
02107                ast_mutex_unlock(&p->lock);
02108                ast_channel_unlock(ast);
02109                if (ast_exists_extension(ast, target_context, "fax", 1,
02110                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02111                   ast_channel_lock(ast);
02112                   ast_mutex_lock(&p->lock);
02113                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02114                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02115                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02116                   if (ast_async_goto(ast, target_context, "fax", 1))
02117                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02118                } else {
02119                   ast_channel_lock(ast);
02120                   ast_mutex_lock(&p->lock);
02121                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02122                }
02123             } else {
02124                ast_debug(1, "Already in a fax extension, not redirecting\n");
02125             }
02126          } else {
02127             ast_debug(1, "Fax already handled\n");
02128          }
02129          dahdi_confmute(p, 0);
02130       }
02131       p->subs[idx].f.frametype = AST_FRAME_NULL;
02132       p->subs[idx].f.subclass.integer = 0;
02133       *dest = &p->subs[idx].f;
02134    }
02135 }
02136 
02137 static void my_lock_private(void *pvt)
02138 {
02139    struct dahdi_pvt *p = pvt;
02140    ast_mutex_lock(&p->lock);
02141 }
02142 
02143 static void my_unlock_private(void *pvt)
02144 {
02145    struct dahdi_pvt *p = pvt;
02146    ast_mutex_unlock(&p->lock);
02147 }
02148 
02149 static void my_deadlock_avoidance_private(void *pvt)
02150 {
02151    struct dahdi_pvt *p = pvt;
02152 
02153    DEADLOCK_AVOIDANCE(&p->lock);
02154 }
02155 
02156 /*!
02157  * \internal
02158  * \brief Post an AMI DAHDI channel association event.
02159  * \since 1.8
02160  *
02161  * \param p DAHDI private pointer
02162  * \param chan Channel associated with the private pointer
02163  *
02164  * \return Nothing
02165  */
02166 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02167 {
02168    char ch_name[20];
02169 
02170    if (p->channel < CHAN_PSEUDO) {
02171       /* No B channel */
02172       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02173    } else if (p->channel == CHAN_PSEUDO) {
02174       /* Pseudo channel */
02175       strcpy(ch_name, "pseudo");
02176    } else {
02177       /* Real channel */
02178       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02179    }
02180    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02181       "Channel: %s\r\n"
02182       "Uniqueid: %s\r\n"
02183       "DAHDISpan: %d\r\n"
02184       "DAHDIChannel: %s\r\n",
02185       chan->name,
02186       chan->uniqueid,
02187       p->span,
02188       ch_name);
02189 }
02190 
02191 #ifdef HAVE_PRI
02192 /*!
02193  * \internal
02194  * \brief Post an AMI DAHDI channel association event.
02195  * \since 1.8
02196  *
02197  * \param pvt DAHDI private pointer
02198  * \param chan Channel associated with the private pointer
02199  *
02200  * \return Nothing
02201  */
02202 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02203 {
02204    struct dahdi_pvt *p = pvt;
02205 
02206    dahdi_ami_channel_event(p, chan);
02207 }
02208 #endif
02209 
02210 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02211 *  returns the last value of the linear setting 
02212 */ 
02213 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02214 {
02215    struct dahdi_pvt *p = pvt;
02216    int oldval;
02217    int idx = analogsub_to_dahdisub(sub);
02218    
02219    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02220    oldval = p->subs[idx].linear;
02221    p->subs[idx].linear = linear_mode ? 1 : 0;
02222    return oldval;
02223 }
02224 
02225 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02226 {
02227    struct dahdi_pvt *p = pvt;
02228    int idx = analogsub_to_dahdisub(sub);
02229 
02230    p->subs[idx].inthreeway = inthreeway;
02231 }
02232 
02233 static int get_alarms(struct dahdi_pvt *p);
02234 static void handle_alarms(struct dahdi_pvt *p, int alms);
02235 static void my_get_and_handle_alarms(void *pvt)
02236 {
02237    int res;
02238    struct dahdi_pvt *p = pvt;
02239 
02240    res = get_alarms(p);
02241    handle_alarms(p, res);
02242 }
02243 
02244 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02245 {
02246    struct ast_channel *bridged = ast_bridged_channel(chan);
02247 
02248    if (bridged && bridged->tech == &dahdi_tech) {
02249       struct dahdi_pvt *p = bridged->tech_pvt;
02250 
02251       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02252          return p->sig_pvt;
02253       }
02254    }
02255    return NULL;
02256 }
02257 
02258 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02259 {
02260    struct dahdi_pvt *p = pvt;
02261    int dahdi_sub = analogsub_to_dahdisub(sub);
02262    return p->subs[dahdi_sub].dfd;
02263 }
02264 
02265 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02266 {
02267    struct dahdi_pvt *p = pvt;
02268 
02269    /* Choose proper cadence */
02270    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02271       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02272          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02273       *cid_rings = cidrings[p->distinctivering - 1];
02274    } else {
02275       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02276          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02277       *cid_rings = p->sendcalleridafter;
02278    }
02279 }
02280 
02281 static void my_set_alarm(void *pvt, int in_alarm)
02282 {
02283    struct dahdi_pvt *p = pvt;
02284 
02285    p->inalarm = in_alarm;
02286 }
02287 
02288 static void my_set_dialing(void *pvt, int is_dialing)
02289 {
02290    struct dahdi_pvt *p = pvt;
02291 
02292    p->dialing = is_dialing;
02293 }
02294 
02295 static void my_set_outgoing(void *pvt, int is_outgoing)
02296 {
02297    struct dahdi_pvt *p = pvt;
02298 
02299    p->outgoing = is_outgoing;
02300 }
02301 
02302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02303 static void my_set_digital(void *pvt, int is_digital)
02304 {
02305    struct dahdi_pvt *p = pvt;
02306 
02307    p->digital = is_digital;
02308 }
02309 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02310 
02311 #if defined(HAVE_SS7)
02312 static void my_set_inservice(void *pvt, int is_inservice)
02313 {
02314    struct dahdi_pvt *p = pvt;
02315 
02316    p->inservice = is_inservice;
02317 }
02318 #endif   /* defined(HAVE_SS7) */
02319 
02320 #if defined(HAVE_SS7)
02321 static void my_set_locallyblocked(void *pvt, int is_blocked)
02322 {
02323    struct dahdi_pvt *p = pvt;
02324 
02325    p->locallyblocked = is_blocked;
02326 }
02327 #endif   /* defined(HAVE_SS7) */
02328 
02329 #if defined(HAVE_SS7)
02330 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02331 {
02332    struct dahdi_pvt *p = pvt;
02333 
02334    p->remotelyblocked = is_blocked;
02335 }
02336 #endif   /* defined(HAVE_SS7) */
02337 
02338 static void my_set_ringtimeout(void *pvt, int ringt)
02339 {
02340    struct dahdi_pvt *p = pvt;
02341    p->ringt = ringt;
02342 }
02343 
02344 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02345 {
02346    struct dahdi_pvt *p = pvt;
02347 
02348    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02349       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02350       gettimeofday(&p->waitingfordt, NULL);
02351       ast_setstate(ast, AST_STATE_OFFHOOK);
02352    }
02353 }
02354 
02355 static int my_check_waitingfordt(void *pvt)
02356 {
02357    struct dahdi_pvt *p = pvt;
02358 
02359    if (p->waitingfordt.tv_usec) {
02360       return 1;
02361    }
02362 
02363    return 0;
02364 }
02365 
02366 static void my_set_confirmanswer(void *pvt, int flag)
02367 {
02368    struct dahdi_pvt *p = pvt;
02369    p->confirmanswer = flag;
02370 }
02371 
02372 static int my_check_confirmanswer(void *pvt)
02373 {
02374    struct dahdi_pvt *p = pvt;
02375    if (p->confirmanswer) {
02376       return 1;
02377    }
02378 
02379    return 0;
02380 }
02381 
02382 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02383 {
02384    struct dahdi_pvt *p = pvt;
02385 
02386    p->callwaiting = callwaiting_enable;
02387 }
02388 
02389 static void my_cancel_cidspill(void *pvt)
02390 {
02391    struct dahdi_pvt *p = pvt;
02392 
02393    ast_free(p->cidspill);
02394    p->cidspill = NULL;
02395    restore_conference(p);
02396 }
02397 
02398 static int my_confmute(void *pvt, int mute)
02399 {
02400    struct dahdi_pvt *p = pvt;
02401    return dahdi_confmute(p, mute);
02402 }
02403 
02404 static void my_set_pulsedial(void *pvt, int flag)
02405 {
02406    struct dahdi_pvt *p = pvt;
02407    p->pulsedial = flag;
02408 }
02409 
02410 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02411 {
02412    struct dahdi_pvt *p = pvt;
02413 
02414    p->owner = new_owner;
02415 }
02416 
02417 static const char *my_get_orig_dialstring(void *pvt)
02418 {
02419    struct dahdi_pvt *p = pvt;
02420 
02421    return p->dialstring;
02422 }
02423 
02424 static void my_increase_ss_count(void)
02425 {
02426    ast_mutex_lock(&ss_thread_lock);
02427    ss_thread_count++;
02428    ast_mutex_unlock(&ss_thread_lock);
02429 }
02430 
02431 static void my_decrease_ss_count(void)
02432 {
02433    ast_mutex_lock(&ss_thread_lock);
02434    ss_thread_count--;
02435    ast_cond_signal(&ss_thread_complete);
02436    ast_mutex_unlock(&ss_thread_lock);
02437 }
02438 
02439 static void my_all_subchannels_hungup(void *pvt)
02440 {
02441    struct dahdi_pvt *p = pvt;
02442    int res, law;
02443 
02444    p->faxhandled = 0;
02445    p->didtdd = 0;
02446 
02447    if (p->dsp) {
02448       ast_dsp_free(p->dsp);
02449       p->dsp = NULL;
02450    }
02451 
02452    p->law = p->law_default;
02453    law = p->law_default;
02454    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02455    if (res < 0)
02456       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02457 
02458    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02459 
02460 #if 1
02461    {
02462    int i;
02463    p->owner = NULL;
02464    /* Cleanup owners here */
02465    for (i = 0; i < 3; i++) {
02466       p->subs[i].owner = NULL;
02467    }
02468    }
02469 #endif
02470 
02471    reset_conf(p);
02472    if (num_restart_pending == 0) {
02473       restart_monitor();
02474    }
02475 }
02476 
02477 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02478 
02479 static int my_conf_del(void *pvt, enum analog_sub sub)
02480 {
02481    struct dahdi_pvt *p = pvt;
02482    int x = analogsub_to_dahdisub(sub);
02483 
02484    return conf_del(p, &p->subs[x], x);
02485 }
02486 
02487 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02488 
02489 static int my_conf_add(void *pvt, enum analog_sub sub)
02490 {
02491    struct dahdi_pvt *p = pvt;
02492    int x = analogsub_to_dahdisub(sub);
02493 
02494    return conf_add(p, &p->subs[x], x, 0);
02495 }
02496 
02497 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02498 
02499 static int my_complete_conference_update(void *pvt, int needconference)
02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int needconf = needconference;
02503    int x;
02504    int useslavenative;
02505    struct dahdi_pvt *slave = NULL;
02506 
02507    useslavenative = isslavenative(p, &slave);
02508 
02509    /* If we have a slave, add him to our conference now. or DAX
02510       if this is slave native */
02511    for (x = 0; x < MAX_SLAVES; x++) {
02512       if (p->slaves[x]) {
02513          if (useslavenative)
02514             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02515          else {
02516             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02517             needconf++;
02518          }
02519       }
02520    }
02521    /* If we're supposed to be in there, do so now */
02522    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02523       if (useslavenative)
02524          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02525       else {
02526          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02527          needconf++;
02528       }
02529    }
02530    /* If we have a master, add ourselves to his conference */
02531    if (p->master) {
02532       if (isslavenative(p->master, NULL)) {
02533          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02534       } else {
02535          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02536       }
02537    }
02538    if (!needconf) {
02539       /* Nobody is left (or should be left) in our conference.
02540          Kill it. */
02541       p->confno = -1;
02542    }
02543 
02544    return 0;
02545 }
02546 
02547 static int check_for_conference(struct dahdi_pvt *p);
02548 
02549 static int my_check_for_conference(void *pvt)
02550 {
02551    struct dahdi_pvt *p = pvt;
02552    return check_for_conference(p);
02553 }
02554 
02555 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)
02556 {
02557    struct dahdi_pvt *p = pvt;
02558    int da, db;
02559    int tchan;
02560    int tinthreeway;
02561 
02562    da = analogsub_to_dahdisub(a);
02563    db = analogsub_to_dahdisub(b);
02564 
02565    tchan = p->subs[da].chan;
02566    p->subs[da].chan = p->subs[db].chan;
02567    p->subs[db].chan = tchan;
02568 
02569    tinthreeway = p->subs[da].inthreeway;
02570    p->subs[da].inthreeway = p->subs[db].inthreeway;
02571    p->subs[db].inthreeway = tinthreeway;
02572 
02573    p->subs[da].owner = ast_a;
02574    p->subs[db].owner = ast_b;
02575 
02576    if (ast_a)
02577       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02578    if (ast_b)
02579       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02580 
02581    wakeup_sub(p, a);
02582    wakeup_sub(p, b);
02583 
02584    return;
02585 }
02586 
02587 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02588 
02589 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02590 {
02591    struct dahdi_pvt *p = pvt;
02592    int dsub = analogsub_to_dahdisub(sub);
02593 
02594    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02595 }
02596 
02597 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02598 static int dahdi_setlaw(int dfd, int law)
02599 {
02600    int res;
02601    res = ioctl(dfd, DAHDI_SETLAW, &law);
02602    if (res)
02603       return res;
02604    return 0;
02605 }
02606 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02607 
02608 #if defined(HAVE_PRI)
02609 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)
02610 {
02611    struct dahdi_pvt *p = pvt;
02612    int audio;
02613    int newlaw = -1;
02614 
02615    switch (p->sig) {
02616    case SIG_PRI_LIB_HANDLE_CASES:
02617       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02618          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02619          break;
02620       }
02621       /* Fall through */
02622    default:
02623       /* Set to audio mode at this point */
02624       audio = 1;
02625       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02626          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02627             p->channel, audio, strerror(errno));
02628       }
02629       break;
02630    }
02631 
02632    if (law != SIG_PRI_DEFLAW) {
02633       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02634    }
02635 
02636    ast_copy_string(p->exten, exten, sizeof(p->exten));
02637 
02638    switch (law) {
02639       case SIG_PRI_DEFLAW:
02640          newlaw = 0;
02641          break;
02642       case SIG_PRI_ALAW:
02643          newlaw = DAHDI_LAW_ALAW;
02644          break;
02645       case SIG_PRI_ULAW:
02646          newlaw = DAHDI_LAW_MULAW;
02647          break;
02648    }
02649    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02650 }
02651 #endif   /* defined(HAVE_PRI) */
02652 
02653 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02654 
02655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02656 /*!
02657  * \internal
02658  * \brief Open the PRI/SS7 channel media path.
02659  * \since 1.8
02660  *
02661  * \param p Channel private control structure.
02662  *
02663  * \return Nothing
02664  */
02665 static void my_pri_ss7_open_media(void *p)
02666 {
02667    struct dahdi_pvt *pvt = p;
02668    int res;
02669    int dfd;
02670    int set_val;
02671 
02672    dfd = pvt->subs[SUB_REAL].dfd;
02673 
02674    /* Open the media path. */
02675    set_val = 1;
02676    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02677    if (res < 0) {
02678       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02679          pvt->channel, strerror(errno));
02680    }
02681 
02682    /* Set correct companding law for this call. */
02683    res = dahdi_setlaw(dfd, pvt->law);
02684    if (res < 0) {
02685       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02686    }
02687 
02688    /* Set correct gain for this call. */
02689    if (pvt->digital) {
02690       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02691    } else {
02692       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02693          pvt->law);
02694    }
02695    if (res < 0) {
02696       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02697    }
02698 
02699    if (pvt->dsp_features && pvt->dsp) {
02700       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02701       pvt->dsp_features = 0;
02702    }
02703 }
02704 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02705 
02706 #if defined(HAVE_PRI)
02707 /*!
02708  * \internal
02709  * \brief Ask DAHDI to dial the given dial string.
02710  * \since 1.8.11
02711  *
02712  * \param p Channel private control structure.
02713  * \param dial_string String to pass to DAHDI to dial.
02714  *
02715  * \note The channel private lock needs to be held when calling.
02716  *
02717  * \return Nothing
02718  */
02719 static void my_pri_dial_digits(void *p, const char *dial_string)
02720 {
02721    struct dahdi_dialoperation zo = {
02722       .op = DAHDI_DIAL_OP_APPEND,
02723    };
02724    struct dahdi_pvt *pvt = p;
02725    int res;
02726 
02727    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02728    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02729    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02730    if (res) {
02731       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02732          pvt->channel, dial_string, strerror(errno));
02733    } else {
02734       pvt->dialing = 1;
02735    }
02736 }
02737 #endif   /* defined(HAVE_PRI) */
02738 
02739 static int unalloc_sub(struct dahdi_pvt *p, int x);
02740 
02741 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02742 {
02743    struct dahdi_pvt *p = pvt;
02744 
02745    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02746 }
02747 
02748 static int alloc_sub(struct dahdi_pvt *p, int x);
02749 
02750 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02751 {
02752    struct dahdi_pvt *p = pvt;
02753 
02754    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02755 }
02756 
02757 static int has_voicemail(struct dahdi_pvt *p);
02758 
02759 static int my_has_voicemail(void *pvt)
02760 {
02761    struct dahdi_pvt *p = pvt;
02762 
02763    return has_voicemail(p);
02764 }
02765 
02766 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02767 {
02768    struct dahdi_pvt *p = pvt;
02769    int index;
02770 
02771    index = analogsub_to_dahdisub(sub);
02772 
02773    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02774 }
02775 
02776 static enum analog_event dahdievent_to_analogevent(int event)
02777 {
02778    enum analog_event res;
02779 
02780    switch (event) {
02781    case DAHDI_EVENT_ONHOOK:
02782       res = ANALOG_EVENT_ONHOOK;
02783       break;
02784    case DAHDI_EVENT_RINGOFFHOOK:
02785       res = ANALOG_EVENT_RINGOFFHOOK;
02786       break;
02787    case DAHDI_EVENT_WINKFLASH:
02788       res = ANALOG_EVENT_WINKFLASH;
02789       break;
02790    case DAHDI_EVENT_ALARM:
02791       res = ANALOG_EVENT_ALARM;
02792       break;
02793    case DAHDI_EVENT_NOALARM:
02794       res = ANALOG_EVENT_NOALARM;
02795       break;
02796    case DAHDI_EVENT_DIALCOMPLETE:
02797       res = ANALOG_EVENT_DIALCOMPLETE;
02798       break;
02799    case DAHDI_EVENT_RINGERON:
02800       res = ANALOG_EVENT_RINGERON;
02801       break;
02802    case DAHDI_EVENT_RINGEROFF:
02803       res = ANALOG_EVENT_RINGEROFF;
02804       break;
02805    case DAHDI_EVENT_HOOKCOMPLETE:
02806       res = ANALOG_EVENT_HOOKCOMPLETE;
02807       break;
02808    case DAHDI_EVENT_PULSE_START:
02809       res = ANALOG_EVENT_PULSE_START;
02810       break;
02811    case DAHDI_EVENT_POLARITY:
02812       res = ANALOG_EVENT_POLARITY;
02813       break;
02814    case DAHDI_EVENT_RINGBEGIN:
02815       res = ANALOG_EVENT_RINGBEGIN;
02816       break;
02817    case DAHDI_EVENT_EC_DISABLED:
02818       res = ANALOG_EVENT_EC_DISABLED;
02819       break;
02820    case DAHDI_EVENT_REMOVED:
02821       res = ANALOG_EVENT_REMOVED;
02822       break;
02823    case DAHDI_EVENT_NEONMWI_ACTIVE:
02824       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02825       break;
02826    case DAHDI_EVENT_NEONMWI_INACTIVE:
02827       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02828       break;
02829 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02830    case DAHDI_EVENT_TX_CED_DETECTED:
02831       res = ANALOG_EVENT_TX_CED_DETECTED;
02832       break;
02833    case DAHDI_EVENT_RX_CED_DETECTED:
02834       res = ANALOG_EVENT_RX_CED_DETECTED;
02835       break;
02836    case DAHDI_EVENT_EC_NLP_DISABLED:
02837       res = ANALOG_EVENT_EC_NLP_DISABLED;
02838       break;
02839    case DAHDI_EVENT_EC_NLP_ENABLED:
02840       res = ANALOG_EVENT_EC_NLP_ENABLED;
02841       break;
02842 #endif
02843    case DAHDI_EVENT_PULSEDIGIT:
02844       res = ANALOG_EVENT_PULSEDIGIT;
02845       break;
02846    case DAHDI_EVENT_DTMFDOWN:
02847       res = ANALOG_EVENT_DTMFDOWN;
02848       break;
02849    case DAHDI_EVENT_DTMFUP:
02850       res = ANALOG_EVENT_DTMFUP;
02851       break;
02852    default:
02853       switch(event & 0xFFFF0000) {
02854       case DAHDI_EVENT_PULSEDIGIT:
02855       case DAHDI_EVENT_DTMFDOWN:
02856       case DAHDI_EVENT_DTMFUP:
02857          /* The event includes a digit number in the low word.
02858           * Converting it to a 'enum analog_event' would remove
02859           * that information. Thus it is returned as-is.
02860           */
02861          return event;
02862       }
02863 
02864       res = ANALOG_EVENT_ERROR;
02865       break;
02866    }
02867 
02868    return res;
02869 }
02870 
02871 static inline int dahdi_wait_event(int fd);
02872 
02873 static int my_wait_event(void *pvt)
02874 {
02875    struct dahdi_pvt *p = pvt;
02876 
02877    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02878 }
02879 
02880 static int my_get_event(void *pvt)
02881 {
02882    struct dahdi_pvt *p = pvt;
02883    int res;
02884 
02885    if (p->fake_event) {
02886       res = p->fake_event;
02887       p->fake_event = 0;
02888    } else
02889       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02890 
02891    return dahdievent_to_analogevent(res);
02892 }
02893 
02894 static int my_is_off_hook(void *pvt)
02895 {
02896    struct dahdi_pvt *p = pvt;
02897    int res;
02898    struct dahdi_params par;
02899 
02900    memset(&par, 0, sizeof(par));
02901 
02902    if (p->subs[SUB_REAL].dfd > -1)
02903       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02904    else {
02905       /* Assume not off hook on CVRS */
02906       res = 0;
02907       par.rxisoffhook = 0;
02908    }
02909    if (res) {
02910       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02911    }
02912 
02913    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02914       /* When "onhook" that means no battery on the line, and thus
02915       it is out of service..., if it's on a TDM card... If it's a channel
02916       bank, there is no telling... */
02917       return (par.rxbits > -1) || par.rxisoffhook;
02918    }
02919 
02920    return par.rxisoffhook;
02921 }
02922 
02923 static void dahdi_enable_ec(struct dahdi_pvt *p);
02924 static void dahdi_disable_ec(struct dahdi_pvt *p);
02925 
02926 static int my_set_echocanceller(void *pvt, int enable)
02927 {
02928    struct dahdi_pvt *p = pvt;
02929 
02930    if (enable)
02931       dahdi_enable_ec(p);
02932    else
02933       dahdi_disable_ec(p);
02934 
02935    return 0;
02936 }
02937 
02938 static int dahdi_ring_phone(struct dahdi_pvt *p);
02939 
02940 static int my_ring(void *pvt)
02941 {
02942    struct dahdi_pvt *p = pvt;
02943 
02944    return dahdi_ring_phone(p);
02945 }
02946 
02947 static int my_flash(void *pvt)
02948 {
02949    struct dahdi_pvt *p = pvt;
02950    int func = DAHDI_FLASH;
02951    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02952 }
02953 
02954 static inline int dahdi_set_hook(int fd, int hs);
02955 
02956 static int my_off_hook(void *pvt)
02957 {
02958    struct dahdi_pvt *p = pvt;
02959    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02960 }
02961 
02962 static void my_set_needringing(void *pvt, int value)
02963 {
02964    struct dahdi_pvt *p = pvt;
02965    p->subs[SUB_REAL].needringing = value;
02966 }
02967 
02968 static void my_set_polarity(void *pvt, int value)
02969 {
02970    struct dahdi_pvt *p = pvt;
02971 
02972    if (p->channel == CHAN_PSEUDO) {
02973       return;
02974    }
02975    p->polarity = value;
02976    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02977 }
02978 
02979 static void my_start_polarityswitch(void *pvt)
02980 {
02981    struct dahdi_pvt *p = pvt;
02982 
02983    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02984       my_set_polarity(pvt, 0);
02985    }
02986 }
02987 
02988 static void my_answer_polarityswitch(void *pvt)
02989 {
02990    struct dahdi_pvt *p = pvt;
02991 
02992    if (!p->answeronpolarityswitch) {
02993       return;
02994    }
02995 
02996    my_set_polarity(pvt, 1);
02997 }
02998 
02999 static void my_hangup_polarityswitch(void *pvt)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (!p->hanguponpolarityswitch) {
03004       return;
03005    }
03006 
03007    if (p->answeronpolarityswitch) {
03008       my_set_polarity(pvt, 0);
03009    } else {
03010       my_set_polarity(pvt, 1);
03011    }
03012 }
03013 
03014 static int my_start(void *pvt)
03015 {
03016    struct dahdi_pvt *p = pvt;
03017    int x = DAHDI_START;
03018 
03019    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03020 }
03021 
03022 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03023 {
03024    int index = analogsub_to_dahdisub(sub);
03025    int res;
03026    struct dahdi_pvt *p = pvt;
03027    struct dahdi_dialoperation ddop;
03028 
03029    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03030       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03031       return -1;
03032    }
03033 
03034    if (sub != ANALOG_SUB_REAL) {
03035       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03036          dop->dialstr, p->channel, sub);
03037       return -1;
03038    }
03039 
03040    ddop.op = DAHDI_DIAL_OP_REPLACE;
03041    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03042 
03043    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03044 
03045    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03046    if (res == -1) {
03047       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03048    }
03049 
03050    return res;
03051 }
03052 
03053 static void dahdi_train_ec(struct dahdi_pvt *p);
03054 
03055 static int my_train_echocanceller(void *pvt)
03056 {
03057    struct dahdi_pvt *p = pvt;
03058 
03059    dahdi_train_ec(p);
03060 
03061    return 0;
03062 }
03063 
03064 static int my_is_dialing(void *pvt, enum analog_sub sub)
03065 {
03066    struct dahdi_pvt *p = pvt;
03067    int index;
03068    int x;
03069 
03070    index = analogsub_to_dahdisub(sub);
03071 
03072    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03073       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03074       return -1;
03075    }
03076 
03077    return x;
03078 }
03079 
03080 static int my_on_hook(void *pvt)
03081 {
03082    struct dahdi_pvt *p = pvt;
03083    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03084 }
03085 
03086 #if defined(HAVE_PRI)
03087 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03088 {
03089    struct dahdi_pvt *old_chan = chan_old;
03090    struct dahdi_pvt *new_chan = chan_new;
03091 
03092    new_chan->owner = old_chan->owner;
03093    old_chan->owner = NULL;
03094    if (new_chan->owner) {
03095       new_chan->owner->tech_pvt = new_chan;
03096       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03097       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03098       old_chan->subs[SUB_REAL].owner = NULL;
03099    }
03100    /* Copy any DSP that may be present */
03101    new_chan->dsp = old_chan->dsp;
03102    new_chan->dsp_features = old_chan->dsp_features;
03103    old_chan->dsp = NULL;
03104    old_chan->dsp_features = 0;
03105 
03106    /* Transfer flags from the old channel. */
03107    new_chan->dialing = old_chan->dialing;
03108    new_chan->digital = old_chan->digital;
03109    new_chan->outgoing = old_chan->outgoing;
03110    old_chan->dialing = 0;
03111    old_chan->digital = 0;
03112    old_chan->outgoing = 0;
03113 
03114    /* More stuff to transfer to the new channel. */
03115    new_chan->law = old_chan->law;
03116    strcpy(new_chan->dialstring, old_chan->dialstring);
03117 }
03118 #endif   /* defined(HAVE_PRI) */
03119 
03120 #if defined(HAVE_PRI)
03121 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03122 {
03123    switch (tone) {
03124    case SIG_PRI_TONE_RINGTONE:
03125       return DAHDI_TONE_RINGTONE;
03126    case SIG_PRI_TONE_STUTTER:
03127       return DAHDI_TONE_STUTTER;
03128    case SIG_PRI_TONE_CONGESTION:
03129       return DAHDI_TONE_CONGESTION;
03130    case SIG_PRI_TONE_DIALTONE:
03131       return DAHDI_TONE_DIALTONE;
03132    case SIG_PRI_TONE_DIALRECALL:
03133       return DAHDI_TONE_DIALRECALL;
03134    case SIG_PRI_TONE_INFO:
03135       return DAHDI_TONE_INFO;
03136    case SIG_PRI_TONE_BUSY:
03137       return DAHDI_TONE_BUSY;
03138    default:
03139       return -1;
03140    }
03141 }
03142 #endif   /* defined(HAVE_PRI) */
03143 
03144 #if defined(HAVE_PRI)
03145 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03146 {
03147    int x;
03148 
03149    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03150    switch (x) {
03151    case DAHDI_EVENT_NONE:
03152       break;
03153    case DAHDI_EVENT_ALARM:
03154    case DAHDI_EVENT_NOALARM:
03155       if (sig_pri_is_alarm_ignored(pri)) {
03156          break;
03157       }
03158       /* Fall through */
03159    default:
03160       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03161          event2str(x), x, pri->span);
03162       break;
03163    }
03164    /* Keep track of alarm state */
03165    switch (x) {
03166    case DAHDI_EVENT_ALARM:
03167       pri_event_alarm(pri, index, 0);
03168       break;
03169    case DAHDI_EVENT_NOALARM:
03170       pri_event_noalarm(pri, index, 0);
03171       break;
03172    default:
03173       break;
03174    }
03175 }
03176 #endif   /* defined(HAVE_PRI) */
03177 
03178 #if defined(HAVE_PRI)
03179 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03180 {
03181    struct dahdi_pvt *p = pvt;
03182 
03183    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03184 }
03185 #endif   /* defined(HAVE_PRI) */
03186 
03187 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03188 /*!
03189  * \internal
03190  * \brief Set the caller id information.
03191  * \since 1.8
03192  *
03193  * \param pvt DAHDI private structure
03194  * \param caller Caller-id information to set.
03195  *
03196  * \return Nothing
03197  */
03198 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03199 {
03200    struct dahdi_pvt *p = pvt;
03201 
03202    ast_copy_string(p->cid_num,
03203       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03204       sizeof(p->cid_num));
03205    ast_copy_string(p->cid_name,
03206       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03207       sizeof(p->cid_name));
03208    ast_copy_string(p->cid_subaddr,
03209       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03210       sizeof(p->cid_subaddr));
03211    p->cid_ton = caller->id.number.plan;
03212    p->callingpres = ast_party_id_presentation(&caller->id);
03213    if (caller->id.tag) {
03214       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03215    }
03216    ast_copy_string(p->cid_ani,
03217       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03218       sizeof(p->cid_ani));
03219    p->cid_ani2 = caller->ani2;
03220 }
03221 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03222 
03223 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03224 /*!
03225  * \internal
03226  * \brief Set the Dialed Number Identifier.
03227  * \since 1.8
03228  *
03229  * \param pvt DAHDI private structure
03230  * \param dnid Dialed Number Identifier string.
03231  *
03232  * \return Nothing
03233  */
03234 static void my_set_dnid(void *pvt, const char *dnid)
03235 {
03236    struct dahdi_pvt *p = pvt;
03237 
03238    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03239 }
03240 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03241 
03242 #if defined(HAVE_PRI)
03243 /*!
03244  * \internal
03245  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03246  * \since 1.8
03247  *
03248  * \param pvt DAHDI private structure
03249  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03250  *
03251  * \return Nothing
03252  */
03253 static void my_set_rdnis(void *pvt, const char *rdnis)
03254 {
03255    struct dahdi_pvt *p = pvt;
03256 
03257    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03258 }
03259 #endif   /* defined(HAVE_PRI) */
03260 
03261 #if defined(HAVE_PRI)
03262 /*!
03263  * \internal
03264  * \brief Make a dialstring for native ISDN CC to recall properly.
03265  * \since 1.8
03266  *
03267  * \param priv Channel private control structure.
03268  * \param buf Where to put the modified dialstring.
03269  * \param buf_size Size of modified dialstring buffer.
03270  *
03271  * \details
03272  * original dialstring:
03273  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03274  *
03275  * The modified dialstring will have prefixed the channel-group section
03276  * with the ISDN channel restriction.
03277  *
03278  * buf:
03279  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03280  *
03281  * The routine will check to see if the ISDN channel restriction is already
03282  * in the original dialstring.
03283  *
03284  * \return Nothing
03285  */
03286 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03287 {
03288    char *dial;
03289    struct dahdi_pvt *pvt;
03290    AST_DECLARE_APP_ARGS(args,
03291       AST_APP_ARG(tech);   /* channel technology token */
03292       AST_APP_ARG(group);  /* channel/group token */
03293       //AST_APP_ARG(ext);  /* extension token */
03294       //AST_APP_ARG(opts); /* options token */
03295       //AST_APP_ARG(other);   /* Any remining unused arguments */
03296    );
03297 
03298    pvt = priv;
03299    dial = ast_strdupa(pvt->dialstring);
03300    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03301    if (!args.tech) {
03302       ast_copy_string(buf, pvt->dialstring, buf_size);
03303       return;
03304    }
03305    if (!args.group) {
03306       /* Append the ISDN span channel restriction to the dialstring. */
03307       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03308       return;
03309    }
03310    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03311       /* The ISDN span channel restriction is not needed or already
03312        * in the dialstring. */
03313       ast_copy_string(buf, pvt->dialstring, buf_size);
03314       return;
03315    }
03316    /* Insert the ISDN span channel restriction into the dialstring. */
03317    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03318 }
03319 #endif   /* defined(HAVE_PRI) */
03320 
03321 #if defined(HAVE_PRI)
03322 /*!
03323  * \internal
03324  * \brief Reevaluate the PRI span device state.
03325  * \since 1.8
03326  *
03327  * \param pri Asterisk D channel control structure.
03328  *
03329  * \return Nothing
03330  *
03331  * \note Assumes the pri->lock is already obtained.
03332  */
03333 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03334 {
03335    unsigned idx;
03336    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03337    unsigned in_use;     /* Number of B channels in use on the span. */
03338    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03339    enum ast_device_state new_state;
03340 
03341    /* Count the number of B channels and the number of B channels in use. */
03342    num_b_chans = 0;
03343    in_use = 0;
03344    in_alarm = 1;
03345    for (idx = pri->numchans; idx--;) {
03346       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03347          /* This is a B channel interface. */
03348          ++num_b_chans;
03349          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03350             ++in_use;
03351          }
03352          if (!pri->pvts[idx]->inalarm) {
03353             /* There is a channel that is not in alarm. */
03354             in_alarm = 0;
03355          }
03356       }
03357    }
03358 
03359    /* Update the span congestion device state and report any change. */
03360    if (in_alarm) {
03361       new_state = AST_DEVICE_UNAVAILABLE;
03362    } else {
03363       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03364    }
03365    if (pri->congestion_devstate != new_state) {
03366       pri->congestion_devstate = new_state;
03367       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03368    }
03369 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03370    /* Update the span threshold device state and report any change. */
03371    if (in_alarm) {
03372       new_state = AST_DEVICE_UNAVAILABLE;
03373    } else if (!in_use) {
03374       new_state = AST_DEVICE_NOT_INUSE;
03375    } else if (!pri->user_busy_threshold) {
03376       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03377    } else {
03378       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03379          : AST_DEVICE_BUSY;
03380    }
03381    if (pri->threshold_devstate != new_state) {
03382       pri->threshold_devstate = new_state;
03383       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03384    }
03385 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03386 }
03387 #endif   /* defined(HAVE_PRI) */
03388 
03389 #if defined(HAVE_PRI)
03390 /*!
03391  * \internal
03392  * \brief Reference this module.
03393  * \since 1.8
03394  *
03395  * \return Nothing
03396  */
03397 static void my_module_ref(void)
03398 {
03399    ast_module_ref(ast_module_info->self);
03400 }
03401 #endif   /* defined(HAVE_PRI) */
03402 
03403 #if defined(HAVE_PRI)
03404 /*!
03405  * \internal
03406  * \brief Unreference this module.
03407  * \since 1.8
03408  *
03409  * \return Nothing
03410  */
03411 static void my_module_unref(void)
03412 {
03413    ast_module_unref(ast_module_info->self);
03414 }
03415 #endif   /* defined(HAVE_PRI) */
03416 
03417 #if defined(HAVE_PRI)
03418 #if defined(HAVE_PRI_CALL_WAITING)
03419 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03420 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03421 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03422 
03423 static struct sig_pri_callback dahdi_pri_callbacks =
03424 {
03425    .handle_dchan_exception = my_handle_dchan_exception,
03426    .play_tone = my_pri_play_tone,
03427    .set_echocanceller = my_set_echocanceller,
03428    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03429    .lock_private = my_lock_private,
03430    .unlock_private = my_unlock_private,
03431    .new_ast_channel = my_new_pri_ast_channel,
03432    .fixup_chans = my_pri_fixup_chans,
03433    .set_alarm = my_set_alarm,
03434    .set_dialing = my_set_dialing,
03435    .set_outgoing = my_set_outgoing,
03436    .set_digital = my_set_digital,
03437    .set_callerid = my_set_callerid,
03438    .set_dnid = my_set_dnid,
03439    .set_rdnis = my_set_rdnis,
03440    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03441 #if defined(HAVE_PRI_CALL_WAITING)
03442    .init_config = my_pri_init_config,
03443 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03444    .get_orig_dialstring = my_get_orig_dialstring,
03445    .make_cc_dialstring = my_pri_make_cc_dialstring,
03446    .update_span_devstate = dahdi_pri_update_span_devstate,
03447    .module_ref = my_module_ref,
03448    .module_unref = my_module_unref,
03449    .dial_digits = my_pri_dial_digits,
03450    .open_media = my_pri_ss7_open_media,
03451    .ami_channel_event = my_ami_channel_event,
03452 };
03453 #endif   /* defined(HAVE_PRI) */
03454 
03455 #if defined(HAVE_SS7)
03456 /*!
03457  * \internal
03458  * \brief Handle the SS7 link exception.
03459  * \since 1.8
03460  *
03461  * \param linkset Controlling linkset for the channel.
03462  * \param which Link index of the signaling channel.
03463  *
03464  * \return Nothing
03465  */
03466 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03467 {
03468    int event;
03469 
03470    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03471       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03472          linkset->span, which);
03473       return;
03474    }
03475    switch (event) {
03476    case DAHDI_EVENT_NONE:
03477       break;
03478    case DAHDI_EVENT_ALARM:
03479       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03480          event2str(event), event, linkset->span, which);
03481       sig_ss7_link_alarm(linkset, which);
03482       break;
03483    case DAHDI_EVENT_NOALARM:
03484       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03485          event2str(event), event, linkset->span, which);
03486       sig_ss7_link_noalarm(linkset, which);
03487       break;
03488    default:
03489       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03490          event2str(event), event, linkset->span, which);
03491       break;
03492    }
03493 }
03494 #endif   /* defined(HAVE_SS7) */
03495 
03496 #if defined(HAVE_SS7)
03497 static void my_ss7_set_loopback(void *pvt, int enable)
03498 {
03499    struct dahdi_pvt *p = pvt;
03500 
03501    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03502       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03503          strerror(errno));
03504    }
03505 }
03506 #endif   /* defined(HAVE_SS7) */
03507 
03508 #if defined(HAVE_SS7)
03509 /*!
03510  * \internal
03511  * \brief Create a new asterisk channel structure for SS7.
03512  * \since 1.8
03513  *
03514  * \param pvt Private channel structure.
03515  * \param state Initial state of new channel.
03516  * \param law Combanding law to use.
03517  * \param exten Dialplan extension for incoming call.
03518  * \param requestor Channel requesting this new channel.
03519  *
03520  * \retval ast_channel on success.
03521  * \retval NULL on error.
03522  */
03523 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)
03524 {
03525    struct dahdi_pvt *p = pvt;
03526    int audio;
03527    int newlaw;
03528 
03529    /* Set to audio mode at this point */
03530    audio = 1;
03531    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03532       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03533          p->channel, audio, strerror(errno));
03534 
03535    if (law != SIG_SS7_DEFLAW) {
03536       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03537          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03538    }
03539 
03540    ast_copy_string(p->exten, exten, sizeof(p->exten));
03541 
03542    newlaw = -1;
03543    switch (law) {
03544    case SIG_SS7_DEFLAW:
03545       newlaw = 0;
03546       break;
03547    case SIG_SS7_ALAW:
03548       newlaw = DAHDI_LAW_ALAW;
03549       break;
03550    case SIG_SS7_ULAW:
03551       newlaw = DAHDI_LAW_MULAW;
03552       break;
03553    }
03554    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03555 }
03556 #endif   /* defined(HAVE_SS7) */
03557 
03558 #if defined(HAVE_SS7)
03559 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03560 {
03561    switch (tone) {
03562    case SIG_SS7_TONE_RINGTONE:
03563       return DAHDI_TONE_RINGTONE;
03564    case SIG_SS7_TONE_STUTTER:
03565       return DAHDI_TONE_STUTTER;
03566    case SIG_SS7_TONE_CONGESTION:
03567       return DAHDI_TONE_CONGESTION;
03568    case SIG_SS7_TONE_DIALTONE:
03569       return DAHDI_TONE_DIALTONE;
03570    case SIG_SS7_TONE_DIALRECALL:
03571       return DAHDI_TONE_DIALRECALL;
03572    case SIG_SS7_TONE_INFO:
03573       return DAHDI_TONE_INFO;
03574    case SIG_SS7_TONE_BUSY:
03575       return DAHDI_TONE_BUSY;
03576    default:
03577       return -1;
03578    }
03579 }
03580 #endif   /* defined(HAVE_SS7) */
03581 
03582 #if defined(HAVE_SS7)
03583 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03584 {
03585    struct dahdi_pvt *p = pvt;
03586 
03587    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03588 }
03589 #endif   /* defined(HAVE_SS7) */
03590 
03591 #if defined(HAVE_SS7)
03592 static struct sig_ss7_callback dahdi_ss7_callbacks =
03593 {
03594    .lock_private = my_lock_private,
03595    .unlock_private = my_unlock_private,
03596 
03597    .set_echocanceller = my_set_echocanceller,
03598    .set_loopback = my_ss7_set_loopback,
03599 
03600    .new_ast_channel = my_new_ss7_ast_channel,
03601    .play_tone = my_ss7_play_tone,
03602 
03603    .handle_link_exception = my_handle_link_exception,
03604    .set_alarm = my_set_alarm,
03605    .set_dialing = my_set_dialing,
03606    .set_outgoing = my_set_outgoing,
03607    .set_digital = my_set_digital,
03608    .set_inservice = my_set_inservice,
03609    .set_locallyblocked = my_set_locallyblocked,
03610    .set_remotelyblocked = my_set_remotelyblocked,
03611    .set_callerid = my_set_callerid,
03612    .set_dnid = my_set_dnid,
03613    .open_media = my_pri_ss7_open_media,
03614 };
03615 #endif   /* defined(HAVE_SS7) */
03616 
03617 /*!
03618  * \brief Send MWI state change
03619  *
03620  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03621  *      MWI state has changed on.
03622  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03623  *      whether there are messages waiting or not.
03624  *
03625  *  \return nothing
03626  *
03627  * This function does two things:
03628  *
03629  * 1) It generates an internal Asterisk event notifying any other module that
03630  *    cares about MWI that the state of a mailbox has changed.
03631  *
03632  * 2) It runs the script specified by the mwimonitornotify option to allow
03633  *    some custom handling of the state change.
03634  */
03635 static void notify_message(char *mailbox_full, int thereornot)
03636 {
03637    char s[sizeof(mwimonitornotify) + 80];
03638    struct ast_event *event;
03639    char *mailbox, *context;
03640 
03641    /* Strip off @default */
03642    context = mailbox = ast_strdupa(mailbox_full);
03643    strsep(&context, "@");
03644    if (ast_strlen_zero(context))
03645       context = "default";
03646 
03647    if (!(event = ast_event_new(AST_EVENT_MWI,
03648          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03649          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03650          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03651          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03652          AST_EVENT_IE_END))) {
03653       return;
03654    }
03655 
03656    ast_event_queue_and_cache(event);
03657 
03658    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03659       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03660       ast_safe_system(s);
03661    }
03662 }
03663 
03664 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03665 {
03666    struct dahdi_pvt *p = pvt;
03667 
03668    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03669       return;
03670 
03671    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03672       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03673       notify_message(p->mailbox, 1);
03674    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03675       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03676       notify_message(p->mailbox, 0);
03677    }
03678    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03679    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03680    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03681       ast_hangup(chan);
03682       return;
03683    }
03684 }
03685 
03686 static int my_have_progressdetect(void *pvt)
03687 {
03688    struct dahdi_pvt *p = pvt;
03689 
03690    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03691       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03692       return 1;
03693    } else {
03694       /* Don't have progress detection. */
03695       return 0;
03696    }
03697 }
03698 
03699 static struct analog_callback dahdi_analog_callbacks =
03700 {
03701    .play_tone = my_play_tone,
03702    .get_event = my_get_event,
03703    .wait_event = my_wait_event,
03704    .is_off_hook = my_is_off_hook,
03705    .set_echocanceller = my_set_echocanceller,
03706    .ring = my_ring,
03707    .flash = my_flash,
03708    .off_hook = my_off_hook,
03709    .dial_digits = my_dial_digits,
03710    .train_echocanceller = my_train_echocanceller,
03711    .on_hook = my_on_hook,
03712    .is_dialing = my_is_dialing,
03713    .allocate_sub = my_allocate_sub,
03714    .unallocate_sub = my_unallocate_sub,
03715    .swap_subs = my_swap_subchannels,
03716    .has_voicemail = my_has_voicemail,
03717    .check_for_conference = my_check_for_conference,
03718    .conf_add = my_conf_add,
03719    .conf_del = my_conf_del,
03720    .complete_conference_update = my_complete_conference_update,
03721    .start = my_start,
03722    .all_subchannels_hungup = my_all_subchannels_hungup,
03723    .lock_private = my_lock_private,
03724    .unlock_private = my_unlock_private,
03725    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03726    .handle_dtmf = my_handle_dtmf,
03727    .wink = my_wink,
03728    .new_ast_channel = my_new_analog_ast_channel,
03729    .dsp_set_digitmode = my_dsp_set_digitmode,
03730    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03731    .send_callerid = my_send_callerid,
03732    .callwait = my_callwait,
03733    .stop_callwait = my_stop_callwait,
03734    .get_callerid = my_get_callerid,
03735    .start_cid_detect = my_start_cid_detect,
03736    .stop_cid_detect = my_stop_cid_detect,
03737    .handle_notify_message = my_handle_notify_message,
03738    .increase_ss_count = my_increase_ss_count,
03739    .decrease_ss_count = my_decrease_ss_count,
03740    .distinctive_ring = my_distinctive_ring,
03741    .set_linear_mode = my_set_linear_mode,
03742    .set_inthreeway = my_set_inthreeway,
03743    .get_and_handle_alarms = my_get_and_handle_alarms,
03744    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03745    .get_sub_fd = my_get_sub_fd,
03746    .set_cadence = my_set_cadence,
03747    .set_alarm = my_set_alarm,
03748    .set_dialing = my_set_dialing,
03749    .set_outgoing = my_set_outgoing,
03750    .set_ringtimeout = my_set_ringtimeout,
03751    .set_waitingfordt = my_set_waitingfordt,
03752    .check_waitingfordt = my_check_waitingfordt,
03753    .set_confirmanswer = my_set_confirmanswer,
03754    .check_confirmanswer = my_check_confirmanswer,
03755    .set_callwaiting = my_set_callwaiting,
03756    .cancel_cidspill = my_cancel_cidspill,
03757    .confmute = my_confmute,
03758    .set_pulsedial = my_set_pulsedial,
03759    .set_new_owner = my_set_new_owner,
03760    .get_orig_dialstring = my_get_orig_dialstring,
03761    .set_needringing = my_set_needringing,
03762    .set_polarity = my_set_polarity,
03763    .start_polarityswitch = my_start_polarityswitch,
03764    .answer_polarityswitch = my_answer_polarityswitch,
03765    .hangup_polarityswitch = my_hangup_polarityswitch,
03766    .have_progressdetect = my_have_progressdetect,
03767 };
03768 
03769 /*! Round robin search locations. */
03770 static struct dahdi_pvt *round_robin[32];
03771 
03772 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03773 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03774 {
03775    int res;
03776    if (p->subs[SUB_REAL].owner == ast)
03777       res = 0;
03778    else if (p->subs[SUB_CALLWAIT].owner == ast)
03779       res = 1;
03780    else if (p->subs[SUB_THREEWAY].owner == ast)
03781       res = 2;
03782    else {
03783       res = -1;
03784       if (!nullok)
03785          ast_log(LOG_WARNING,
03786             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03787             ast ? ast->name : "", p->channel, fname, line);
03788    }
03789    return res;
03790 }
03791 
03792 /*!
03793  * \internal
03794  * \brief Obtain the specified subchannel owner lock if the owner exists.
03795  *
03796  * \param pvt Channel private struct.
03797  * \param sub_idx Subchannel owner to lock.
03798  *
03799  * \note Assumes the pvt->lock is already obtained.
03800  *
03801  * \note
03802  * Because deadlock avoidance may have been necessary, you need to confirm
03803  * the state of things before continuing.
03804  *
03805  * \return Nothing
03806  */
03807 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03808 {
03809    for (;;) {
03810       if (!pvt->subs[sub_idx].owner) {
03811          /* No subchannel owner pointer */
03812          break;
03813       }
03814       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03815          /* Got subchannel owner lock */
03816          break;
03817       }
03818       /* We must unlock the private to avoid the possibility of a deadlock */
03819       DEADLOCK_AVOIDANCE(&pvt->lock);
03820    }
03821 }
03822 
03823 static void wakeup_sub(struct dahdi_pvt *p, int a)
03824 {
03825    dahdi_lock_sub_owner(p, a);
03826    if (p->subs[a].owner) {
03827       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03828       ast_channel_unlock(p->subs[a].owner);
03829    }
03830 }
03831 
03832 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03833 {
03834    for (;;) {
03835       if (p->owner) {
03836          if (ast_channel_trylock(p->owner)) {
03837             DEADLOCK_AVOIDANCE(&p->lock);
03838          } else {
03839             ast_queue_frame(p->owner, f);
03840             ast_channel_unlock(p->owner);
03841             break;
03842          }
03843       } else
03844          break;
03845    }
03846 }
03847 
03848 static void handle_clear_alarms(struct dahdi_pvt *p)
03849 {
03850 #if defined(HAVE_PRI)
03851    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03852       return;
03853    }
03854 #endif   /* defined(HAVE_PRI) */
03855 
03856    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03857       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03858       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03859    }
03860    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03861       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03862       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03863    }
03864 }
03865 
03866 #ifdef HAVE_OPENR2
03867 
03868 static int dahdi_r2_answer(struct dahdi_pvt *p)
03869 {
03870    int res = 0;
03871    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03872    * and does not has support for openr2_chan_answer_call_with_mode
03873    *  */
03874 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03875    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03876    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03877    if (!double_answer) {
03878       /* this still can result in double answer if the channel context
03879       * was configured that way */
03880       res = openr2_chan_answer_call(p->r2chan);
03881    } else if (wants_double_answer) {
03882       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03883    } else {
03884       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03885    }
03886 #else
03887    res = openr2_chan_answer_call(p->r2chan);
03888 #endif
03889    return res;
03890 }
03891 
03892 
03893 
03894 /* should be called with the ast_channel locked */
03895 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03896 {
03897    openr2_calling_party_category_t cat;
03898    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03899    struct dahdi_pvt *p = c->tech_pvt;
03900    if (ast_strlen_zero(catstr)) {
03901       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03902             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03903       return p->mfcr2_category;
03904    }
03905    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03906       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03907             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03908       return p->mfcr2_category;
03909    }
03910    ast_debug(1, "Using category %s\n", catstr);
03911    return cat;
03912 }
03913 
03914 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03915 {
03916    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03917    ast_mutex_lock(&p->lock);
03918    if (p->mfcr2call) {
03919       ast_mutex_unlock(&p->lock);
03920       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03921          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03922          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03923          the other end will see our seize as a forced release and drop the call, we will see an invalid
03924          pattern that will be seen and treated as protocol error. */
03925       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03926       return;
03927    }
03928    p->mfcr2call = 1;
03929    /* better safe than sorry ... */
03930    p->cid_name[0] = '\0';
03931    p->cid_num[0] = '\0';
03932    p->cid_subaddr[0] = '\0';
03933    p->rdnis[0] = '\0';
03934    p->exten[0] = '\0';
03935    p->mfcr2_ani_index = '\0';
03936    p->mfcr2_dnis_index = '\0';
03937    p->mfcr2_dnis_matched = 0;
03938    p->mfcr2_answer_pending = 0;
03939    p->mfcr2_call_accepted = 0;
03940    ast_mutex_unlock(&p->lock);
03941    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03942 }
03943 
03944 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03945 {
03946    int res;
03947    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03948    ast_mutex_lock(&p->lock);
03949    p->inalarm = alarm ? 1 : 0;
03950    if (p->inalarm) {
03951       res = get_alarms(p);
03952       handle_alarms(p, res);
03953    } else {
03954       handle_clear_alarms(p);
03955    }
03956    ast_mutex_unlock(&p->lock);
03957 }
03958 
03959 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03960 {
03961    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03962 }
03963 
03964 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03965 {
03966    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03967    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03968    if (p->owner) {
03969       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03970       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03971    }
03972    ast_mutex_lock(&p->lock);
03973    p->mfcr2call = 0;
03974    ast_mutex_unlock(&p->lock);
03975 }
03976 
03977 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03978 {
03979    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03980       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03981          p->channel, openr2_proto_get_disconnect_string(cause));
03982       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03983       openr2_chan_set_idle(p->r2chan);
03984       ast_mutex_lock(&p->lock);
03985       p->mfcr2call = 0;
03986       ast_mutex_unlock(&p->lock);
03987    }
03988 }
03989 
03990 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03991 {
03992    struct dahdi_pvt *p;
03993    struct ast_channel *c;
03994    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03995          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03996          openr2_proto_get_category_string(category));
03997    p = openr2_chan_get_client_data(r2chan);
03998    /* if collect calls are not allowed and this is a collect call, reject it! */
03999    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04000       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04001       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04002       return;
04003    }
04004    ast_mutex_lock(&p->lock);
04005    p->mfcr2_recvd_category = category;
04006    /* if we're not supposed to use CID, clear whatever we have */
04007    if (!p->use_callerid) {
04008       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04009       p->cid_num[0] = 0;
04010       p->cid_name[0] = 0;
04011    }
04012    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04013    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04014       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04015       p->exten[0] = 's';
04016       p->exten[1] = 0;
04017    }
04018    ast_mutex_unlock(&p->lock);
04019    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04020       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04021             p->channel, p->exten, p->context);
04022       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04023       return;
04024    }
04025    if (!p->mfcr2_accept_on_offer) {
04026       /* The user wants us to start the PBX thread right away without accepting the call first */
04027       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04028       if (c) {
04029          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04030             the call or reject it and detect the tone off condition of the other end, all of this
04031             will be done in the PBX thread now */
04032          return;
04033       }
04034       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04035       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04036    } else if (p->mfcr2_charge_calls) {
04037       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04038       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04039    } else {
04040       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04041       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04042    }
04043 }
04044 
04045 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04046 {
04047    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04048    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04049    ast_mutex_lock(&p->lock);
04050    p->mfcr2call = 0;
04051    ast_mutex_unlock(&p->lock);
04052 }
04053 
04054 static void dahdi_enable_ec(struct dahdi_pvt *p);
04055 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04056 {
04057    struct dahdi_pvt *p = NULL;
04058    struct ast_channel *c = NULL;
04059    p = openr2_chan_get_client_data(r2chan);
04060    dahdi_enable_ec(p);
04061    p->mfcr2_call_accepted = 1;
04062    /* if it's an incoming call ... */
04063    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04064       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04065       /* If accept on offer is not set, it means at this point the PBX thread is already
04066          launched (was launched in the 'on call offered' handler) and therefore this callback
04067          is being executed already in the PBX thread rather than the monitor thread, don't launch
04068          any other thread, just disable the openr2 reading and answer the call if needed */
04069       if (!p->mfcr2_accept_on_offer) {
04070          openr2_chan_disable_read(r2chan);
04071          if (p->mfcr2_answer_pending) {
04072             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04073             dahdi_r2_answer(p);
04074          }
04075          return;
04076       }
04077       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04078       if (c) {
04079          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04080             library to forget about it */
04081          openr2_chan_disable_read(r2chan);
04082          return;
04083       }
04084       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04085       /* failed to create the channel, bail out and report it as an out of order line */
04086       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04087       return;
04088    }
04089    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04090    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04091    p->subs[SUB_REAL].needringing = 1;
04092    p->dialing = 0;
04093    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04094    openr2_chan_disable_read(r2chan);
04095 }
04096 
04097 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04098 {
04099    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04100    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04101    p->subs[SUB_REAL].needanswer = 1;
04102 }
04103 
04104 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04105 {
04106    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04107 }
04108 
04109 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04110 {
04111    switch (cause) {
04112    case OR2_CAUSE_BUSY_NUMBER:
04113       return AST_CAUSE_BUSY;
04114    case OR2_CAUSE_NETWORK_CONGESTION:
04115       return AST_CAUSE_CONGESTION;
04116    case OR2_CAUSE_OUT_OF_ORDER:
04117       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04118    case OR2_CAUSE_UNALLOCATED_NUMBER:
04119       return AST_CAUSE_UNREGISTERED;
04120    case OR2_CAUSE_NO_ANSWER:
04121       return AST_CAUSE_NO_ANSWER;
04122    case OR2_CAUSE_NORMAL_CLEARING:
04123       return AST_CAUSE_NORMAL_CLEARING;
04124    case OR2_CAUSE_UNSPECIFIED:
04125    default:
04126       return AST_CAUSE_NOTDEFINED;
04127    }
04128 }
04129 
04130 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04131 {
04132    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04133    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04134    ast_mutex_lock(&p->lock);
04135    if (!p->owner) {
04136       ast_mutex_unlock(&p->lock);
04137       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04138       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04139       return;
04140    }
04141    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04142       be done in dahdi_hangup */
04143    if (p->owner->_state == AST_STATE_UP) {
04144       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04145       ast_mutex_unlock(&p->lock);
04146    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04147       /* being the forward side we must report what happened to the call to whoever requested it */
04148       switch (cause) {
04149       case OR2_CAUSE_BUSY_NUMBER:
04150          p->subs[SUB_REAL].needbusy = 1;
04151          break;
04152       case OR2_CAUSE_NETWORK_CONGESTION:
04153       case OR2_CAUSE_OUT_OF_ORDER:
04154       case OR2_CAUSE_UNALLOCATED_NUMBER:
04155       case OR2_CAUSE_NO_ANSWER:
04156       case OR2_CAUSE_UNSPECIFIED:
04157       case OR2_CAUSE_NORMAL_CLEARING:
04158          p->subs[SUB_REAL].needcongestion = 1;
04159          break;
04160       default:
04161          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04162       }
04163       ast_mutex_unlock(&p->lock);
04164    } else {
04165       ast_mutex_unlock(&p->lock);
04166       /* being the backward side and not UP yet, we only need to request hangup */
04167       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04168       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04169    }
04170 }
04171 
04172 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04173 {
04174    switch (level) {
04175    case OR2_LOG_NOTICE:
04176       ast_verbose("%s", logmessage);
04177       break;
04178    case OR2_LOG_WARNING:
04179       ast_log(LOG_WARNING, "%s", logmessage);
04180       break;
04181    case OR2_LOG_ERROR:
04182       ast_log(LOG_ERROR, "%s", logmessage);
04183       break;
04184    case OR2_LOG_STACK_TRACE:
04185    case OR2_LOG_MF_TRACE:
04186    case OR2_LOG_CAS_TRACE:
04187    case OR2_LOG_DEBUG:
04188    case OR2_LOG_EX_DEBUG:
04189       ast_log(LOG_DEBUG, "%s", logmessage);
04190       break;
04191    default:
04192       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04193       ast_log(LOG_DEBUG, "%s", logmessage);
04194       break;
04195    }
04196 }
04197 
04198 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04199 {
04200    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04201    ast_mutex_lock(&p->lock);
04202    p->remotelyblocked = 1;
04203    ast_mutex_unlock(&p->lock);
04204    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04205 }
04206 
04207 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04208 {
04209    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04210    ast_mutex_lock(&p->lock);
04211    p->remotelyblocked = 0;
04212    ast_mutex_unlock(&p->lock);
04213    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04214 }
04215 
04216 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04217    __attribute__((format (printf, 3, 0)));
04218 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04219 {
04220 #define CONTEXT_TAG "Context - "
04221    char logmsg[256];
04222    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04223    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04224    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04225    dahdi_r2_write_log(level, completemsg);
04226 #undef CONTEXT_TAG
04227 }
04228 
04229 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04230    __attribute__((format (printf, 3, 0)));
04231 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04232 {
04233 #define CHAN_TAG "Chan "
04234    char logmsg[256];
04235    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04236    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04237    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04238    dahdi_r2_write_log(level, completemsg);
04239 }
04240 
04241 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04242 {
04243    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04244    /* if 'immediate' is set, let's stop requesting DNIS */
04245    if (p->immediate) {
04246       return 0;
04247    }
04248    p->exten[p->mfcr2_dnis_index] = digit;
04249    p->rdnis[p->mfcr2_dnis_index] = digit;
04250    p->mfcr2_dnis_index++;
04251    p->exten[p->mfcr2_dnis_index] = 0;
04252    p->rdnis[p->mfcr2_dnis_index] = 0;
04253    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04254    if ((p->mfcr2_dnis_matched ||
04255        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04256        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04257       return 0;
04258    }
04259    /* otherwise keep going */
04260    return 1;
04261 }
04262 
04263 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04264 {
04265    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04266    p->cid_num[p->mfcr2_ani_index] = digit;
04267    p->cid_name[p->mfcr2_ani_index] = digit;
04268    p->mfcr2_ani_index++;
04269    p->cid_num[p->mfcr2_ani_index] = 0;
04270    p->cid_name[p->mfcr2_ani_index] = 0;
04271 }
04272 
04273 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04274 {
04275    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04276 }
04277 
04278 static openr2_event_interface_t dahdi_r2_event_iface = {
04279    .on_call_init = dahdi_r2_on_call_init,
04280    .on_call_offered = dahdi_r2_on_call_offered,
04281    .on_call_accepted = dahdi_r2_on_call_accepted,
04282    .on_call_answered = dahdi_r2_on_call_answered,
04283    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04284    .on_call_end = dahdi_r2_on_call_end,
04285    .on_call_read = dahdi_r2_on_call_read,
04286    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04287    .on_os_error = dahdi_r2_on_os_error,
04288    .on_protocol_error = dahdi_r2_on_protocol_error,
04289    .on_line_blocked = dahdi_r2_on_line_blocked,
04290    .on_line_idle = dahdi_r2_on_line_idle,
04291    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04292    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04293    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04294    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04295    /* so far we do nothing with billing pulses */
04296    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04297 };
04298 
04299 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04300 {
04301    return AST_ALAW(sample);
04302 }
04303 
04304 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04305 {
04306    return AST_LIN2A(sample);
04307 }
04308 
04309 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04310    dahdi_r2_alaw_to_linear,
04311    dahdi_r2_linear_to_alaw
04312 };
04313 
04314 #endif /* HAVE_OPENR2 */
04315 
04316 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04317 {
04318    int tchan;
04319    int tinthreeway;
04320    struct ast_channel *towner;
04321 
04322    ast_debug(1, "Swapping %d and %d\n", a, b);
04323 
04324    tchan = p->subs[a].chan;
04325    towner = p->subs[a].owner;
04326    tinthreeway = p->subs[a].inthreeway;
04327 
04328    p->subs[a].chan = p->subs[b].chan;
04329    p->subs[a].owner = p->subs[b].owner;
04330    p->subs[a].inthreeway = p->subs[b].inthreeway;
04331 
04332    p->subs[b].chan = tchan;
04333    p->subs[b].owner = towner;
04334    p->subs[b].inthreeway = tinthreeway;
04335 
04336    if (p->subs[a].owner)
04337       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04338    if (p->subs[b].owner)
04339       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04340    wakeup_sub(p, a);
04341    wakeup_sub(p, b);
04342 }
04343 
04344 static int dahdi_open(char *fn)
04345 {
04346    int fd;
04347    int isnum;
04348    int chan = 0;
04349    int bs;
04350    int x;
04351    isnum = 1;
04352    for (x = 0; x < strlen(fn); x++) {
04353       if (!isdigit(fn[x])) {
04354          isnum = 0;
04355          break;
04356       }
04357    }
04358    if (isnum) {
04359       chan = atoi(fn);
04360       if (chan < 1) {
04361          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04362          return -1;
04363       }
04364       fn = "/dev/dahdi/channel";
04365    }
04366    fd = open(fn, O_RDWR | O_NONBLOCK);
04367    if (fd < 0) {
04368       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04369       return -1;
04370    }
04371    if (chan) {
04372       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04373          x = errno;
04374          close(fd);
04375          errno = x;
04376          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04377          return -1;
04378       }
04379    }
04380    bs = READ_SIZE;
04381    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04382       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04383       x = errno;
04384       close(fd);
04385       errno = x;
04386       return -1;
04387    }
04388    return fd;
04389 }
04390 
04391 static void dahdi_close(int fd)
04392 {
04393    if (fd > 0)
04394       close(fd);
04395 }
04396 
04397 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04398 {
04399    dahdi_close(chan_pvt->subs[sub_num].dfd);
04400    chan_pvt->subs[sub_num].dfd = -1;
04401 }
04402 
04403 #if defined(HAVE_PRI)
04404 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04405 {
04406    dahdi_close(pri->pri.fds[fd_num]);
04407    pri->pri.fds[fd_num] = -1;
04408 }
04409 #endif   /* defined(HAVE_PRI) */
04410 
04411 #if defined(HAVE_SS7)
04412 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04413 {
04414    dahdi_close(ss7->ss7.fds[fd_num]);
04415    ss7->ss7.fds[fd_num] = -1;
04416 }
04417 #endif   /* defined(HAVE_SS7) */
04418 
04419 static int dahdi_setlinear(int dfd, int linear)
04420 {
04421    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04422 }
04423 
04424 
04425 static int alloc_sub(struct dahdi_pvt *p, int x)
04426 {
04427    struct dahdi_bufferinfo bi;
04428    int res;
04429    if (p->subs[x].dfd >= 0) {
04430       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04431       return -1;
04432    }
04433 
04434    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04435    if (p->subs[x].dfd <= -1) {
04436       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04437       return -1;
04438    }
04439 
04440    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04441    if (!res) {
04442       bi.txbufpolicy = p->buf_policy;
04443       bi.rxbufpolicy = p->buf_policy;
04444       bi.numbufs = p->buf_no;
04445       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04446       if (res < 0) {
04447          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04448       }
04449    } else
04450       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04451 
04452    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04453       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04454       dahdi_close_sub(p, x);
04455       p->subs[x].dfd = -1;
04456       return -1;
04457    }
04458    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04459    return 0;
04460 }
04461 
04462 static int unalloc_sub(struct dahdi_pvt *p, int x)
04463 {
04464    if (!x) {
04465       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04466       return -1;
04467    }
04468    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04469    dahdi_close_sub(p, x);
04470    p->subs[x].linear = 0;
04471    p->subs[x].chan = 0;
04472    p->subs[x].owner = NULL;
04473    p->subs[x].inthreeway = 0;
04474    p->polarity = POLARITY_IDLE;
04475    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04476    return 0;
04477 }
04478 
04479 static int digit_to_dtmfindex(char digit)
04480 {
04481    if (isdigit(digit))
04482       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04483    else if (digit >= 'A' && digit <= 'D')
04484       return DAHDI_TONE_DTMF_A + (digit - 'A');
04485    else if (digit >= 'a' && digit <= 'd')
04486       return DAHDI_TONE_DTMF_A + (digit - 'a');
04487    else if (digit == '*')
04488       return DAHDI_TONE_DTMF_s;
04489    else if (digit == '#')
04490       return DAHDI_TONE_DTMF_p;
04491    else
04492       return -1;
04493 }
04494 
04495 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04496 {
04497    struct dahdi_pvt *pvt;
04498    int idx;
04499    int dtmf = -1;
04500    int res;
04501 
04502    pvt = chan->tech_pvt;
04503 
04504    ast_mutex_lock(&pvt->lock);
04505 
04506    idx = dahdi_get_index(chan, pvt, 0);
04507 
04508    if ((idx != SUB_REAL) || !pvt->owner)
04509       goto out;
04510 
04511 #ifdef HAVE_PRI
04512    switch (pvt->sig) {
04513    case SIG_PRI_LIB_HANDLE_CASES:
04514       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04515       if (!res)
04516          goto out;
04517       break;
04518    default:
04519       break;
04520    }
04521 #endif
04522    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04523       goto out;
04524 
04525    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04526       struct dahdi_dialoperation zo = {
04527          .op = DAHDI_DIAL_OP_APPEND,
04528       };
04529 
04530       zo.dialstr[0] = 'T';
04531       zo.dialstr[1] = digit;
04532       zo.dialstr[2] = '\0';
04533       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04534          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04535             chan->name, digit, strerror(errno));
04536       else
04537          pvt->dialing = 1;
04538    } else {
04539       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04540          chan->name, digit);
04541       pvt->dialing = 1;
04542       pvt->begindigit = digit;
04543    }
04544 
04545 out:
04546    ast_mutex_unlock(&pvt->lock);
04547 
04548    return 0;
04549 }
04550 
04551 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04552 {
04553    struct dahdi_pvt *pvt;
04554    int res = 0;
04555    int idx;
04556    int x;
04557 
04558    pvt = chan->tech_pvt;
04559 
04560    ast_mutex_lock(&pvt->lock);
04561 
04562    idx = dahdi_get_index(chan, pvt, 0);
04563 
04564    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04565       goto out;
04566 
04567 #ifdef HAVE_PRI
04568    /* This means that the digit was already sent via PRI signalling */
04569    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04570       goto out;
04571    }
04572 #endif
04573 
04574    if (pvt->begindigit) {
04575       x = -1;
04576       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04577          chan->name, digit);
04578       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04579       pvt->dialing = 0;
04580       pvt->begindigit = 0;
04581    }
04582 
04583 out:
04584    ast_mutex_unlock(&pvt->lock);
04585 
04586    return res;
04587 }
04588 
04589 static const char * const events[] = {
04590    "No event",
04591    "On hook",
04592    "Ring/Answered",
04593    "Wink/Flash",
04594    "Alarm",
04595    "No more alarm",
04596    "HDLC Abort",
04597    "HDLC Overrun",
04598    "HDLC Bad FCS",
04599    "Dial Complete",
04600    "Ringer On",
04601    "Ringer Off",
04602    "Hook Transition Complete",
04603    "Bits Changed",
04604    "Pulse Start",
04605    "Timer Expired",
04606    "Timer Ping",
04607    "Polarity Reversal",
04608    "Ring Begin",
04609 };
04610 
04611 static struct {
04612    int alarm;
04613    char *name;
04614 } alarms[] = {
04615    { DAHDI_ALARM_RED, "Red Alarm" },
04616    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04617    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04618    { DAHDI_ALARM_RECOVER, "Recovering" },
04619    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04620    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04621    { DAHDI_ALARM_NONE, "None" },
04622 };
04623 
04624 static char *alarm2str(int alm)
04625 {
04626    int x;
04627    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04628       if (alarms[x].alarm & alm)
04629          return alarms[x].name;
04630    }
04631    return alm ? "Unknown Alarm" : "No Alarm";
04632 }
04633 
04634 static const char *event2str(int event)
04635 {
04636    static char buf[256];
04637    if ((event < (ARRAY_LEN(events))) && (event > -1))
04638       return events[event];
04639    sprintf(buf, "Event %d", event); /* safe */
04640    return buf;
04641 }
04642 
04643 static char *dahdi_sig2str(int sig)
04644 {
04645    static char buf[256];
04646    switch (sig) {
04647    case SIG_EM:
04648       return "E & M Immediate";
04649    case SIG_EMWINK:
04650       return "E & M Wink";
04651    case SIG_EM_E1:
04652       return "E & M E1";
04653    case SIG_FEATD:
04654       return "Feature Group D (DTMF)";
04655    case SIG_FEATDMF:
04656       return "Feature Group D (MF)";
04657    case SIG_FEATDMF_TA:
04658       return "Feature Groud D (MF) Tandem Access";
04659    case SIG_FEATB:
04660       return "Feature Group B (MF)";
04661    case SIG_E911:
04662       return "E911 (MF)";
04663    case SIG_FGC_CAMA:
04664       return "FGC/CAMA (Dialpulse)";
04665    case SIG_FGC_CAMAMF:
04666       return "FGC/CAMA (MF)";
04667    case SIG_FXSLS:
04668       return "FXS Loopstart";
04669    case SIG_FXSGS:
04670       return "FXS Groundstart";
04671    case SIG_FXSKS:
04672       return "FXS Kewlstart";
04673    case SIG_FXOLS:
04674       return "FXO Loopstart";
04675    case SIG_FXOGS:
04676       return "FXO Groundstart";
04677    case SIG_FXOKS:
04678       return "FXO Kewlstart";
04679    case SIG_PRI:
04680       return "ISDN PRI";
04681    case SIG_BRI:
04682       return "ISDN BRI Point to Point";
04683    case SIG_BRI_PTMP:
04684       return "ISDN BRI Point to MultiPoint";
04685    case SIG_SS7:
04686       return "SS7";
04687    case SIG_MFCR2:
04688       return "MFC/R2";
04689    case SIG_SF:
04690       return "SF (Tone) Immediate";
04691    case SIG_SFWINK:
04692       return "SF (Tone) Wink";
04693    case SIG_SF_FEATD:
04694       return "SF (Tone) with Feature Group D (DTMF)";
04695    case SIG_SF_FEATDMF:
04696       return "SF (Tone) with Feature Group D (MF)";
04697    case SIG_SF_FEATB:
04698       return "SF (Tone) with Feature Group B (MF)";
04699    case 0:
04700       return "Pseudo";
04701    default:
04702       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04703       return buf;
04704    }
04705 }
04706 
04707 #define sig2str dahdi_sig2str
04708 
04709 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04710 {
04711    /* If the conference already exists, and we're already in it
04712       don't bother doing anything */
04713    struct dahdi_confinfo zi;
04714 
04715    memset(&zi, 0, sizeof(zi));
04716    zi.chan = 0;
04717 
04718    if (slavechannel > 0) {
04719       /* If we have only one slave, do a digital mon */
04720       zi.confmode = DAHDI_CONF_DIGITALMON;
04721       zi.confno = slavechannel;
04722    } else {
04723       if (!idx) {
04724          /* Real-side and pseudo-side both participate in conference */
04725          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04726             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04727       } else
04728          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04729       zi.confno = p->confno;
04730    }
04731    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04732       return 0;
04733    if (c->dfd < 0)
04734       return 0;
04735    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04736       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04737       return -1;
04738    }
04739    if (slavechannel < 1) {
04740       p->confno = zi.confno;
04741    }
04742    c->curconf = zi;
04743    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04744    return 0;
04745 }
04746 
04747 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04748 {
04749    /* If they're listening to our channel, they're ours */
04750    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04751       return 1;
04752    /* If they're a talker on our (allocated) conference, they're ours */
04753    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04754       return 1;
04755    return 0;
04756 }
04757 
04758 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04759 {
04760    struct dahdi_confinfo zi;
04761    if (/* Can't delete if there's no dfd */
04762       (c->dfd < 0) ||
04763       /* Don't delete from the conference if it's not our conference */
04764       !isourconf(p, c)
04765       /* Don't delete if we don't think it's conferenced at all (implied) */
04766       ) return 0;
04767    memset(&zi, 0, sizeof(zi));
04768    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04769       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04770       return -1;
04771    }
04772    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04773    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04774    return 0;
04775 }
04776 
04777 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04778 {
04779    int x;
04780    int useslavenative;
04781    struct dahdi_pvt *slave = NULL;
04782    /* Start out optimistic */
04783    useslavenative = 1;
04784    /* Update conference state in a stateless fashion */
04785    for (x = 0; x < 3; x++) {
04786       /* Any three-way calling makes slave native mode *definitely* out
04787          of the question */
04788       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04789          useslavenative = 0;
04790    }
04791    /* If we don't have any 3-way calls, check to see if we have
04792       precisely one slave */
04793    if (useslavenative) {
04794       for (x = 0; x < MAX_SLAVES; x++) {
04795          if (p->slaves[x]) {
04796             if (slave) {
04797                /* Whoops already have a slave!  No
04798                   slave native and stop right away */
04799                slave = NULL;
04800                useslavenative = 0;
04801                break;
04802             } else {
04803                /* We have one slave so far */
04804                slave = p->slaves[x];
04805             }
04806          }
04807       }
04808    }
04809    /* If no slave, slave native definitely out */
04810    if (!slave)
04811       useslavenative = 0;
04812    else if (slave->law != p->law) {
04813       useslavenative = 0;
04814       slave = NULL;
04815    }
04816    if (out)
04817       *out = slave;
04818    return useslavenative;
04819 }
04820 
04821 static int reset_conf(struct dahdi_pvt *p)
04822 {
04823    p->confno = -1;
04824    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04825    if (p->subs[SUB_REAL].dfd > -1) {
04826       struct dahdi_confinfo zi;
04827 
04828       memset(&zi, 0, sizeof(zi));
04829       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04830          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04831    }
04832    return 0;
04833 }
04834 
04835 static int update_conf(struct dahdi_pvt *p)
04836 {
04837    int needconf = 0;
04838    int x;
04839    int useslavenative;
04840    struct dahdi_pvt *slave = NULL;
04841 
04842    useslavenative = isslavenative(p, &slave);
04843    /* Start with the obvious, general stuff */
04844    for (x = 0; x < 3; x++) {
04845       /* Look for three way calls */
04846       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04847          conf_add(p, &p->subs[x], x, 0);
04848          needconf++;
04849       } else {
04850          conf_del(p, &p->subs[x], x);
04851       }
04852    }
04853    /* If we have a slave, add him to our conference now. or DAX
04854       if this is slave native */
04855    for (x = 0; x < MAX_SLAVES; x++) {
04856       if (p->slaves[x]) {
04857          if (useslavenative)
04858             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04859          else {
04860             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04861             needconf++;
04862          }
04863       }
04864    }
04865    /* If we're supposed to be in there, do so now */
04866    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04867       if (useslavenative)
04868          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04869       else {
04870          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04871          needconf++;
04872       }
04873    }
04874    /* If we have a master, add ourselves to his conference */
04875    if (p->master) {
04876       if (isslavenative(p->master, NULL)) {
04877          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04878       } else {
04879          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04880       }
04881    }
04882    if (!needconf) {
04883       /* Nobody is left (or should be left) in our conference.
04884          Kill it. */
04885       p->confno = -1;
04886    }
04887    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04888    return 0;
04889 }
04890 
04891 static void dahdi_enable_ec(struct dahdi_pvt *p)
04892 {
04893    int res;
04894    if (!p)
04895       return;
04896    if (p->echocanon) {
04897       ast_debug(1, "Echo cancellation already on\n");
04898       return;
04899    }
04900    if (p->digital) {
04901       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04902       return;
04903    }
04904    if (p->echocancel.head.tap_length) {
04905 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04906       switch (p->sig) {
04907 #if defined(HAVE_PRI)
04908       case SIG_PRI_LIB_HANDLE_CASES:
04909          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04910             /*
04911              * PRI nobch pseudo channel.  Does not need ec anyway.
04912              * Does not handle ioctl(DAHDI_AUDIOMODE)
04913              */
04914             return;
04915          }
04916          /* Fall through */
04917 #endif   /* defined(HAVE_PRI) */
04918 #if defined(HAVE_SS7)
04919       case SIG_SS7:
04920 #endif   /* defined(HAVE_SS7) */
04921          {
04922             int x = 1;
04923 
04924             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04925             if (res)
04926                ast_log(LOG_WARNING,
04927                   "Unable to enable audio mode on channel %d (%s)\n",
04928                   p->channel, strerror(errno));
04929          }
04930          break;
04931       default:
04932          break;
04933       }
04934 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04935       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04936       if (res) {
04937          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04938       } else {
04939          p->echocanon = 1;
04940          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04941       }
04942    } else
04943       ast_debug(1, "No echo cancellation requested\n");
04944 }
04945 
04946 static void dahdi_train_ec(struct dahdi_pvt *p)
04947 {
04948    int x;
04949    int res;
04950 
04951    if (p && p->echocanon && p->echotraining) {
04952       x = p->echotraining;
04953       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04954       if (res)
04955          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04956       else
04957          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04958    } else {
04959       ast_debug(1, "No echo training requested\n");
04960    }
04961 }
04962 
04963 static void dahdi_disable_ec(struct dahdi_pvt *p)
04964 {
04965    int res;
04966 
04967    if (p->echocanon) {
04968       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04969 
04970       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04971 
04972       if (res)
04973          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04974       else
04975          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04976    }
04977 
04978    p->echocanon = 0;
04979 }
04980 
04981 /* perform a dynamic range compression transform on the given sample */
04982 static int drc_sample(int sample, float drc)
04983 {
04984    float neg;
04985    float shallow, steep;
04986    float max = SHRT_MAX;
04987    
04988    neg = (sample < 0 ? -1 : 1);
04989    steep = drc*sample;
04990    shallow = neg*(max-max/drc)+(float)sample/drc;
04991    if (abs(steep) < abs(shallow)) {
04992       sample = steep;
04993    }
04994    else {
04995       sample = shallow;
04996    }
04997 
04998    return sample;
04999 }
05000 
05001 
05002 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05003 {
05004    int j;
05005    int k;
05006 
05007    float linear_gain = pow(10.0, gain / 20.0);
05008 
05009    switch (law) {
05010    case DAHDI_LAW_ALAW:
05011       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05012          if (gain || drc) {
05013             k = AST_ALAW(j);
05014             if (drc) {
05015                k = drc_sample(k, drc);
05016             }
05017             k = (float)k*linear_gain;
05018             if (k > 32767) k = 32767;
05019             if (k < -32767) k = -32767;
05020             g->txgain[j] = AST_LIN2A(k);
05021          } else {
05022             g->txgain[j] = j;
05023          }
05024       }
05025       break;
05026    case DAHDI_LAW_MULAW:
05027       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05028          if (gain || drc) {
05029             k = AST_MULAW(j);
05030             if (drc) {
05031                k = drc_sample(k, drc);
05032             }
05033             k = (float)k*linear_gain;
05034             if (k > 32767) k = 32767;
05035             if (k < -32767) k = -32767;
05036             g->txgain[j] = AST_LIN2MU(k);
05037 
05038          } else {
05039             g->txgain[j] = j;
05040          }
05041       }
05042       break;
05043    }
05044 }
05045 
05046 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05047 {
05048    int j;
05049    int k;
05050    float linear_gain = pow(10.0, gain / 20.0);
05051 
05052    switch (law) {
05053    case DAHDI_LAW_ALAW:
05054       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05055          if (gain || drc) {
05056             k = AST_ALAW(j);
05057             if (drc) {
05058                k = drc_sample(k, drc);
05059             }
05060             k = (float)k*linear_gain;
05061             if (k > 32767) k = 32767;
05062             if (k < -32767) k = -32767;
05063             g->rxgain[j] = AST_LIN2A(k);
05064          } else {
05065             g->rxgain[j] = j;
05066          }
05067       }
05068       break;
05069    case DAHDI_LAW_MULAW:
05070       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05071          if (gain || drc) {
05072             k = AST_MULAW(j);
05073             if (drc) {
05074                k = drc_sample(k, drc);
05075             }
05076             k = (float)k*linear_gain;
05077             if (k > 32767) k = 32767;
05078             if (k < -32767) k = -32767;
05079             g->rxgain[j] = AST_LIN2MU(k);
05080          } else {
05081             g->rxgain[j] = j;
05082          }
05083       }
05084       break;
05085    }
05086 }
05087 
05088 static int set_actual_txgain(int fd, float gain, float drc, int law)
05089 {
05090    struct dahdi_gains g;
05091    int res;
05092 
05093    memset(&g, 0, sizeof(g));
05094    res = ioctl(fd, DAHDI_GETGAINS, &g);
05095    if (res) {
05096       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05097       return res;
05098    }
05099 
05100    fill_txgain(&g, gain, drc, law);
05101 
05102    return ioctl(fd, DAHDI_SETGAINS, &g);
05103 }
05104 
05105 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05106 {
05107    struct dahdi_gains g;
05108    int res;
05109 
05110    memset(&g, 0, sizeof(g));
05111    res = ioctl(fd, DAHDI_GETGAINS, &g);
05112    if (res) {
05113       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05114       return res;
05115    }
05116 
05117    fill_rxgain(&g, gain, drc, law);
05118 
05119    return ioctl(fd, DAHDI_SETGAINS, &g);
05120 }
05121 
05122 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05123 {
05124    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05125 }
05126 
05127 static int bump_gains(struct dahdi_pvt *p)
05128 {
05129    int res;
05130 
05131    /* Bump receive gain by value stored in cid_rxgain */
05132    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05133    if (res) {
05134       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05135       return -1;
05136    }
05137 
05138    return 0;
05139 }
05140 
05141 static int restore_gains(struct dahdi_pvt *p)
05142 {
05143    int res;
05144 
05145    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05146    if (res) {
05147       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05148       return -1;
05149    }
05150 
05151    return 0;
05152 }
05153 
05154 static inline int dahdi_set_hook(int fd, int hs)
05155 {
05156    int x, res;
05157 
05158    x = hs;
05159    res = ioctl(fd, DAHDI_HOOK, &x);
05160 
05161    if (res < 0) {
05162       if (errno == EINPROGRESS)
05163          return 0;
05164       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05165       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05166    }
05167 
05168    return res;
05169 }
05170 
05171 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05172 {
05173    int x, res;
05174 
05175    x = muted;
05176 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05177    switch (p->sig) {
05178 #if defined(HAVE_PRI)
05179    case SIG_PRI_LIB_HANDLE_CASES:
05180       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05181          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05182          break;
05183       }
05184       /* Fall through */
05185 #endif   /* defined(HAVE_PRI) */
05186 #if defined(HAVE_SS7)
05187    case SIG_SS7:
05188 #endif   /* defined(HAVE_SS7) */
05189       {
05190          int y = 1;
05191 
05192          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05193          if (res)
05194             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05195                p->channel, strerror(errno));
05196       }
05197       break;
05198    default:
05199       break;
05200    }
05201 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05202    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05203    if (res < 0)
05204       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05205    return res;
05206 }
05207 
05208 static int save_conference(struct dahdi_pvt *p)
05209 {
05210    struct dahdi_confinfo c;
05211    int res;
05212    if (p->saveconf.confmode) {
05213       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05214       return -1;
05215    }
05216    p->saveconf.chan = 0;
05217    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05218    if (res) {
05219       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05220       p->saveconf.confmode = 0;
05221       return -1;
05222    }
05223    memset(&c, 0, sizeof(c));
05224    c.confmode = DAHDI_CONF_NORMAL;
05225    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05226    if (res) {
05227       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05228       return -1;
05229    }
05230    ast_debug(1, "Disabled conferencing\n");
05231    return 0;
05232 }
05233 
05234 static int restore_conference(struct dahdi_pvt *p)
05235 {
05236    int res;
05237    if (p->saveconf.confmode) {
05238       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05239       p->saveconf.confmode = 0;
05240       if (res) {
05241          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05242          return -1;
05243       }
05244       ast_debug(1, "Restored conferencing\n");
05245    }
05246    return 0;
05247 }
05248 
05249 static int send_cwcidspill(struct dahdi_pvt *p)
05250 {
05251    p->callwaitcas = 0;
05252    p->cidcwexpire = 0;
05253    p->cid_suppress_expire = 0;
05254    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05255       return -1;
05256    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05257    /* Make sure we account for the end */
05258    p->cidlen += READ_SIZE * 4;
05259    p->cidpos = 0;
05260    send_callerid(p);
05261    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05262    return 0;
05263 }
05264 
05265 static int has_voicemail(struct dahdi_pvt *p)
05266 {
05267    int new_msgs;
05268    struct ast_event *event;
05269    char *mailbox, *context;
05270 
05271    mailbox = context = ast_strdupa(p->mailbox);
05272    strsep(&context, "@");
05273    if (ast_strlen_zero(context))
05274       context = "default";
05275 
05276    event = ast_event_get_cached(AST_EVENT_MWI,
05277       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05278       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05279       AST_EVENT_IE_END);
05280 
05281    if (event) {
05282       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05283       ast_event_destroy(event);
05284    } else
05285       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05286 
05287    return new_msgs;
05288 }
05289 
05290 
05291 
05292 static int send_callerid(struct dahdi_pvt *p)
05293 {
05294    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05295    int res;
05296    /* Take out of linear mode if necessary */
05297    if (p->subs[SUB_REAL].linear) {
05298       p->subs[SUB_REAL].linear = 0;
05299       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05300    }
05301    while (p->cidpos < p->cidlen) {
05302       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05303       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05304       if (res < 0) {
05305          if (errno == EAGAIN)
05306             return 0;
05307          else {
05308             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05309             return -1;
05310          }
05311       }
05312       if (!res)
05313          return 0;
05314       p->cidpos += res;
05315    }
05316    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05317    ast_free(p->cidspill);
05318    p->cidspill = NULL;
05319    if (p->callwaitcas) {
05320       /* Wait for CID/CW to expire */
05321       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05322       p->cid_suppress_expire = p->cidcwexpire;
05323    } else
05324       restore_conference(p);
05325    return 0;
05326 }
05327 
05328 static int dahdi_callwait(struct ast_channel *ast)
05329 {
05330    struct dahdi_pvt *p = ast->tech_pvt;
05331    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05332    if (p->cidspill) {
05333       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05334       ast_free(p->cidspill);
05335    }
05336 
05337    /*
05338     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05339     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05340     */
05341    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05342       return -1;
05343    save_conference(p);
05344    /* Silence */
05345    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05346    if (!p->callwaitrings && p->callwaitingcallerid) {
05347       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05348       p->callwaitcas = 1;
05349       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05350    } else {
05351       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05352       p->callwaitcas = 0;
05353       p->cidlen = 2400 + READ_SIZE * 4;
05354    }
05355    p->cidpos = 0;
05356    send_callerid(p);
05357 
05358    return 0;
05359 }
05360 
05361 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05362 {
05363    struct dahdi_pvt *p = ast->tech_pvt;
05364    int x, res, mysig;
05365    char dest[256]; /* must be same length as p->dialdest */
05366 
05367    ast_mutex_lock(&p->lock);
05368    ast_copy_string(dest, rdest, sizeof(dest));
05369    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05370    if ((ast->_state == AST_STATE_BUSY)) {
05371       p->subs[SUB_REAL].needbusy = 1;
05372       ast_mutex_unlock(&p->lock);
05373       return 0;
05374    }
05375    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05376       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05377       ast_mutex_unlock(&p->lock);
05378       return -1;
05379    }
05380    p->waitingfordt.tv_sec = 0;
05381    p->dialednone = 0;
05382    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05383    {
05384       /* Special pseudo -- automatically up */
05385       ast_setstate(ast, AST_STATE_UP);
05386       ast_mutex_unlock(&p->lock);
05387       return 0;
05388    }
05389    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05390    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05391    if (res)
05392       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05393    p->outgoing = 1;
05394 
05395    if (IS_DIGITAL(ast->transfercapability)){
05396       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05397    } else {
05398       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05399    }  
05400 
05401 #ifdef HAVE_PRI
05402    if (dahdi_sig_pri_lib_handles(p->sig)) {
05403       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05404          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05405       ast_mutex_unlock(&p->lock);
05406       return res;
05407    }
05408 #endif
05409 
05410 #if defined(HAVE_SS7)
05411    if (p->sig == SIG_SS7) {
05412       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05413       ast_mutex_unlock(&p->lock);
05414       return res;
05415    }
05416 #endif   /* defined(HAVE_SS7) */
05417 
05418    /* If this is analog signalling we can exit here */
05419    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05420       p->callwaitrings = 0;
05421       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05422       ast_mutex_unlock(&p->lock);
05423       return res;
05424    }
05425 
05426    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05427    switch (mysig) {
05428    case 0:
05429       /* Special pseudo -- automatically up*/
05430       ast_setstate(ast, AST_STATE_UP);
05431       break;
05432    case SIG_MFCR2:
05433       break;
05434    default:
05435       ast_debug(1, "not yet implemented\n");
05436       ast_mutex_unlock(&p->lock);
05437       return -1;
05438    }
05439 
05440 #ifdef HAVE_OPENR2
05441    if (p->mfcr2) {
05442       openr2_calling_party_category_t chancat;
05443       int callres = 0;
05444       char *c, *l;
05445 
05446       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05447       p->dialdest[0] = '\0';
05448 
05449       c = strchr(dest, '/');
05450       if (c) {
05451          c++;
05452       } else {
05453          c = "";
05454       }
05455       if (!p->hidecallerid) {
05456          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05457       } else {
05458          l = NULL;
05459       }
05460       if (strlen(c) < p->stripmsd) {
05461          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05462          ast_mutex_unlock(&p->lock);
05463          return -1;
05464       }
05465       p->dialing = 1;
05466       chancat = dahdi_r2_get_channel_category(ast);
05467       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05468       if (-1 == callres) {
05469          ast_mutex_unlock(&p->lock);
05470          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05471          return -1;
05472       }
05473       p->mfcr2_call_accepted = 0;
05474       p->mfcr2_progress = 0;
05475       ast_setstate(ast, AST_STATE_DIALING);
05476    }
05477 #endif /* HAVE_OPENR2 */
05478    ast_mutex_unlock(&p->lock);
05479    return 0;
05480 }
05481 
05482 /*!
05483  * \internal
05484  * \brief Insert the given chan_dahdi interface structure into the interface list.
05485  * \since 1.8
05486  *
05487  * \param pvt chan_dahdi private interface structure to insert.
05488  *
05489  * \details
05490  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05491  * Any duplicates are inserted after the existing entries.
05492  *
05493  * \note The new interface must not already be in the list.
05494  *
05495  * \return Nothing
05496  */
05497 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05498 {
05499    struct dahdi_pvt *cur;
05500 
05501    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05502 
05503    /* Find place in middle of list for the new interface. */
05504    for (cur = iflist; cur; cur = cur->next) {
05505       if (pvt->channel < cur->channel) {
05506          /* New interface goes before the current interface. */
05507          pvt->prev = cur->prev;
05508          pvt->next = cur;
05509          if (cur->prev) {
05510             /* Insert into the middle of the list. */
05511             cur->prev->next = pvt;
05512          } else {
05513             /* Insert at head of list. */
05514             iflist = pvt;
05515          }
05516          cur->prev = pvt;
05517          return;
05518       }
05519    }
05520 
05521    /* New interface goes onto the end of the list */
05522    pvt->prev = ifend;
05523    pvt->next = NULL;
05524    if (ifend) {
05525       ifend->next = pvt;
05526    }
05527    ifend = pvt;
05528    if (!iflist) {
05529       /* List was empty */
05530       iflist = pvt;
05531    }
05532 }
05533 
05534 /*!
05535  * \internal
05536  * \brief Extract the given chan_dahdi interface structure from the interface list.
05537  * \since 1.8
05538  *
05539  * \param pvt chan_dahdi private interface structure to extract.
05540  *
05541  * \note
05542  * The given interface structure can be either in the interface list or a stand alone
05543  * structure that has not been put in the list if the next and prev pointers are NULL.
05544  *
05545  * \return Nothing
05546  */
05547 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05548 {
05549    /* Extract from the forward chain. */
05550    if (pvt->prev) {
05551       pvt->prev->next = pvt->next;
05552    } else if (iflist == pvt) {
05553       /* Node is at the head of the list. */
05554       iflist = pvt->next;
05555    }
05556 
05557    /* Extract from the reverse chain. */
05558    if (pvt->next) {
05559       pvt->next->prev = pvt->prev;
05560    } else if (ifend == pvt) {
05561       /* Node is at the end of the list. */
05562       ifend = pvt->prev;
05563    }
05564 
05565    /* Node is no longer in the list. */
05566    pvt->which_iflist = DAHDI_IFLIST_NONE;
05567    pvt->prev = NULL;
05568    pvt->next = NULL;
05569 }
05570 
05571 #if defined(HAVE_PRI)
05572 /*!
05573  * \internal
05574  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05575  * \since 1.8
05576  *
05577  * \param pri sig_pri span control structure holding no B channel list.
05578  * \param pvt chan_dahdi private interface structure to insert.
05579  *
05580  * \details
05581  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05582  * Any duplicates are inserted after the existing entries.
05583  *
05584  * \note The new interface must not already be in the list.
05585  *
05586  * \return Nothing
05587  */
05588 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05589 {
05590    struct dahdi_pvt *cur;
05591 
05592    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05593 
05594    /* Find place in middle of list for the new interface. */
05595    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05596       if (pvt->channel < cur->channel) {
05597          /* New interface goes before the current interface. */
05598          pvt->prev = cur->prev;
05599          pvt->next = cur;
05600          if (cur->prev) {
05601             /* Insert into the middle of the list. */
05602             cur->prev->next = pvt;
05603          } else {
05604             /* Insert at head of list. */
05605             pri->no_b_chan_iflist = pvt;
05606          }
05607          cur->prev = pvt;
05608          return;
05609       }
05610    }
05611 
05612    /* New interface goes onto the end of the list */
05613    pvt->prev = pri->no_b_chan_end;
05614    pvt->next = NULL;
05615    if (pri->no_b_chan_end) {
05616       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05617    }
05618    pri->no_b_chan_end = pvt;
05619    if (!pri->no_b_chan_iflist) {
05620       /* List was empty */
05621       pri->no_b_chan_iflist = pvt;
05622    }
05623 }
05624 #endif   /* defined(HAVE_PRI) */
05625 
05626 #if defined(HAVE_PRI)
05627 /*!
05628  * \internal
05629  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05630  * \since 1.8
05631  *
05632  * \param pri sig_pri span control structure holding no B channel list.
05633  * \param pvt chan_dahdi private interface structure to extract.
05634  *
05635  * \note
05636  * The given interface structure can be either in the interface list or a stand alone
05637  * structure that has not been put in the list if the next and prev pointers are NULL.
05638  *
05639  * \return Nothing
05640  */
05641 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05642 {
05643    /* Extract from the forward chain. */
05644    if (pvt->prev) {
05645       pvt->prev->next = pvt->next;
05646    } else if (pri->no_b_chan_iflist == pvt) {
05647       /* Node is at the head of the list. */
05648       pri->no_b_chan_iflist = pvt->next;
05649    }
05650 
05651    /* Extract from the reverse chain. */
05652    if (pvt->next) {
05653       pvt->next->prev = pvt->prev;
05654    } else if (pri->no_b_chan_end == pvt) {
05655       /* Node is at the end of the list. */
05656       pri->no_b_chan_end = pvt->prev;
05657    }
05658 
05659    /* Node is no longer in the list. */
05660    pvt->which_iflist = DAHDI_IFLIST_NONE;
05661    pvt->prev = NULL;
05662    pvt->next = NULL;
05663 }
05664 #endif   /* defined(HAVE_PRI) */
05665 
05666 #if defined(HAVE_PRI)
05667 /*!
05668  * \internal
05669  * \brief Unlink the channel interface from the PRI private pointer array.
05670  * \since 1.8
05671  *
05672  * \param pvt chan_dahdi private interface structure to unlink.
05673  *
05674  * \return Nothing
05675  */
05676 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05677 {
05678    unsigned idx;
05679    struct sig_pri_span *pri;
05680 
05681    pri = pvt->pri;
05682    if (!pri) {
05683       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05684       return;
05685    }
05686    ast_mutex_lock(&pri->lock);
05687    for (idx = 0; idx < pri->numchans; ++idx) {
05688       if (pri->pvts[idx] == pvt->sig_pvt) {
05689          pri->pvts[idx] = NULL;
05690          ast_mutex_unlock(&pri->lock);
05691          return;
05692       }
05693    }
05694    ast_mutex_unlock(&pri->lock);
05695 }
05696 #endif   /* defined(HAVE_PRI) */
05697 
05698 #if defined(HAVE_SS7)
05699 /*!
05700  * \internal
05701  * \brief Unlink the channel interface from the SS7 private pointer array.
05702  * \since 1.8
05703  *
05704  * \param pvt chan_dahdi private interface structure to unlink.
05705  *
05706  * \return Nothing
05707  */
05708 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05709 {
05710    unsigned idx;
05711    struct sig_ss7_linkset *ss7;
05712 
05713    ss7 = pvt->ss7;
05714    if (!ss7) {
05715       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05716       return;
05717    }
05718    ast_mutex_lock(&ss7->lock);
05719    for (idx = 0; idx < ss7->numchans; ++idx) {
05720       if (ss7->pvts[idx] == pvt->sig_pvt) {
05721          ss7->pvts[idx] = NULL;
05722          ast_mutex_unlock(&ss7->lock);
05723          return;
05724       }
05725    }
05726    ast_mutex_unlock(&ss7->lock);
05727 }
05728 #endif   /* defined(HAVE_SS7) */
05729 
05730 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05731 {
05732    if (cur->next && cur->next->span == cur->span) {
05733       return cur->next;
05734    } else if (cur->prev && cur->prev->span == cur->span) {
05735       return cur->prev;
05736    }
05737 
05738    return NULL;
05739 }
05740 
05741 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05742 {
05743    struct dahdi_pvt *p = pvt;
05744 
05745    if (p->manages_span_alarms) {
05746       struct dahdi_pvt *next = find_next_iface_in_span(p);
05747       if (next) {
05748          next->manages_span_alarms = 1;
05749       }
05750    }
05751 
05752    /* Remove channel from the list */
05753 #if defined(HAVE_PRI)
05754    dahdi_unlink_pri_pvt(p);
05755 #endif   /* defined(HAVE_PRI) */
05756 #if defined(HAVE_SS7)
05757    dahdi_unlink_ss7_pvt(p);
05758 #endif   /* defined(HAVE_SS7) */
05759    switch (pvt->which_iflist) {
05760    case DAHDI_IFLIST_NONE:
05761       break;
05762    case DAHDI_IFLIST_MAIN:
05763       dahdi_iflist_extract(p);
05764       break;
05765 #if defined(HAVE_PRI)
05766    case DAHDI_IFLIST_NO_B_CHAN:
05767       if (p->pri) {
05768          dahdi_nobch_extract(p->pri, p);
05769       }
05770       break;
05771 #endif   /* defined(HAVE_PRI) */
05772    }
05773 
05774    if (p->sig_pvt) {
05775       if (analog_lib_handles(p->sig, 0, 0)) {
05776          analog_delete(p->sig_pvt);
05777       }
05778       switch (p->sig) {
05779 #if defined(HAVE_PRI)
05780       case SIG_PRI_LIB_HANDLE_CASES:
05781          sig_pri_chan_delete(p->sig_pvt);
05782          break;
05783 #endif   /* defined(HAVE_PRI) */
05784 #if defined(HAVE_SS7)
05785       case SIG_SS7:
05786          sig_ss7_chan_delete(p->sig_pvt);
05787          break;
05788 #endif   /* defined(HAVE_SS7) */
05789       default:
05790          break;
05791       }
05792    }
05793    ast_free(p->cidspill);
05794    if (p->use_smdi)
05795       ast_smdi_interface_unref(p->smdi_iface);
05796    if (p->mwi_event_sub)
05797       ast_event_unsubscribe(p->mwi_event_sub);
05798    if (p->vars) {
05799       ast_variables_destroy(p->vars);
05800    }
05801    if (p->cc_params) {
05802       ast_cc_config_params_destroy(p->cc_params);
05803    }
05804    ast_mutex_destroy(&p->lock);
05805    dahdi_close_sub(p, SUB_REAL);
05806    if (p->owner)
05807       p->owner->tech_pvt = NULL;
05808    ast_free(p);
05809 }
05810 
05811 static void destroy_channel(struct dahdi_pvt *cur, int now)
05812 {
05813    int i;
05814 
05815    if (!now) {
05816       /* Do not destroy the channel now if it is owned by someone. */
05817       if (cur->owner) {
05818          return;
05819       }
05820       for (i = 0; i < 3; i++) {
05821          if (cur->subs[i].owner) {
05822             return;
05823          }
05824       }
05825    }
05826    destroy_dahdi_pvt(cur);
05827 }
05828 
05829 static void destroy_all_channels(void)
05830 {
05831    int chan;
05832 #if defined(HAVE_PRI)
05833    unsigned span;
05834    struct sig_pri_span *pri;
05835 #endif   /* defined(HAVE_PRI) */
05836    struct dahdi_pvt *p;
05837 
05838    while (num_restart_pending) {
05839       usleep(1);
05840    }
05841 
05842    ast_mutex_lock(&iflock);
05843    /* Destroy all the interfaces and free their memory */
05844    while (iflist) {
05845       p = iflist;
05846 
05847       chan = p->channel;
05848 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05849       {
05850          char db_chan_name[20];
05851          char db_answer[5];
05852          char state;
05853          int why = -1;
05854 
05855          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05856          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05857             sscanf(db_answer, "%1c:%30d", &state, &why);
05858          }
05859          if (!why) {
05860             /* SRVST persistence is not required */
05861             ast_db_del(db_chan_name, SRVST_DBKEY);
05862          }
05863       }
05864 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05865       /* Free associated memory */
05866       destroy_dahdi_pvt(p);
05867       ast_verb(3, "Unregistered channel %d\n", chan);
05868    }
05869    ifcount = 0;
05870    ast_mutex_unlock(&iflock);
05871 
05872 #if defined(HAVE_PRI)
05873    /* Destroy all of the no B channel interface lists */
05874    for (span = 0; span < NUM_SPANS; ++span) {
05875       if (!pris[span].dchannels[0]) {
05876          break;
05877       }
05878       pri = &pris[span].pri;
05879       ast_mutex_lock(&pri->lock);
05880       while (pri->no_b_chan_iflist) {
05881          p = pri->no_b_chan_iflist;
05882 
05883          /* Free associated memory */
05884          destroy_dahdi_pvt(p);
05885       }
05886       ast_mutex_unlock(&pri->lock);
05887    }
05888 #endif   /* defined(HAVE_PRI) */
05889 }
05890 
05891 #if defined(HAVE_PRI)
05892 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05893 
05894 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05895 {
05896    /* Data will be our digit string */
05897    struct dahdi_pvt *p;
05898 
05899    if (ast_strlen_zero(digits)) {
05900       ast_debug(1, "No digit string sent to application!\n");
05901       return -1;
05902    }
05903 
05904    p = (struct dahdi_pvt *)chan->tech_pvt;
05905 
05906    if (!p) {
05907       ast_debug(1, "Unable to find technology private\n");
05908       return -1;
05909    }
05910 
05911    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05912 
05913    return 0;
05914 }
05915 #endif   /* defined(HAVE_PRI) */
05916 
05917 #if defined(HAVE_PRI)
05918 #if defined(HAVE_PRI_PROG_W_CAUSE)
05919 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05920 
05921 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05922 {
05923    /* Data will be our digit string */
05924    struct dahdi_pvt *pvt;
05925    char *parse;
05926    int res;
05927    AST_DECLARE_APP_ARGS(args,
05928       AST_APP_ARG(destination);
05929       AST_APP_ARG(original);
05930       AST_APP_ARG(reason);
05931    );
05932 
05933    if (ast_strlen_zero(data)) {
05934       ast_log(LOG_DEBUG, "No data sent to application!\n");
05935       return -1;
05936    }
05937    if (chan->tech != &dahdi_tech) {
05938       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05939       return -1;
05940    }
05941    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05942    if (!pvt) {
05943       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05944       return -1;
05945    }
05946    switch (pvt->sig) {
05947    case SIG_PRI_LIB_HANDLE_CASES:
05948       break;
05949    default:
05950       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05951          chan->name);
05952       return -1;
05953    }
05954 
05955    parse = ast_strdupa(data);
05956    AST_STANDARD_APP_ARGS(args, parse);
05957 
05958    if (ast_strlen_zero(args.destination)) {
05959       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05960       return -1;
05961    }
05962 
05963    if (ast_strlen_zero(args.original)) {
05964       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05965       args.original = NULL;
05966    }
05967 
05968    if (ast_strlen_zero(args.reason)) {
05969       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05970       args.reason = NULL;
05971    }
05972 
05973    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05974       args.destination, args.original, args.reason);
05975    if (!res) {
05976       /*
05977        * Wait up to 5 seconds for a reply before hanging up this call
05978        * leg if the peer does not disconnect first.
05979        */
05980       ast_safe_sleep(chan, 5000);
05981    }
05982 
05983    return -1;
05984 }
05985 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05986 #endif   /* defined(HAVE_PRI) */
05987 
05988 #if defined(HAVE_OPENR2)
05989 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05990 
05991 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05992 {
05993    /* data is whether to accept with charge or no charge */
05994    openr2_call_mode_t accept_mode;
05995    int res, timeout, maxloops;
05996    struct ast_frame *f;
05997    struct dahdi_pvt *p;
05998    char *parse;
05999    AST_DECLARE_APP_ARGS(args,
06000          AST_APP_ARG(charge);
06001    );
06002 
06003    if (ast_strlen_zero(data)) {
06004       ast_log(LOG_DEBUG, "No data sent to application!\n");
06005       return -1;
06006    }
06007 
06008    if (chan->tech != &dahdi_tech) {
06009       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06010       return -1;
06011    }
06012 
06013    p = (struct dahdi_pvt *)chan->tech_pvt;
06014    if (!p) {
06015       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06016       return -1;
06017    }
06018 
06019    parse = ast_strdupa(data);
06020    AST_STANDARD_APP_ARGS(args, parse);
06021 
06022    if (ast_strlen_zero(args.charge)) {
06023       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06024       return -1;
06025    }
06026 
06027    ast_mutex_lock(&p->lock);
06028    if (!p->mfcr2 || !p->mfcr2call) {
06029       ast_mutex_unlock(&p->lock);
06030       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06031       return -1;
06032    }
06033 
06034    if (p->mfcr2_call_accepted) {
06035       ast_mutex_unlock(&p->lock);
06036       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06037       return 0;
06038    }
06039    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06040    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06041       ast_mutex_unlock(&p->lock);
06042       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06043       return -1;
06044    }
06045    ast_mutex_unlock(&p->lock);
06046 
06047    res = 0;
06048    timeout = 100;
06049    maxloops = 50; /* wait up to 5 seconds */
06050    /* we need to read() until the call is accepted */
06051    while (maxloops > 0) {
06052       maxloops--;
06053       if (ast_check_hangup(chan)) {
06054          break;
06055       }
06056       res = ast_waitfor(chan, timeout);
06057       if (res < 0) {
06058          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06059          res = -1;
06060          break;
06061       }
06062       if (res == 0) {
06063          continue;
06064       }
06065       f = ast_read(chan);
06066       if (!f) {
06067          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06068          res = -1;
06069          break;
06070       }
06071       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06072          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06073          ast_frfree(f);
06074          res = -1;
06075          break;
06076       }
06077       ast_frfree(f);
06078       ast_mutex_lock(&p->lock);
06079       if (p->mfcr2_call_accepted) {
06080          ast_mutex_unlock(&p->lock);
06081          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06082          break;
06083       }
06084       ast_mutex_unlock(&p->lock);
06085    }
06086    if (res == -1) {
06087       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06088    }
06089    return res;
06090 }
06091 
06092 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06093 {
06094    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06095    switch (cause) {
06096    case AST_CAUSE_USER_BUSY:
06097    case AST_CAUSE_CALL_REJECTED:
06098    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06099       r2cause = OR2_CAUSE_BUSY_NUMBER;
06100       break;
06101 
06102    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06103    case AST_CAUSE_SWITCH_CONGESTION:
06104       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06105       break;
06106 
06107    case AST_CAUSE_UNALLOCATED:
06108       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06109       break;
06110 
06111    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06112    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06113       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06114       break;
06115 
06116    case AST_CAUSE_NO_ANSWER:
06117    case AST_CAUSE_NO_USER_RESPONSE:
06118       r2cause = OR2_CAUSE_NO_ANSWER;
06119       break;
06120 
06121    default:
06122       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06123       break;
06124    }
06125    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06126          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06127    return r2cause;
06128 }
06129 #endif
06130 
06131 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06132 {
06133    if (p->bufferoverrideinuse) {
06134       /* faxbuffers are in use, revert them */
06135       struct dahdi_bufferinfo bi = {
06136          .txbufpolicy = p->buf_policy,
06137          .rxbufpolicy = p->buf_policy,
06138          .bufsize = p->bufsize,
06139          .numbufs = p->buf_no
06140       };
06141       int bpres;
06142 
06143       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06144          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06145       }
06146       p->bufferoverrideinuse = 0;
06147       return bpres;
06148    }
06149 
06150    return -1;
06151 }
06152 
06153 static int dahdi_hangup(struct ast_channel *ast)
06154 {
06155    int res = 0;
06156    int idx,x;
06157    int law;
06158    /*static int restore_gains(struct dahdi_pvt *p);*/
06159    struct dahdi_pvt *p = ast->tech_pvt;
06160    struct dahdi_params par;
06161 
06162    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06163    if (!ast->tech_pvt) {
06164       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06165       return 0;
06166    }
06167 
06168    ast_mutex_lock(&p->lock);
06169    p->exten[0] = '\0';
06170    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06171       dahdi_confmute(p, 0);
06172       restore_gains(p);
06173       p->ignoredtmf = 0;
06174       p->waitingfordt.tv_sec = 0;
06175 
06176       res = analog_hangup(p->sig_pvt, ast);
06177       revert_fax_buffers(p, ast);
06178 
06179       goto hangup_out;
06180    } else {
06181       p->cid_num[0] = '\0';
06182       p->cid_name[0] = '\0';
06183       p->cid_subaddr[0] = '\0';
06184    }
06185 
06186 #if defined(HAVE_PRI)
06187    if (dahdi_sig_pri_lib_handles(p->sig)) {
06188       x = 1;
06189       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06190 
06191       dahdi_confmute(p, 0);
06192       p->muting = 0;
06193       restore_gains(p);
06194       if (p->dsp) {
06195          ast_dsp_free(p->dsp);
06196          p->dsp = NULL;
06197       }
06198       p->ignoredtmf = 0;
06199 
06200       /* Real channel, do some fixup */
06201       p->subs[SUB_REAL].owner = NULL;
06202       p->subs[SUB_REAL].needbusy = 0;
06203       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06204 
06205       p->owner = NULL;
06206       p->cid_tag[0] = '\0';
06207       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06208       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06209       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06210       p->outgoing = 0;
06211       p->digital = 0;
06212       p->faxhandled = 0;
06213       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06214 
06215       revert_fax_buffers(p, ast);
06216 
06217       p->law = p->law_default;
06218       law = p->law_default;
06219       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06220       if (res < 0) {
06221          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06222             p->channel, strerror(errno));
06223       }
06224 
06225       sig_pri_hangup(p->sig_pvt, ast);
06226 
06227       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06228       dahdi_disable_ec(p);
06229 
06230       x = 0;
06231       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06232       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06233 
06234       p->rdnis[0] = '\0';
06235       update_conf(p);
06236       reset_conf(p);
06237 
06238       /* Restore data mode */
06239       x = 0;
06240       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06241 
06242       if (num_restart_pending == 0) {
06243          restart_monitor();
06244       }
06245       goto hangup_out;
06246    }
06247 #endif   /* defined(HAVE_PRI) */
06248 
06249 #if defined(HAVE_SS7)
06250    if (p->sig == SIG_SS7) {
06251       x = 1;
06252       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06253 
06254       dahdi_confmute(p, 0);
06255       p->muting = 0;
06256       restore_gains(p);
06257       if (p->dsp) {
06258          ast_dsp_free(p->dsp);
06259          p->dsp = NULL;
06260       }
06261       p->ignoredtmf = 0;
06262 
06263       /* Real channel, do some fixup */
06264       p->subs[SUB_REAL].owner = NULL;
06265       p->subs[SUB_REAL].needbusy = 0;
06266       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06267 
06268       p->owner = NULL;
06269       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06270       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06271       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06272       p->outgoing = 0;
06273       p->digital = 0;
06274       p->faxhandled = 0;
06275       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06276 
06277       revert_fax_buffers(p, ast);
06278 
06279       p->law = p->law_default;
06280       law = p->law_default;
06281       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06282       if (res < 0) {
06283          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06284             p->channel, strerror(errno));
06285       }
06286 
06287       sig_ss7_hangup(p->sig_pvt, ast);
06288 
06289       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06290       dahdi_disable_ec(p);
06291 
06292       x = 0;
06293       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06294       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06295 
06296       update_conf(p);
06297       reset_conf(p);
06298 
06299       /* Restore data mode */
06300       x = 0;
06301       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06302 
06303       if (num_restart_pending == 0) {
06304          restart_monitor();
06305       }
06306       goto hangup_out;
06307    }
06308 #endif   /* defined(HAVE_SS7) */
06309 
06310    idx = dahdi_get_index(ast, p, 1);
06311 
06312    dahdi_confmute(p, 0);
06313    p->muting = 0;
06314    restore_gains(p);
06315    if (p->origcid_num) {
06316       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06317       ast_free(p->origcid_num);
06318       p->origcid_num = NULL;
06319    }
06320    if (p->origcid_name) {
06321       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06322       ast_free(p->origcid_name);
06323       p->origcid_name = NULL;
06324    }
06325    if (p->dsp)
06326       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06327 
06328    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06329       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06330    p->ignoredtmf = 0;
06331 
06332    if (idx > -1) {
06333       /* Real channel, do some fixup */
06334       p->subs[idx].owner = NULL;
06335       p->subs[idx].needanswer = 0;
06336       p->subs[idx].needflash = 0;
06337       p->subs[idx].needringing = 0;
06338       p->subs[idx].needbusy = 0;
06339       p->subs[idx].needcongestion = 0;
06340       p->subs[idx].linear = 0;
06341       p->polarity = POLARITY_IDLE;
06342       dahdi_setlinear(p->subs[idx].dfd, 0);
06343       if (idx == SUB_REAL) {
06344          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06345             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06346             if (p->subs[SUB_CALLWAIT].inthreeway) {
06347                /* We had flipped over to answer a callwait and now it's gone */
06348                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06349                /* Move to the call-wait, but un-own us until they flip back. */
06350                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06351                unalloc_sub(p, SUB_CALLWAIT);
06352                p->owner = NULL;
06353             } else {
06354                /* The three way hung up, but we still have a call wait */
06355                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06356                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06357                unalloc_sub(p, SUB_THREEWAY);
06358                if (p->subs[SUB_REAL].inthreeway) {
06359                   /* This was part of a three way call.  Immediately make way for
06360                      another call */
06361                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06362                   p->owner = p->subs[SUB_REAL].owner;
06363                } else {
06364                   /* This call hasn't been completed yet...  Set owner to NULL */
06365                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06366                   p->owner = NULL;
06367                }
06368                p->subs[SUB_REAL].inthreeway = 0;
06369             }
06370          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06371             /* Move to the call-wait and switch back to them. */
06372             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06373             unalloc_sub(p, SUB_CALLWAIT);
06374             p->owner = p->subs[SUB_REAL].owner;
06375             if (p->owner->_state != AST_STATE_UP)
06376                p->subs[SUB_REAL].needanswer = 1;
06377             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06378                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06379          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06380             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06381             unalloc_sub(p, SUB_THREEWAY);
06382             if (p->subs[SUB_REAL].inthreeway) {
06383                /* This was part of a three way call.  Immediately make way for
06384                   another call */
06385                ast_debug(1, "Call was complete, setting owner to former third call\n");
06386                p->owner = p->subs[SUB_REAL].owner;
06387             } else {
06388                /* This call hasn't been completed yet...  Set owner to NULL */
06389                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06390                p->owner = NULL;
06391             }
06392             p->subs[SUB_REAL].inthreeway = 0;
06393          }
06394       } else if (idx == SUB_CALLWAIT) {
06395          /* Ditch the holding callwait call, and immediately make it availabe */
06396          if (p->subs[SUB_CALLWAIT].inthreeway) {
06397             /* This is actually part of a three way, placed on hold.  Place the third part
06398                on music on hold now */
06399             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06400                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06401                   S_OR(p->mohsuggest, NULL),
06402                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06403             }
06404             p->subs[SUB_THREEWAY].inthreeway = 0;
06405             /* Make it the call wait now */
06406             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06407             unalloc_sub(p, SUB_THREEWAY);
06408          } else
06409             unalloc_sub(p, SUB_CALLWAIT);
06410       } else if (idx == SUB_THREEWAY) {
06411          if (p->subs[SUB_CALLWAIT].inthreeway) {
06412             /* The other party of the three way call is currently in a call-wait state.
06413                Start music on hold for them, and take the main guy out of the third call */
06414             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06415                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06416                   S_OR(p->mohsuggest, NULL),
06417                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06418             }
06419             p->subs[SUB_CALLWAIT].inthreeway = 0;
06420          }
06421          p->subs[SUB_REAL].inthreeway = 0;
06422          /* If this was part of a three way call index, let us make
06423             another three way call */
06424          unalloc_sub(p, SUB_THREEWAY);
06425       } else {
06426          /* This wasn't any sort of call, but how are we an index? */
06427          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06428       }
06429    }
06430 
06431    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06432       p->owner = NULL;
06433       p->ringt = 0;
06434       p->distinctivering = 0;
06435       p->confirmanswer = 0;
06436       p->outgoing = 0;
06437       p->digital = 0;
06438       p->faxhandled = 0;
06439       p->pulsedial = 0;
06440       if (p->dsp) {
06441          ast_dsp_free(p->dsp);
06442          p->dsp = NULL;
06443       }
06444 
06445       revert_fax_buffers(p, ast);
06446 
06447       p->law = p->law_default;
06448       law = p->law_default;
06449       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06450       if (res < 0)
06451          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06452       /* Perform low level hangup if no owner left */
06453 #ifdef HAVE_OPENR2
06454       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06455          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06456          /* If it's an incoming call, check the mfcr2_forced_release setting */
06457          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06458             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06459          } else {
06460             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06461             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06462             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06463                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06464             dahdi_r2_disconnect_call(p, r2cause);
06465          }
06466       } else if (p->mfcr2call) {
06467          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06468          /* since ast_request() was called but not ast_call() we have not yet dialed
06469          and the openr2 stack will not call on_call_end callback, we need to unset
06470          the mfcr2call flag and bump the monitor count so the monitor thread can take
06471          care of this channel events from now on */
06472          p->mfcr2call = 0;
06473       }
06474 #endif
06475       switch (p->sig) {
06476       case SIG_SS7:
06477       case SIG_MFCR2:
06478       case SIG_PRI_LIB_HANDLE_CASES:
06479       case 0:
06480          break;
06481       default:
06482          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06483          break;
06484       }
06485       if (res < 0) {
06486          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06487       }
06488       switch (p->sig) {
06489       case SIG_FXOGS:
06490       case SIG_FXOLS:
06491       case SIG_FXOKS:
06492          memset(&par, 0, sizeof(par));
06493          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06494          if (!res) {
06495             struct analog_pvt *analog_p = p->sig_pvt;
06496 #if 0
06497             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06498 #endif
06499             /* If they're off hook, try playing congestion */
06500             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06501                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06502             else
06503                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06504             analog_p->fxsoffhookstate = par.rxisoffhook;
06505          }
06506          break;
06507       case SIG_FXSGS:
06508       case SIG_FXSLS:
06509       case SIG_FXSKS:
06510          /* Make sure we're not made available for at least two seconds assuming
06511          we were actually used for an inbound or outbound call. */
06512          if (ast->_state != AST_STATE_RESERVED) {
06513             time(&p->guardtime);
06514             p->guardtime += 2;
06515          }
06516          break;
06517       default:
06518          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06519          break;
06520       }
06521       if (p->sig)
06522          dahdi_disable_ec(p);
06523       x = 0;
06524       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06525       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06526       p->didtdd = 0;
06527       p->callwaitcas = 0;
06528       p->callwaiting = p->permcallwaiting;
06529       p->hidecallerid = p->permhidecallerid;
06530       p->waitingfordt.tv_sec = 0;
06531       p->dialing = 0;
06532       p->rdnis[0] = '\0';
06533       update_conf(p);
06534       reset_conf(p);
06535       /* Restore data mode */
06536       switch (p->sig) {
06537       case SIG_PRI_LIB_HANDLE_CASES:
06538       case SIG_SS7:
06539          x = 0;
06540          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06541          break;
06542       default:
06543          break;
06544       }
06545       if (num_restart_pending == 0)
06546          restart_monitor();
06547    }
06548 
06549    p->callwaitingrepeat = 0;
06550    p->cidcwexpire = 0;
06551    p->cid_suppress_expire = 0;
06552    p->oprmode = 0;
06553 hangup_out:
06554    ast->tech_pvt = NULL;
06555    ast_free(p->cidspill);
06556    p->cidspill = NULL;
06557 
06558    ast_mutex_unlock(&p->lock);
06559    ast_verb(3, "Hungup '%s'\n", ast->name);
06560 
06561    ast_mutex_lock(&iflock);
06562    if (p->restartpending) {
06563       num_restart_pending--;
06564    }
06565 
06566    if (p->destroy) {
06567       destroy_channel(p, 0);
06568    }
06569    ast_mutex_unlock(&iflock);
06570 
06571    ast_module_unref(ast_module_info->self);
06572    return 0;
06573 }
06574 
06575 static int dahdi_answer(struct ast_channel *ast)
06576 {
06577    struct dahdi_pvt *p = ast->tech_pvt;
06578    int res = 0;
06579    int idx;
06580    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06581    ast_mutex_lock(&p->lock);
06582    idx = dahdi_get_index(ast, p, 0);
06583    if (idx < 0)
06584       idx = SUB_REAL;
06585    /* nothing to do if a radio channel */
06586    if ((p->radio || (p->oprmode < 0))) {
06587       ast_mutex_unlock(&p->lock);
06588       return 0;
06589    }
06590 
06591    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06592       res = analog_answer(p->sig_pvt, ast);
06593       ast_mutex_unlock(&p->lock);
06594       return res;
06595    }
06596 
06597    switch (p->sig) {
06598 #if defined(HAVE_PRI)
06599    case SIG_PRI_LIB_HANDLE_CASES:
06600       res = sig_pri_answer(p->sig_pvt, ast);
06601       break;
06602 #endif   /* defined(HAVE_PRI) */
06603 #if defined(HAVE_SS7)
06604    case SIG_SS7:
06605       res = sig_ss7_answer(p->sig_pvt, ast);
06606       break;
06607 #endif   /* defined(HAVE_SS7) */
06608 #ifdef HAVE_OPENR2
06609    case SIG_MFCR2:
06610       if (!p->mfcr2_call_accepted) {
06611          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06612             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06613          p->mfcr2_answer_pending = 1;
06614          if (p->mfcr2_charge_calls) {
06615             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06616             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06617          } else {
06618             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06619             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06620          }
06621       } else {
06622          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06623          dahdi_r2_answer(p);
06624       }
06625       break;
06626 #endif
06627    case 0:
06628       ast_mutex_unlock(&p->lock);
06629       return 0;
06630    default:
06631       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06632       res = -1;
06633       break;
06634    }
06635    ast_mutex_unlock(&p->lock);
06636    return res;
06637 }
06638 
06639 static void disable_dtmf_detect(struct dahdi_pvt *p)
06640 {
06641    int val = 0;
06642 
06643    p->ignoredtmf = 1;
06644 
06645    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06646 
06647    if (!p->hardwaredtmf && p->dsp) {
06648       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06649       ast_dsp_set_features(p->dsp, p->dsp_features);
06650    }
06651 }
06652 
06653 static void enable_dtmf_detect(struct dahdi_pvt *p)
06654 {
06655    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06656 
06657    if (p->channel == CHAN_PSEUDO)
06658       return;
06659 
06660    p->ignoredtmf = 0;
06661 
06662    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06663 
06664    if (!p->hardwaredtmf && p->dsp) {
06665       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06666       ast_dsp_set_features(p->dsp, p->dsp_features);
06667    }
06668 }
06669 
06670 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06671 {
06672    char *cp;
06673    struct dahdi_pvt *p = chan->tech_pvt;
06674 
06675    /* all supported options require data */
06676    if (!p || !data || (*datalen < 1)) {
06677       errno = EINVAL;
06678       return -1;
06679    }
06680 
06681    switch (option) {
06682    case AST_OPTION_DIGIT_DETECT:
06683       cp = (char *) data;
06684       *cp = p->ignoredtmf ? 0 : 1;
06685       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06686       break;
06687    case AST_OPTION_FAX_DETECT:
06688       cp = (char *) data;
06689       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06690       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06691       break;
06692    case AST_OPTION_CC_AGENT_TYPE:
06693 #if defined(HAVE_PRI)
06694 #if defined(HAVE_PRI_CCSS)
06695       if (dahdi_sig_pri_lib_handles(p->sig)) {
06696          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06697          break;
06698       }
06699 #endif   /* defined(HAVE_PRI_CCSS) */
06700 #endif   /* defined(HAVE_PRI) */
06701       return -1;
06702    default:
06703       return -1;
06704    }
06705 
06706    errno = 0;
06707 
06708    return 0;
06709 }
06710 
06711 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06712 {
06713    char *cp;
06714    signed char *scp;
06715    int x;
06716    int idx;
06717    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06718    struct oprmode *oprmode;
06719 
06720 
06721    /* all supported options require data */
06722    if (!p || !data || (datalen < 1)) {
06723       errno = EINVAL;
06724       return -1;
06725    }
06726 
06727    switch (option) {
06728    case AST_OPTION_TXGAIN:
06729       scp = (signed char *) data;
06730       idx = dahdi_get_index(chan, p, 0);
06731       if (idx < 0) {
06732          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06733          return -1;
06734       }
06735       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06736       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06737    case AST_OPTION_RXGAIN:
06738       scp = (signed char *) data;
06739       idx = dahdi_get_index(chan, p, 0);
06740       if (idx < 0) {
06741          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06742          return -1;
06743       }
06744       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06745       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06746    case AST_OPTION_TONE_VERIFY:
06747       if (!p->dsp)
06748          break;
06749       cp = (char *) data;
06750       switch (*cp) {
06751       case 1:
06752          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06753          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06754          break;
06755       case 2:
06756          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06757          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06758          break;
06759       default:
06760          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06761          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06762          break;
06763       }
06764       break;
06765    case AST_OPTION_TDD:
06766       /* turn on or off TDD */
06767       cp = (char *) data;
06768       p->mate = 0;
06769       if (!*cp) { /* turn it off */
06770          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06771          if (p->tdd)
06772             tdd_free(p->tdd);
06773          p->tdd = 0;
06774          break;
06775       }
06776       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06777          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06778       dahdi_disable_ec(p);
06779       /* otherwise, turn it on */
06780       if (!p->didtdd) { /* if havent done it yet */
06781          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06782          unsigned char *buf;
06783          int size, res, fd, len;
06784          struct pollfd fds[1];
06785 
06786          buf = mybuf;
06787          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06788          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06789          len = 40000;
06790          idx = dahdi_get_index(chan, p, 0);
06791          if (idx < 0) {
06792             ast_log(LOG_WARNING, "No index in TDD?\n");
06793             return -1;
06794          }
06795          fd = p->subs[idx].dfd;
06796          while (len) {
06797             if (ast_check_hangup(chan))
06798                return -1;
06799             size = len;
06800             if (size > READ_SIZE)
06801                size = READ_SIZE;
06802             fds[0].fd = fd;
06803             fds[0].events = POLLPRI | POLLOUT;
06804             fds[0].revents = 0;
06805             res = poll(fds, 1, -1);
06806             if (!res) {
06807                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06808                continue;
06809             }
06810             /* if got exception */
06811             if (fds[0].revents & POLLPRI)
06812                return -1;
06813             if (!(fds[0].revents & POLLOUT)) {
06814                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06815                continue;
06816             }
06817             res = write(fd, buf, size);
06818             if (res != size) {
06819                if (res == -1) return -1;
06820                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06821                break;
06822             }
06823             len -= size;
06824             buf += size;
06825          }
06826          p->didtdd = 1; /* set to have done it now */
06827       }
06828       if (*cp == 2) { /* Mate mode */
06829          if (p->tdd)
06830             tdd_free(p->tdd);
06831          p->tdd = 0;
06832          p->mate = 1;
06833          break;
06834       }
06835       if (!p->tdd) { /* if we don't have one yet */
06836          p->tdd = tdd_new(); /* allocate one */
06837       }
06838       break;
06839    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06840       if (!p->dsp)
06841          break;
06842       cp = (char *) data;
06843       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06844          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06845       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06846       break;
06847    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06848 #if defined(HAVE_PRI)
06849       if (dahdi_sig_pri_lib_handles(p->sig)
06850          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06851          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06852          break;
06853       }
06854 #endif   /* defined(HAVE_PRI) */
06855 
06856       cp = (char *) data;
06857       if (!*cp) {
06858          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06859          x = 0;
06860          dahdi_disable_ec(p);
06861       } else {
06862          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06863          x = 1;
06864       }
06865       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06866          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06867       break;
06868    case AST_OPTION_OPRMODE:  /* Operator services mode */
06869       oprmode = (struct oprmode *) data;
06870       /* We don't support operator mode across technologies */
06871       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06872          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06873                chan->tech->type, oprmode->peer->tech->type);
06874          errno = EINVAL;
06875          return -1;
06876       }
06877       pp = oprmode->peer->tech_pvt;
06878       p->oprmode = pp->oprmode = 0;
06879       /* setup peers */
06880       p->oprpeer = pp;
06881       pp->oprpeer = p;
06882       /* setup modes, if any */
06883       if (oprmode->mode)
06884       {
06885          pp->oprmode = oprmode->mode;
06886          p->oprmode = -oprmode->mode;
06887       }
06888       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06889          oprmode->mode, chan->name,oprmode->peer->name);
06890       break;
06891    case AST_OPTION_ECHOCAN:
06892       cp = (char *) data;
06893       if (*cp) {
06894          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06895          dahdi_enable_ec(p);
06896       } else {
06897          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06898          dahdi_disable_ec(p);
06899       }
06900       break;
06901    case AST_OPTION_DIGIT_DETECT:
06902       cp = (char *) data;
06903       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06904       if (*cp) {
06905          enable_dtmf_detect(p);
06906       } else {
06907          disable_dtmf_detect(p);
06908       }
06909       break;
06910    case AST_OPTION_FAX_DETECT:
06911       cp = (char *) data;
06912       if (p->dsp) {
06913          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06914          if (*cp) {
06915             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06916          } else {
06917             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06918          }
06919          ast_dsp_set_features(p->dsp, p->dsp_features);
06920       }
06921       break;
06922    default:
06923       return -1;
06924    }
06925    errno = 0;
06926 
06927    return 0;
06928 }
06929 
06930 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06931 {
06932    struct dahdi_pvt *p = chan->tech_pvt;
06933    int res = 0;
06934 
06935    if (!p) {
06936       /* No private structure! */
06937       *buf = '\0';
06938       return -1;
06939    }
06940 
06941    if (!strcasecmp(data, "rxgain")) {
06942       ast_mutex_lock(&p->lock);
06943       snprintf(buf, len, "%f", p->rxgain);
06944       ast_mutex_unlock(&p->lock);
06945    } else if (!strcasecmp(data, "txgain")) {
06946       ast_mutex_lock(&p->lock);
06947       snprintf(buf, len, "%f", p->txgain);
06948       ast_mutex_unlock(&p->lock);
06949    } else if (!strcasecmp(data, "dahdi_channel")) {
06950       ast_mutex_lock(&p->lock);
06951       snprintf(buf, len, "%d", p->channel);
06952       ast_mutex_unlock(&p->lock);
06953    } else if (!strcasecmp(data, "dahdi_span")) {
06954       ast_mutex_lock(&p->lock);
06955       snprintf(buf, len, "%d", p->span);
06956       ast_mutex_unlock(&p->lock);
06957    } else if (!strcasecmp(data, "dahdi_type")) {
06958       ast_mutex_lock(&p->lock);
06959       switch (p->sig) {
06960 #if defined(HAVE_OPENR2)
06961       case SIG_MFCR2:
06962          ast_copy_string(buf, "mfc/r2", len);
06963          break;
06964 #endif   /* defined(HAVE_OPENR2) */
06965 #if defined(HAVE_PRI)
06966       case SIG_PRI_LIB_HANDLE_CASES:
06967          ast_copy_string(buf, "pri", len);
06968          break;
06969 #endif   /* defined(HAVE_PRI) */
06970       case 0:
06971          ast_copy_string(buf, "pseudo", len);
06972          break;
06973 #if defined(HAVE_SS7)
06974       case SIG_SS7:
06975          ast_copy_string(buf, "ss7", len);
06976          break;
06977 #endif   /* defined(HAVE_SS7) */
06978       default:
06979          /* The only thing left is analog ports. */
06980          ast_copy_string(buf, "analog", len);
06981          break;
06982       }
06983       ast_mutex_unlock(&p->lock);
06984 #if defined(HAVE_PRI)
06985 #if defined(HAVE_PRI_REVERSE_CHARGE)
06986    } else if (!strcasecmp(data, "reversecharge")) {
06987       ast_mutex_lock(&p->lock);
06988       switch (p->sig) {
06989       case SIG_PRI_LIB_HANDLE_CASES:
06990          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06991          break;
06992       default:
06993          *buf = '\0';
06994          res = -1;
06995          break;
06996       }
06997       ast_mutex_unlock(&p->lock);
06998 #endif
06999 #if defined(HAVE_PRI_SETUP_KEYPAD)
07000    } else if (!strcasecmp(data, "keypad_digits")) {
07001       ast_mutex_lock(&p->lock);
07002       switch (p->sig) {
07003       case SIG_PRI_LIB_HANDLE_CASES:
07004          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07005             len);
07006          break;
07007       default:
07008          *buf = '\0';
07009          res = -1;
07010          break;
07011       }
07012       ast_mutex_unlock(&p->lock);
07013 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07014    } else if (!strcasecmp(data, "no_media_path")) {
07015       ast_mutex_lock(&p->lock);
07016       switch (p->sig) {
07017       case SIG_PRI_LIB_HANDLE_CASES:
07018          /*
07019           * TRUE if the call is on hold or is call waiting because
07020           * there is no media path available.
07021           */
07022          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07023          break;
07024       default:
07025          *buf = '\0';
07026          res = -1;
07027          break;
07028       }
07029       ast_mutex_unlock(&p->lock);
07030 #endif   /* defined(HAVE_PRI) */
07031    } else {
07032       *buf = '\0';
07033       res = -1;
07034    }
07035 
07036    return res;
07037 }
07038 
07039 
07040 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07041 {
07042    int res;
07043    char policy_str[21] = "";
07044 
07045    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07046       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07047       return 1;
07048    }
07049    if (*num_buffers < 0) {
07050       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07051       return -1;
07052    }
07053    if (!strcasecmp(policy_str, "full")) {
07054       *policy = DAHDI_POLICY_WHEN_FULL;
07055    } else if (!strcasecmp(policy_str, "immediate")) {
07056       *policy = DAHDI_POLICY_IMMEDIATE;
07057 #if defined(HAVE_DAHDI_HALF_FULL)
07058    } else if (!strcasecmp(policy_str, "half")) {
07059       *policy = DAHDI_POLICY_HALF_FULL;
07060 #endif
07061    } else {
07062       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07063       return -1;
07064    }
07065 
07066    return 0;
07067 }
07068 
07069 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07070 {
07071    struct dahdi_pvt *p = chan->tech_pvt;
07072    int res = 0;
07073 
07074    if (!p) {
07075       /* No private structure! */
07076       return -1;
07077    }
07078 
07079    if (!strcasecmp(data, "buffers")) {
07080       int num_bufs, policy;
07081 
07082       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07083          struct dahdi_bufferinfo bi = {
07084             .txbufpolicy = policy,
07085             .rxbufpolicy = policy,
07086             .bufsize = p->bufsize,
07087             .numbufs = num_bufs,
07088          };
07089          int bpres;
07090 
07091          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07092             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07093          } else {
07094             p->bufferoverrideinuse = 1;
07095          }
07096       } else {
07097          res = -1;
07098       }
07099    } else if (!strcasecmp(data, "echocan_mode")) {
07100       if (!strcasecmp(value, "on")) {
07101          ast_mutex_lock(&p->lock);
07102          dahdi_enable_ec(p);
07103          ast_mutex_unlock(&p->lock);
07104       } else if (!strcasecmp(value, "off")) {
07105          ast_mutex_lock(&p->lock);
07106          dahdi_disable_ec(p);
07107          ast_mutex_unlock(&p->lock);
07108 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07109       } else if (!strcasecmp(value, "fax")) {
07110          int blah = 1;
07111 
07112          ast_mutex_lock(&p->lock);
07113          if (!p->echocanon) {
07114             dahdi_enable_ec(p);
07115          }
07116          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07117             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07118          }
07119          ast_mutex_unlock(&p->lock);
07120       } else if (!strcasecmp(value, "voice")) {
07121          int blah = 0;
07122 
07123          ast_mutex_lock(&p->lock);
07124          if (!p->echocanon) {
07125             dahdi_enable_ec(p);
07126          }
07127          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07128             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07129          }
07130          ast_mutex_unlock(&p->lock);
07131 #endif
07132       } else {
07133          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07134          res = -1;
07135       }
07136    } else {
07137       res = -1;
07138    }
07139 
07140    return res;
07141 }
07142 
07143 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07144 {
07145    /* Unlink a specific slave or all slaves/masters from a given master */
07146    int x;
07147    int hasslaves;
07148    if (!master)
07149       return;
07150    if (needlock) {
07151       ast_mutex_lock(&master->lock);
07152       if (slave) {
07153          while (ast_mutex_trylock(&slave->lock)) {
07154             DEADLOCK_AVOIDANCE(&master->lock);
07155          }
07156       }
07157    }
07158    hasslaves = 0;
07159    for (x = 0; x < MAX_SLAVES; x++) {
07160       if (master->slaves[x]) {
07161          if (!slave || (master->slaves[x] == slave)) {
07162             /* Take slave out of the conference */
07163             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07164             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07165             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07166             master->slaves[x]->master = NULL;
07167             master->slaves[x] = NULL;
07168          } else
07169             hasslaves = 1;
07170       }
07171       if (!hasslaves)
07172          master->inconference = 0;
07173    }
07174    if (!slave) {
07175       if (master->master) {
07176          /* Take master out of the conference */
07177          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07178          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07179          hasslaves = 0;
07180          for (x = 0; x < MAX_SLAVES; x++) {
07181             if (master->master->slaves[x] == master)
07182                master->master->slaves[x] = NULL;
07183             else if (master->master->slaves[x])
07184                hasslaves = 1;
07185          }
07186          if (!hasslaves)
07187             master->master->inconference = 0;
07188       }
07189       master->master = NULL;
07190    }
07191    update_conf(master);
07192    if (needlock) {
07193       if (slave)
07194          ast_mutex_unlock(&slave->lock);
07195       ast_mutex_unlock(&master->lock);
07196    }
07197 }
07198 
07199 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07200    int x;
07201    if (!slave || !master) {
07202       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07203       return;
07204    }
07205    for (x = 0; x < MAX_SLAVES; x++) {
07206       if (!master->slaves[x]) {
07207          master->slaves[x] = slave;
07208          break;
07209       }
07210    }
07211    if (x >= MAX_SLAVES) {
07212       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07213       master->slaves[MAX_SLAVES - 1] = slave;
07214    }
07215    if (slave->master)
07216       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07217    slave->master = master;
07218 
07219    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07220 }
07221 
07222 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)
07223 {
07224    struct ast_channel *who;
07225    struct dahdi_pvt *p0, *p1, *op0, *op1;
07226    struct dahdi_pvt *master = NULL, *slave = NULL;
07227    struct ast_frame *f;
07228    int inconf = 0;
07229    int nothingok = 1;
07230    int ofd0, ofd1;
07231    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07232    int os0 = -1, os1 = -1;
07233    int priority = 0;
07234    struct ast_channel *oc0, *oc1;
07235    enum ast_bridge_result res;
07236 #ifdef PRI_2BCT
07237    int triedtopribridge = 0;
07238    q931_call *q931c0;
07239    q931_call *q931c1;
07240 #endif
07241 
07242    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07243       There is code below to handle it properly until DTMF is actually seen,
07244       but due to currently unresolved issues it's ignored...
07245    */
07246 
07247    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07248       return AST_BRIDGE_FAILED_NOWARN;
07249 
07250    ast_channel_lock(c0);
07251    while (ast_channel_trylock(c1)) {
07252       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07253    }
07254 
07255    p0 = c0->tech_pvt;
07256    p1 = c1->tech_pvt;
07257    /* cant do pseudo-channels here */
07258    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07259       ast_channel_unlock(c0);
07260       ast_channel_unlock(c1);
07261       return AST_BRIDGE_FAILED_NOWARN;
07262    }
07263 
07264    oi0 = dahdi_get_index(c0, p0, 0);
07265    oi1 = dahdi_get_index(c1, p1, 0);
07266    if ((oi0 < 0) || (oi1 < 0)) {
07267       ast_channel_unlock(c0);
07268       ast_channel_unlock(c1);
07269       return AST_BRIDGE_FAILED;
07270    }
07271 
07272    op0 = p0 = c0->tech_pvt;
07273    op1 = p1 = c1->tech_pvt;
07274    ofd0 = c0->fds[0];
07275    ofd1 = c1->fds[0];
07276    oc0 = p0->owner;
07277    oc1 = p1->owner;
07278 
07279    if (ast_mutex_trylock(&p0->lock)) {
07280       /* Don't block, due to potential for deadlock */
07281       ast_channel_unlock(c0);
07282       ast_channel_unlock(c1);
07283       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07284       return AST_BRIDGE_RETRY;
07285    }
07286    if (ast_mutex_trylock(&p1->lock)) {
07287       /* Don't block, due to potential for deadlock */
07288       ast_mutex_unlock(&p0->lock);
07289       ast_channel_unlock(c0);
07290       ast_channel_unlock(c1);
07291       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07292       return AST_BRIDGE_RETRY;
07293    }
07294 
07295    if ((p0->callwaiting && p0->callwaitingcallerid)
07296       || (p1->callwaiting && p1->callwaitingcallerid)) {
07297       /*
07298        * Call Waiting Caller ID requires DTMF detection to know if it
07299        * can send the CID spill.
07300        *
07301        * For now, don't attempt to native bridge if either channel
07302        * needs DTMF detection.  There is code below to handle it
07303        * properly until DTMF is actually seen, but due to currently
07304        * unresolved issues it's ignored...
07305        */
07306       ast_mutex_unlock(&p0->lock);
07307       ast_mutex_unlock(&p1->lock);
07308       ast_channel_unlock(c0);
07309       ast_channel_unlock(c1);
07310       return AST_BRIDGE_FAILED_NOWARN;
07311    }
07312 
07313 #if defined(HAVE_PRI)
07314    if ((dahdi_sig_pri_lib_handles(p0->sig)
07315          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07316       || (dahdi_sig_pri_lib_handles(p1->sig)
07317          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07318       /*
07319        * PRI nobch channels (hold and call waiting) are equivalent to
07320        * pseudo channels and cannot be done here.
07321        */
07322       ast_mutex_unlock(&p0->lock);
07323       ast_mutex_unlock(&p1->lock);
07324       ast_channel_unlock(c0);
07325       ast_channel_unlock(c1);
07326       return AST_BRIDGE_FAILED_NOWARN;
07327    }
07328 #endif   /* defined(HAVE_PRI) */
07329 
07330    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07331       if (p0->owner && p1->owner) {
07332          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07333          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07334             master = p0;
07335             slave = p1;
07336             inconf = 1;
07337          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07338             master = p1;
07339             slave = p0;
07340             inconf = 1;
07341          } else {
07342             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07343             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07344                p0->channel,
07345                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07346                p0->subs[SUB_REAL].inthreeway, p0->channel,
07347                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07348                p1->subs[SUB_REAL].inthreeway);
07349          }
07350          nothingok = 0;
07351       }
07352    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07353       if (p1->subs[SUB_THREEWAY].inthreeway) {
07354          master = p1;
07355          slave = p0;
07356          nothingok = 0;
07357       }
07358    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07359       if (p0->subs[SUB_THREEWAY].inthreeway) {
07360          master = p0;
07361          slave = p1;
07362          nothingok = 0;
07363       }
07364    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07365       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07366          don't put us in anything */
07367       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07368          master = p1;
07369          slave = p0;
07370          nothingok = 0;
07371       }
07372    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07373       /* Same as previous */
07374       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07375          master = p0;
07376          slave = p1;
07377          nothingok = 0;
07378       }
07379    }
07380    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07381       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07382    if (master && slave) {
07383       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07384          in an active threeway call with a channel that is ringing, we should
07385          indicate ringing. */
07386       if ((oi1 == SUB_THREEWAY) &&
07387          p1->subs[SUB_THREEWAY].inthreeway &&
07388          p1->subs[SUB_REAL].owner &&
07389          p1->subs[SUB_REAL].inthreeway &&
07390          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07391          ast_debug(1,
07392             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07393             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07394          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07395          os1 = p1->subs[SUB_REAL].owner->_state;
07396       } else {
07397          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07398             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07399          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07400       }
07401       if ((oi0 == SUB_THREEWAY) &&
07402          p0->subs[SUB_THREEWAY].inthreeway &&
07403          p0->subs[SUB_REAL].owner &&
07404          p0->subs[SUB_REAL].inthreeway &&
07405          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07406          ast_debug(1,
07407             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07408             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07409          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07410          os0 = p0->subs[SUB_REAL].owner->_state;
07411       } else {
07412          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07413             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07414          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07415       }
07416       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07417          if (!p0->echocanbridged || !p1->echocanbridged) {
07418             /* Disable echo cancellation if appropriate */
07419             dahdi_disable_ec(p0);
07420             dahdi_disable_ec(p1);
07421          }
07422       }
07423       dahdi_link(slave, master);
07424       master->inconference = inconf;
07425    } else if (!nothingok)
07426       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07427 
07428    update_conf(p0);
07429    update_conf(p1);
07430    t0 = p0->subs[SUB_REAL].inthreeway;
07431    t1 = p1->subs[SUB_REAL].inthreeway;
07432 
07433    ast_mutex_unlock(&p0->lock);
07434    ast_mutex_unlock(&p1->lock);
07435 
07436    ast_channel_unlock(c0);
07437    ast_channel_unlock(c1);
07438 
07439    /* Native bridge failed */
07440    if ((!master || !slave) && !nothingok) {
07441       dahdi_enable_ec(p0);
07442       dahdi_enable_ec(p1);
07443       return AST_BRIDGE_FAILED;
07444    }
07445 
07446    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07447 
07448    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07449       disable_dtmf_detect(op0);
07450 
07451    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07452       disable_dtmf_detect(op1);
07453 
07454    for (;;) {
07455       struct ast_channel *c0_priority[2] = {c0, c1};
07456       struct ast_channel *c1_priority[2] = {c1, c0};
07457 
07458       /* Here's our main loop...  Start by locking things, looking for private parts,
07459          and then balking if anything is wrong */
07460 
07461       ast_channel_lock(c0);
07462       while (ast_channel_trylock(c1)) {
07463          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07464       }
07465 
07466       p0 = c0->tech_pvt;
07467       p1 = c1->tech_pvt;
07468 
07469       if (op0 == p0)
07470          i0 = dahdi_get_index(c0, p0, 1);
07471       if (op1 == p1)
07472          i1 = dahdi_get_index(c1, p1, 1);
07473 
07474       ast_channel_unlock(c0);
07475       ast_channel_unlock(c1);
07476 
07477       if (!timeoutms ||
07478          (op0 != p0) ||
07479          (op1 != p1) ||
07480          (ofd0 != c0->fds[0]) ||
07481          (ofd1 != c1->fds[0]) ||
07482          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07483          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07484          (oc0 != p0->owner) ||
07485          (oc1 != p1->owner) ||
07486          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07487          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07488          (oi0 != i0) ||
07489          (oi1 != i1)) {
07490          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07491             op0->channel, oi0, op1->channel, oi1);
07492          res = AST_BRIDGE_RETRY;
07493          goto return_from_bridge;
07494       }
07495 
07496 #ifdef PRI_2BCT
07497       if (!triedtopribridge) {
07498          triedtopribridge = 1;
07499          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07500             ast_mutex_lock(&p0->pri->lock);
07501             switch (p0->sig) {
07502             case SIG_PRI_LIB_HANDLE_CASES:
07503                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07504                break;
07505             default:
07506                q931c0 = NULL;
07507                break;
07508             }
07509             switch (p1->sig) {
07510             case SIG_PRI_LIB_HANDLE_CASES:
07511                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07512                break;
07513             default:
07514                q931c1 = NULL;
07515                break;
07516             }
07517             if (q931c0 && q931c1) {
07518                pri_channel_bridge(q931c0, q931c1);
07519             }
07520             ast_mutex_unlock(&p0->pri->lock);
07521          }
07522       }
07523 #endif
07524 
07525       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07526       if (!who) {
07527          ast_debug(1, "Ooh, empty read...\n");
07528          continue;
07529       }
07530       f = ast_read(who);
07531       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07532          *fo = f;
07533          *rc = who;
07534          res = AST_BRIDGE_COMPLETE;
07535          goto return_from_bridge;
07536       }
07537       if (f->frametype == AST_FRAME_DTMF) {
07538          if ((who == c0) && p0->pulsedial) {
07539             ast_write(c1, f);
07540          } else if ((who == c1) && p1->pulsedial) {
07541             ast_write(c0, f);
07542          } else {
07543             *fo = f;
07544             *rc = who;
07545             res = AST_BRIDGE_COMPLETE;
07546             goto return_from_bridge;
07547          }
07548       }
07549       ast_frfree(f);
07550 
07551       /* Swap who gets priority */
07552       priority = !priority;
07553    }
07554 
07555 return_from_bridge:
07556    if (op0 == p0)
07557       dahdi_enable_ec(p0);
07558 
07559    if (op1 == p1)
07560       dahdi_enable_ec(p1);
07561 
07562    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07563       enable_dtmf_detect(op0);
07564 
07565    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07566       enable_dtmf_detect(op1);
07567 
07568    dahdi_unlink(slave, master, 1);
07569 
07570    return res;
07571 }
07572 
07573 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07574 {
07575    struct dahdi_pvt *p = newchan->tech_pvt;
07576    int x;
07577 
07578    ast_mutex_lock(&p->lock);
07579 
07580    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07581    if (p->owner == oldchan) {
07582       p->owner = newchan;
07583    }
07584    for (x = 0; x < 3; x++) {
07585       if (p->subs[x].owner == oldchan) {
07586          if (!x) {
07587             dahdi_unlink(NULL, p, 0);
07588          }
07589          p->subs[x].owner = newchan;
07590       }
07591    }
07592    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07593       analog_fixup(oldchan, newchan, p->sig_pvt);
07594 #if defined(HAVE_PRI)
07595    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07596       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07597 #endif   /* defined(HAVE_PRI) */
07598 #if defined(HAVE_SS7)
07599    } else if (p->sig == SIG_SS7) {
07600       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07601 #endif   /* defined(HAVE_SS7) */
07602    }
07603    update_conf(p);
07604 
07605    ast_mutex_unlock(&p->lock);
07606 
07607    if (newchan->_state == AST_STATE_RINGING) {
07608       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07609    }
07610    return 0;
07611 }
07612 
07613 static int dahdi_ring_phone(struct dahdi_pvt *p)
07614 {
07615    int x;
07616    int res;
07617    /* Make sure our transmit state is on hook */
07618    x = 0;
07619    x = DAHDI_ONHOOK;
07620    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07621    do {
07622       x = DAHDI_RING;
07623       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07624       if (res) {
07625          switch (errno) {
07626          case EBUSY:
07627          case EINTR:
07628             /* Wait just in case */
07629             usleep(10000);
07630             continue;
07631          case EINPROGRESS:
07632             res = 0;
07633             break;
07634          default:
07635             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07636             res = 0;
07637          }
07638       }
07639    } while (res);
07640    return res;
07641 }
07642 
07643 static void *analog_ss_thread(void *data);
07644 
07645 static int attempt_transfer(struct dahdi_pvt *p)
07646 {
07647    /* In order to transfer, we need at least one of the channels to
07648       actually be in a call bridge.  We can't conference two applications
07649       together (but then, why would we want to?) */
07650    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07651       /* The three-way person we're about to transfer to could still be in MOH, so
07652          stop if now if appropriate */
07653       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07654          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07655       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07656          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07657       }
07658       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07659          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07660       }
07661        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07662          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07663                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07664          return -1;
07665       }
07666       /* Orphan the channel after releasing the lock */
07667       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07668       unalloc_sub(p, SUB_THREEWAY);
07669    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07670       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07671       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07672          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07673       }
07674       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07675          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07676       }
07677       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07678          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07679                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07680          return -1;
07681       }
07682       /* Three-way is now the REAL */
07683       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07684       ast_channel_unlock(p->subs[SUB_REAL].owner);
07685       unalloc_sub(p, SUB_THREEWAY);
07686       /* Tell the caller not to hangup */
07687       return 1;
07688    } else {
07689       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07690          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07691       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07692       return -1;
07693    }
07694    return 0;
07695 }
07696 
07697 static int check_for_conference(struct dahdi_pvt *p)
07698 {
07699    struct dahdi_confinfo ci;
07700    /* Fine if we already have a master, etc */
07701    if (p->master || (p->confno > -1))
07702       return 0;
07703    memset(&ci, 0, sizeof(ci));
07704    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07705       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07706       return 0;
07707    }
07708    /* If we have no master and don't have a confno, then
07709       if we're in a conference, it's probably a MeetMe room or
07710       some such, so don't let us 3-way out! */
07711    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07712       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07713       return 1;
07714    }
07715    return 0;
07716 }
07717 
07718 /*! Checks channel for alarms
07719  * \param p a channel to check for alarms.
07720  * \returns the alarms on the span to which the channel belongs, or alarms on
07721  *          the channel if no span alarms.
07722  */
07723 static int get_alarms(struct dahdi_pvt *p)
07724 {
07725    int res;
07726    struct dahdi_spaninfo zi;
07727    struct dahdi_params params;
07728 
07729    memset(&zi, 0, sizeof(zi));
07730    zi.spanno = p->span;
07731 
07732    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07733       if (zi.alarms != DAHDI_ALARM_NONE)
07734          return zi.alarms;
07735    } else {
07736       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07737       return 0;
07738    }
07739 
07740    /* No alarms on the span. Check for channel alarms. */
07741    memset(&params, 0, sizeof(params));
07742    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07743       return params.chan_alarms;
07744 
07745    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07746 
07747    return DAHDI_ALARM_NONE;
07748 }
07749 
07750 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07751 {
07752    struct dahdi_pvt *p = ast->tech_pvt;
07753    struct ast_frame *f = *dest;
07754 
07755    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07756       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07757       f->subclass.integer, f->subclass.integer, ast->name);
07758 
07759    if (p->confirmanswer) {
07760       if (f->frametype == AST_FRAME_DTMF_END) {
07761          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07762          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07763             of a DTMF digit */
07764          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07765          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07766          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07767          p->confirmanswer = 0;
07768       } else {
07769          p->subs[idx].f.frametype = AST_FRAME_NULL;
07770          p->subs[idx].f.subclass.integer = 0;
07771       }
07772       *dest = &p->subs[idx].f;
07773    } else if (p->callwaitcas) {
07774       if (f->frametype == AST_FRAME_DTMF_END) {
07775          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07776             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07777             ast_free(p->cidspill);
07778             p->cidspill = NULL;
07779             send_cwcidspill(p);
07780          }
07781          p->callwaitcas = 0;
07782       }
07783       p->subs[idx].f.frametype = AST_FRAME_NULL;
07784       p->subs[idx].f.subclass.integer = 0;
07785       *dest = &p->subs[idx].f;
07786    } else if (f->subclass.integer == 'f') {
07787       if (f->frametype == AST_FRAME_DTMF_END) {
07788          /* Fax tone -- Handle and return NULL */
07789          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07790             /* If faxbuffers are configured, use them for the fax transmission */
07791             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07792                struct dahdi_bufferinfo bi = {
07793                   .txbufpolicy = p->faxbuf_policy,
07794                   .bufsize = p->bufsize,
07795                   .numbufs = p->faxbuf_no
07796                };
07797                int res;
07798 
07799                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07800                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07801                } else {
07802                   p->bufferoverrideinuse = 1;
07803                }
07804             }
07805             p->faxhandled = 1;
07806             if (p->dsp) {
07807                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07808                ast_dsp_set_features(p->dsp, p->dsp_features);
07809                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07810             }
07811             if (strcmp(ast->exten, "fax")) {
07812                const char *target_context = S_OR(ast->macrocontext, ast->context);
07813 
07814                /* We need to unlock 'ast' here because ast_exists_extension has the
07815                 * potential to start autoservice on the channel. Such action is prone
07816                 * to deadlock.
07817                 */
07818                ast_mutex_unlock(&p->lock);
07819                ast_channel_unlock(ast);
07820                if (ast_exists_extension(ast, target_context, "fax", 1,
07821                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07822                   ast_channel_lock(ast);
07823                   ast_mutex_lock(&p->lock);
07824                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07825                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07826                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07827                   if (ast_async_goto(ast, target_context, "fax", 1))
07828                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07829                } else {
07830                   ast_channel_lock(ast);
07831                   ast_mutex_lock(&p->lock);
07832                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07833                }
07834             } else {
07835                ast_debug(1, "Already in a fax extension, not redirecting\n");
07836             }
07837          } else {
07838             ast_debug(1, "Fax already handled\n");
07839          }
07840          dahdi_confmute(p, 0);
07841       }
07842       p->subs[idx].f.frametype = AST_FRAME_NULL;
07843       p->subs[idx].f.subclass.integer = 0;
07844       *dest = &p->subs[idx].f;
07845    }
07846 }
07847 
07848 static void handle_alarms(struct dahdi_pvt *p, int alms)
07849 {
07850    const char *alarm_str;
07851 
07852 #if defined(HAVE_PRI)
07853    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07854       return;
07855    }
07856 #endif   /* defined(HAVE_PRI) */
07857 
07858    alarm_str = alarm2str(alms);
07859    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07860       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07861       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07862                  "Alarm: %s\r\n"
07863                  "Channel: %d\r\n",
07864                  alarm_str, p->channel);
07865    }
07866 
07867    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07868       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07869       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07870                  "Alarm: %s\r\n"
07871                  "Span: %d\r\n",
07872                  alarm_str, p->span);
07873    }
07874 }
07875 
07876 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07877 {
07878    int res, x;
07879    int idx, mysig;
07880    char *c;
07881    struct dahdi_pvt *p = ast->tech_pvt;
07882    pthread_t threadid;
07883    struct ast_channel *chan;
07884    struct ast_frame *f;
07885 
07886    idx = dahdi_get_index(ast, p, 0);
07887    if (idx < 0) {
07888       return &ast_null_frame;
07889    }
07890    mysig = p->sig;
07891    if (p->outsigmod > -1)
07892       mysig = p->outsigmod;
07893    p->subs[idx].f.frametype = AST_FRAME_NULL;
07894    p->subs[idx].f.subclass.integer = 0;
07895    p->subs[idx].f.datalen = 0;
07896    p->subs[idx].f.samples = 0;
07897    p->subs[idx].f.mallocd = 0;
07898    p->subs[idx].f.offset = 0;
07899    p->subs[idx].f.src = "dahdi_handle_event";
07900    p->subs[idx].f.data.ptr = NULL;
07901    f = &p->subs[idx].f;
07902 
07903    if (p->fake_event) {
07904       res = p->fake_event;
07905       p->fake_event = 0;
07906    } else
07907       res = dahdi_get_event(p->subs[idx].dfd);
07908 
07909    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07910 
07911    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07912       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07913       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07914 #if defined(HAVE_PRI)
07915       if (dahdi_sig_pri_lib_handles(p->sig)
07916          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07917          && p->pri
07918          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07919          /* absorb event */
07920       } else
07921 #endif   /* defined(HAVE_PRI) */
07922       {
07923          /* Unmute conference */
07924          dahdi_confmute(p, 0);
07925          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07926          p->subs[idx].f.subclass.integer = res & 0xff;
07927          dahdi_handle_dtmf(ast, idx, &f);
07928       }
07929       return f;
07930    }
07931 
07932    if (res & DAHDI_EVENT_DTMFDOWN) {
07933       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07934 #if defined(HAVE_PRI)
07935       if (dahdi_sig_pri_lib_handles(p->sig)
07936          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07937          && p->pri
07938          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07939          /* absorb event */
07940       } else
07941 #endif   /* defined(HAVE_PRI) */
07942       {
07943          /* Mute conference */
07944          dahdi_confmute(p, 1);
07945          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07946          p->subs[idx].f.subclass.integer = res & 0xff;
07947          dahdi_handle_dtmf(ast, idx, &f);
07948       }
07949       return &p->subs[idx].f;
07950    }
07951 
07952    switch (res) {
07953    case DAHDI_EVENT_EC_DISABLED:
07954       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07955       p->echocanon = 0;
07956       break;
07957 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07958    case DAHDI_EVENT_TX_CED_DETECTED:
07959       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07960       break;
07961    case DAHDI_EVENT_RX_CED_DETECTED:
07962       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07963       break;
07964    case DAHDI_EVENT_EC_NLP_DISABLED:
07965       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07966       break;
07967    case DAHDI_EVENT_EC_NLP_ENABLED:
07968       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07969       break;
07970 #endif
07971    case DAHDI_EVENT_BITSCHANGED:
07972 #ifdef HAVE_OPENR2
07973       if (p->sig != SIG_MFCR2) {
07974          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07975       } else {
07976          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07977          openr2_chan_handle_cas(p->r2chan);
07978       }
07979 #else
07980       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07981 #endif
07982       break;
07983    case DAHDI_EVENT_PULSE_START:
07984       /* Stop tone if there's a pulse start and the PBX isn't started */
07985       if (!ast->pbx)
07986          tone_zone_play_tone(p->subs[idx].dfd, -1);
07987       break;
07988    case DAHDI_EVENT_DIALCOMPLETE:
07989       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
07990 #if defined(HAVE_PRI)
07991       if (dahdi_sig_pri_lib_handles(p->sig)) {
07992          if (p->inalarm) {
07993             break;
07994          }
07995          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
07996             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
07997                strerror(errno));
07998             return NULL;
07999          }
08000          if (x) {
08001             /* Still dialing in DAHDI driver */
08002             break;
08003          }
08004          /*
08005           * The ast channel is locked and the private may be locked more
08006           * than once.
08007           */
08008          sig_pri_dial_complete(p->sig_pvt, ast);
08009          break;
08010       }
08011 #endif   /* defined(HAVE_PRI) */
08012 #ifdef HAVE_OPENR2
08013       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08014          /* we don't need to do anything for this event for R2 signaling
08015             if the call is being setup */
08016          break;
08017       }
08018 #endif
08019       if (p->inalarm) break;
08020       if ((p->radio || (p->oprmode < 0))) break;
08021       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08022          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08023          return NULL;
08024       }
08025       if (!x) { /* if not still dialing in driver */
08026          dahdi_enable_ec(p);
08027          if (p->echobreak) {
08028             dahdi_train_ec(p);
08029             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08030             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08031             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08032             p->echobreak = 0;
08033          } else {
08034             p->dialing = 0;
08035             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08036                /* if thru with dialing after offhook */
08037                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08038                   ast_setstate(ast, AST_STATE_UP);
08039                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08040                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08041                   break;
08042                } else { /* if to state wait for offhook to dial rest */
08043                   /* we now wait for off hook */
08044                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08045                }
08046             }
08047             if (ast->_state == AST_STATE_DIALING) {
08048                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08049                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08050                } else if (p->confirmanswer || (!p->dialednone
08051                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08052                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08053                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08054                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08055                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08056                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08057                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08058                      || (mysig == SIG_SF_FEATB)))) {
08059                   ast_setstate(ast, AST_STATE_RINGING);
08060                } else if (!p->answeronpolarityswitch) {
08061                   ast_setstate(ast, AST_STATE_UP);
08062                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064                   /* If aops=0 and hops=1, this is necessary */
08065                   p->polarity = POLARITY_REV;
08066                } else {
08067                   /* Start clean, so we can catch the change to REV polarity when party answers */
08068                   p->polarity = POLARITY_IDLE;
08069                }
08070             }
08071          }
08072       }
08073       break;
08074    case DAHDI_EVENT_ALARM:
08075       switch (p->sig) {
08076 #if defined(HAVE_PRI)
08077       case SIG_PRI_LIB_HANDLE_CASES:
08078          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08079          break;
08080 #endif   /* defined(HAVE_PRI) */
08081 #if defined(HAVE_SS7)
08082       case SIG_SS7:
08083          sig_ss7_set_alarm(p->sig_pvt, 1);
08084          break;
08085 #endif   /* defined(HAVE_SS7) */
08086       default:
08087          p->inalarm = 1;
08088          break;
08089       }
08090       res = get_alarms(p);
08091       handle_alarms(p, res);
08092 #ifdef HAVE_PRI
08093       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08094          /* fall through intentionally */
08095       } else {
08096          break;
08097       }
08098 #endif
08099 #if defined(HAVE_SS7)
08100       if (p->sig == SIG_SS7)
08101          break;
08102 #endif   /* defined(HAVE_SS7) */
08103 #ifdef HAVE_OPENR2
08104       if (p->sig == SIG_MFCR2)
08105          break;
08106 #endif
08107    case DAHDI_EVENT_ONHOOK:
08108       if (p->radio) {
08109          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08110          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08111          break;
08112       }
08113       if (p->oprmode < 0)
08114       {
08115          if (p->oprmode != -1) break;
08116          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08117          {
08118             /* Make sure it starts ringing */
08119             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08120             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08121             save_conference(p->oprpeer);
08122             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08123          }
08124          break;
08125       }
08126       switch (p->sig) {
08127       case SIG_FXOLS:
08128       case SIG_FXOGS:
08129       case SIG_FXOKS:
08130          /* Check for some special conditions regarding call waiting */
08131          if (idx == SUB_REAL) {
08132             /* The normal line was hung up */
08133             if (p->subs[SUB_CALLWAIT].owner) {
08134                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08135                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08136                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08137                unalloc_sub(p, SUB_CALLWAIT);
08138 #if 0
08139                p->subs[idx].needanswer = 0;
08140                p->subs[idx].needringing = 0;
08141 #endif
08142                p->callwaitingrepeat = 0;
08143                p->cidcwexpire = 0;
08144                p->cid_suppress_expire = 0;
08145                p->owner = NULL;
08146                /* Don't start streaming audio yet if the incoming call isn't up yet */
08147                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08148                   p->dialing = 1;
08149                dahdi_ring_phone(p);
08150             } else if (p->subs[SUB_THREEWAY].owner) {
08151                unsigned int mssinceflash;
08152                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08153                   the private structure -- not especially easy or clean */
08154                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08155                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08156                   DLA_UNLOCK(&p->lock);
08157                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08158                   /* We can grab ast and p in that order, without worry.  We should make sure
08159                      nothing seriously bad has happened though like some sort of bizarre double
08160                      masquerade! */
08161                   DLA_LOCK(&p->lock);
08162                   if (p->owner != ast) {
08163                      ast_log(LOG_WARNING, "This isn't good...\n");
08164                      return NULL;
08165                   }
08166                }
08167                if (!p->subs[SUB_THREEWAY].owner) {
08168                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08169                   return NULL;
08170                }
08171                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08172                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08173                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08174                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08175                      hanging up.  Hangup both channels now */
08176                   if (p->subs[SUB_THREEWAY].owner)
08177                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08178                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08179                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08180                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08181                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08182                   if (p->transfer) {
08183                      /* In any case this isn't a threeway call anymore */
08184                      p->subs[SUB_REAL].inthreeway = 0;
08185                      p->subs[SUB_THREEWAY].inthreeway = 0;
08186                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08187                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08188                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08189                         /* Swap subs and dis-own channel */
08190                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08191                         p->owner = NULL;
08192                         /* Ring the phone */
08193                         dahdi_ring_phone(p);
08194                      } else {
08195                         if ((res = attempt_transfer(p)) < 0) {
08196                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08197                            if (p->subs[SUB_THREEWAY].owner)
08198                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08199                         } else if (res) {
08200                            /* Don't actually hang up at this point */
08201                            if (p->subs[SUB_THREEWAY].owner)
08202                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08203                            break;
08204                         }
08205                      }
08206                   } else {
08207                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08208                      if (p->subs[SUB_THREEWAY].owner)
08209                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08210                   }
08211                } else {
08212                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08213                   /* Swap subs and dis-own channel */
08214                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08215                   p->owner = NULL;
08216                   /* Ring the phone */
08217                   dahdi_ring_phone(p);
08218                }
08219             }
08220          } else {
08221             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08222          }
08223          /* Fall through */
08224       default:
08225          dahdi_disable_ec(p);
08226          return NULL;
08227       }
08228       break;
08229    case DAHDI_EVENT_RINGOFFHOOK:
08230       if (p->inalarm) break;
08231       if (p->oprmode < 0)
08232       {
08233          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08234          {
08235             /* Make sure it stops ringing */
08236             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08237             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08238             restore_conference(p->oprpeer);
08239          }
08240          break;
08241       }
08242       if (p->radio)
08243       {
08244          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08245          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08246          break;
08247       }
08248       /* for E911, its supposed to wait for offhook then dial
08249          the second half of the dial string */
08250       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08251          c = strchr(p->dialdest, '/');
08252          if (c)
08253             c++;
08254          else
08255             c = p->dialdest;
08256          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08257          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08258          if (strlen(p->dop.dialstr) > 4) {
08259             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08260             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08261             p->echorest[sizeof(p->echorest) - 1] = '\0';
08262             p->echobreak = 1;
08263             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08264          } else
08265             p->echobreak = 0;
08266          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08267             int saveerr = errno;
08268 
08269             x = DAHDI_ONHOOK;
08270             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08271             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08272             return NULL;
08273             }
08274          p->dialing = 1;
08275          return &p->subs[idx].f;
08276       }
08277       switch (p->sig) {
08278       case SIG_FXOLS:
08279       case SIG_FXOGS:
08280       case SIG_FXOKS:
08281          switch (ast->_state) {
08282          case AST_STATE_RINGING:
08283             dahdi_enable_ec(p);
08284             dahdi_train_ec(p);
08285             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08286             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08287             /* Make sure it stops ringing */
08288             p->subs[SUB_REAL].needringing = 0;
08289             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08290             ast_debug(1, "channel %d answered\n", p->channel);
08291 
08292             /* Cancel any running CallerID spill */
08293             ast_free(p->cidspill);
08294             p->cidspill = NULL;
08295             restore_conference(p);
08296 
08297             p->dialing = 0;
08298             p->callwaitcas = 0;
08299             if (p->confirmanswer) {
08300                /* Ignore answer if "confirm answer" is enabled */
08301                p->subs[idx].f.frametype = AST_FRAME_NULL;
08302                p->subs[idx].f.subclass.integer = 0;
08303             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08304                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08305                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08306                if (res < 0) {
08307                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08308                   p->dop.dialstr[0] = '\0';
08309                   return NULL;
08310                } else {
08311                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08312                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08313                   p->subs[idx].f.subclass.integer = 0;
08314                   p->dialing = 1;
08315                }
08316                p->dop.dialstr[0] = '\0';
08317                ast_setstate(ast, AST_STATE_DIALING);
08318             } else
08319                ast_setstate(ast, AST_STATE_UP);
08320             return &p->subs[idx].f;
08321          case AST_STATE_DOWN:
08322             ast_setstate(ast, AST_STATE_RING);
08323             ast->rings = 1;
08324             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08325             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08326             ast_debug(1, "channel %d picked up\n", p->channel);
08327             return &p->subs[idx].f;
08328          case AST_STATE_UP:
08329             /* Make sure it stops ringing */
08330             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08331             /* Okay -- probably call waiting*/
08332             if (ast_bridged_channel(p->owner))
08333                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08334             p->subs[idx].needunhold = 1;
08335             break;
08336          case AST_STATE_RESERVED:
08337             /* Start up dialtone */
08338             if (has_voicemail(p))
08339                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08340             else
08341                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08342             break;
08343          default:
08344             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08345          }
08346          break;
08347       case SIG_FXSLS:
08348       case SIG_FXSGS:
08349       case SIG_FXSKS:
08350          if (ast->_state == AST_STATE_RING) {
08351             p->ringt = p->ringt_base;
08352          }
08353 
08354          /* If we get a ring then we cannot be in
08355           * reversed polarity. So we reset to idle */
08356          ast_debug(1, "Setting IDLE polarity due "
08357             "to ring. Old polarity was %d\n",
08358             p->polarity);
08359          p->polarity = POLARITY_IDLE;
08360 
08361          /* Fall through */
08362       case SIG_EM:
08363       case SIG_EM_E1:
08364       case SIG_EMWINK:
08365       case SIG_FEATD:
08366       case SIG_FEATDMF:
08367       case SIG_FEATDMF_TA:
08368       case SIG_E911:
08369       case SIG_FGC_CAMA:
08370       case SIG_FGC_CAMAMF:
08371       case SIG_FEATB:
08372       case SIG_SF:
08373       case SIG_SFWINK:
08374       case SIG_SF_FEATD:
08375       case SIG_SF_FEATDMF:
08376       case SIG_SF_FEATB:
08377          if (ast->_state == AST_STATE_PRERING)
08378             ast_setstate(ast, AST_STATE_RING);
08379          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08380             ast_debug(1, "Ring detected\n");
08381             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08382             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08383          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08384             ast_debug(1, "Line answered\n");
08385             if (p->confirmanswer) {
08386                p->subs[idx].f.frametype = AST_FRAME_NULL;
08387                p->subs[idx].f.subclass.integer = 0;
08388             } else {
08389                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08390                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08391                ast_setstate(ast, AST_STATE_UP);
08392             }
08393          } else if (ast->_state != AST_STATE_RING)
08394             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08395          break;
08396       default:
08397          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08398       }
08399       break;
08400    case DAHDI_EVENT_RINGBEGIN:
08401       switch (p->sig) {
08402       case SIG_FXSLS:
08403       case SIG_FXSGS:
08404       case SIG_FXSKS:
08405          if (ast->_state == AST_STATE_RING) {
08406             p->ringt = p->ringt_base;
08407          }
08408          break;
08409       }
08410       break;
08411    case DAHDI_EVENT_RINGERON:
08412       break;
08413    case DAHDI_EVENT_NOALARM:
08414       switch (p->sig) {
08415 #if defined(HAVE_PRI)
08416       case SIG_PRI_LIB_HANDLE_CASES:
08417          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08418          break;
08419 #endif   /* defined(HAVE_PRI) */
08420 #if defined(HAVE_SS7)
08421       case SIG_SS7:
08422          sig_ss7_set_alarm(p->sig_pvt, 0);
08423          break;
08424 #endif   /* defined(HAVE_SS7) */
08425       default:
08426          p->inalarm = 0;
08427          break;
08428       }
08429       handle_clear_alarms(p);
08430       break;
08431    case DAHDI_EVENT_WINKFLASH:
08432       if (p->inalarm) break;
08433       if (p->radio) break;
08434       if (p->oprmode < 0) break;
08435       if (p->oprmode > 1)
08436       {
08437          struct dahdi_params par;
08438 
08439          memset(&par, 0, sizeof(par));
08440          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08441          {
08442             if (!par.rxisoffhook)
08443             {
08444                /* Make sure it stops ringing */
08445                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08446                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08447                save_conference(p);
08448                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08449             }
08450          }
08451          break;
08452       }
08453       /* Remember last time we got a flash-hook */
08454       p->flashtime = ast_tvnow();
08455       switch (mysig) {
08456       case SIG_FXOLS:
08457       case SIG_FXOGS:
08458       case SIG_FXOKS:
08459          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08460             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08461 
08462          /* Cancel any running CallerID spill */
08463          ast_free(p->cidspill);
08464          p->cidspill = NULL;
08465          restore_conference(p);
08466          p->callwaitcas = 0;
08467 
08468          if (idx != SUB_REAL) {
08469             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08470             goto winkflashdone;
08471          }
08472 
08473          if (p->subs[SUB_CALLWAIT].owner) {
08474             /* Swap to call-wait */
08475             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08476             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08477             p->owner = p->subs[SUB_REAL].owner;
08478             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08479             if (p->owner->_state == AST_STATE_RINGING) {
08480                ast_setstate(p->owner, AST_STATE_UP);
08481                p->subs[SUB_REAL].needanswer = 1;
08482             }
08483             p->callwaitingrepeat = 0;
08484             p->cidcwexpire = 0;
08485             p->cid_suppress_expire = 0;
08486             /* Start music on hold if appropriate */
08487             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08488                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08489                   S_OR(p->mohsuggest, NULL),
08490                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08491             }
08492             p->subs[SUB_CALLWAIT].needhold = 1;
08493             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08494                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08495                   S_OR(p->mohsuggest, NULL),
08496                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08497             }
08498             p->subs[SUB_REAL].needunhold = 1;
08499          } else if (!p->subs[SUB_THREEWAY].owner) {
08500             if (!p->threewaycalling) {
08501                /* Just send a flash if no 3-way calling */
08502                p->subs[SUB_REAL].needflash = 1;
08503                goto winkflashdone;
08504             } else if (!check_for_conference(p)) {
08505                char cid_num[256];
08506                char cid_name[256];
08507 
08508                cid_num[0] = 0;
08509                cid_name[0] = 0;
08510                if (p->dahditrcallerid && p->owner) {
08511                   if (p->owner->caller.id.number.valid
08512                      && p->owner->caller.id.number.str) {
08513                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08514                         sizeof(cid_num));
08515                   }
08516                   if (p->owner->caller.id.name.valid
08517                      && p->owner->caller.id.name.str) {
08518                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08519                         sizeof(cid_name));
08520                   }
08521                }
08522                /* XXX This section needs much more error checking!!! XXX */
08523                /* Start a 3-way call if feasible */
08524                if (!((ast->pbx) ||
08525                   (ast->_state == AST_STATE_UP) ||
08526                   (ast->_state == AST_STATE_RING))) {
08527                   ast_debug(1, "Flash when call not up or ringing\n");
08528                   goto winkflashdone;
08529                }
08530                if (alloc_sub(p, SUB_THREEWAY)) {
08531                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08532                   goto winkflashdone;
08533                }
08534 
08535                /*
08536                 * Make new channel
08537                 *
08538                 * We cannot hold the p or ast locks while creating a new
08539                 * channel.
08540                 */
08541                ast_mutex_unlock(&p->lock);
08542                ast_channel_unlock(ast);
08543                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08544                ast_channel_lock(ast);
08545                ast_mutex_lock(&p->lock);
08546                if (p->dahditrcallerid) {
08547                   if (!p->origcid_num)
08548                      p->origcid_num = ast_strdup(p->cid_num);
08549                   if (!p->origcid_name)
08550                      p->origcid_name = ast_strdup(p->cid_name);
08551                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08552                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08553                }
08554                /* Swap things around between the three-way and real call */
08555                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08556                /* Disable echo canceller for better dialing */
08557                dahdi_disable_ec(p);
08558                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08559                if (res)
08560                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08561                p->owner = chan;
08562                if (!chan) {
08563                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08564                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08565                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08566                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08567                   dahdi_enable_ec(p);
08568                   ast_hangup(chan);
08569                } else {
08570                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08571 
08572                   /* Start music on hold if appropriate */
08573                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08574                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08575                         S_OR(p->mohsuggest, NULL),
08576                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08577                   }
08578                   p->subs[SUB_THREEWAY].needhold = 1;
08579                }
08580             }
08581          } else {
08582             /* Already have a 3 way call */
08583             if (p->subs[SUB_THREEWAY].inthreeway) {
08584                /* Call is already up, drop the last person */
08585                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08586                /* If the primary call isn't answered yet, use it */
08587                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08588                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08589                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08590                   p->owner = p->subs[SUB_REAL].owner;
08591                }
08592                /* Drop the last call and stop the conference */
08593                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08594                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08595                p->subs[SUB_REAL].inthreeway = 0;
08596                p->subs[SUB_THREEWAY].inthreeway = 0;
08597             } else {
08598                /* Lets see what we're up to */
08599                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08600                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08601                   int otherindex = SUB_THREEWAY;
08602 
08603                   ast_verb(3, "Building conference call with %s and %s\n",
08604                      p->subs[SUB_THREEWAY].owner->name,
08605                      p->subs[SUB_REAL].owner->name);
08606                   /* Put them in the threeway, and flip */
08607                   p->subs[SUB_THREEWAY].inthreeway = 1;
08608                   p->subs[SUB_REAL].inthreeway = 1;
08609                   if (ast->_state == AST_STATE_UP) {
08610                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08611                      otherindex = SUB_REAL;
08612                   }
08613                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08614                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08615                   p->subs[otherindex].needunhold = 1;
08616                   p->owner = p->subs[SUB_REAL].owner;
08617                } else {
08618                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08619                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08620                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08621                   p->owner = p->subs[SUB_REAL].owner;
08622                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08623                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08624                   p->subs[SUB_REAL].needunhold = 1;
08625                   dahdi_enable_ec(p);
08626                }
08627             }
08628          }
08629 winkflashdone:
08630          update_conf(p);
08631          break;
08632       case SIG_EM:
08633       case SIG_EM_E1:
08634       case SIG_FEATD:
08635       case SIG_SF:
08636       case SIG_SFWINK:
08637       case SIG_SF_FEATD:
08638       case SIG_FXSLS:
08639       case SIG_FXSGS:
08640          if (p->dialing)
08641             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08642          else
08643             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08644          break;
08645       case SIG_FEATDMF_TA:
08646          switch (p->whichwink) {
08647          case 0:
08648             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08649                S_COR(p->owner->caller.ani.number.valid,
08650                   p->owner->caller.ani.number.str, ""));
08651             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08652                p->owner->caller.ani2,
08653                S_COR(p->owner->caller.ani.number.valid,
08654                   p->owner->caller.ani.number.str, ""));
08655             break;
08656          case 1:
08657             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08658             break;
08659          case 2:
08660             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08661             return NULL;
08662          }
08663          p->whichwink++;
08664          /* Fall through */
08665       case SIG_FEATDMF:
08666       case SIG_E911:
08667       case SIG_FGC_CAMAMF:
08668       case SIG_FGC_CAMA:
08669       case SIG_FEATB:
08670       case SIG_SF_FEATDMF:
08671       case SIG_SF_FEATB:
08672       case SIG_EMWINK:
08673          /* FGD MF and EMWINK *Must* wait for wink */
08674          if (!ast_strlen_zero(p->dop.dialstr)) {
08675             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08676             if (res < 0) {
08677                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08678                p->dop.dialstr[0] = '\0';
08679                return NULL;
08680             } else
08681                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08682          }
08683          p->dop.dialstr[0] = '\0';
08684          break;
08685       default:
08686          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08687       }
08688       break;
08689    case DAHDI_EVENT_HOOKCOMPLETE:
08690       if (p->inalarm) break;
08691       if ((p->radio || (p->oprmode < 0))) break;
08692       if (p->waitingfordt.tv_sec) break;
08693       switch (mysig) {
08694       case SIG_FXSLS:  /* only interesting for FXS */
08695       case SIG_FXSGS:
08696       case SIG_FXSKS:
08697       case SIG_EM:
08698       case SIG_EM_E1:
08699       case SIG_EMWINK:
08700       case SIG_FEATD:
08701       case SIG_SF:
08702       case SIG_SFWINK:
08703       case SIG_SF_FEATD:
08704          if (!ast_strlen_zero(p->dop.dialstr)) {
08705             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08706             if (res < 0) {
08707                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08708                p->dop.dialstr[0] = '\0';
08709                return NULL;
08710             } else
08711                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08712          }
08713          p->dop.dialstr[0] = '\0';
08714          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08715          break;
08716       case SIG_FEATDMF:
08717       case SIG_FEATDMF_TA:
08718       case SIG_E911:
08719       case SIG_FGC_CAMA:
08720       case SIG_FGC_CAMAMF:
08721       case SIG_FEATB:
08722       case SIG_SF_FEATDMF:
08723       case SIG_SF_FEATB:
08724          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08725          break;
08726       default:
08727          break;
08728       }
08729       break;
08730    case DAHDI_EVENT_POLARITY:
08731       /*
08732        * If we get a Polarity Switch event, check to see
08733        * if we should change the polarity state and
08734        * mark the channel as UP or if this is an indication
08735        * of remote end disconnect.
08736        */
08737       if (p->polarity == POLARITY_IDLE) {
08738          p->polarity = POLARITY_REV;
08739          if (p->answeronpolarityswitch &&
08740             ((ast->_state == AST_STATE_DIALING) ||
08741             (ast->_state == AST_STATE_RINGING))) {
08742             ast_debug(1, "Answering on polarity switch!\n");
08743             ast_setstate(p->owner, AST_STATE_UP);
08744             if (p->hanguponpolarityswitch) {
08745                p->polaritydelaytv = ast_tvnow();
08746             }
08747          } else
08748             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08749       }
08750       /* Removed else statement from here as it was preventing hangups from ever happening*/
08751       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08752       if (p->hanguponpolarityswitch &&
08753          (p->polarityonanswerdelay > 0) &&
08754          (p->polarity == POLARITY_REV) &&
08755          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08756          /* Added log_debug information below to provide a better indication of what is going on */
08757          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) );
08758 
08759          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08760             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08761             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08762             p->polarity = POLARITY_IDLE;
08763          } else
08764             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);
08765 
08766       } else {
08767          p->polarity = POLARITY_IDLE;
08768          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08769       }
08770       /* Added more log_debug information below to provide a better indication of what is going on */
08771       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) );
08772       break;
08773    default:
08774       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08775    }
08776    return &p->subs[idx].f;
08777 }
08778 
08779 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08780 {
08781    int res;
08782    int idx;
08783    struct ast_frame *f;
08784    int usedindex = -1;
08785    struct dahdi_pvt *p = ast->tech_pvt;
08786 
08787    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08788       idx = SUB_REAL;
08789    }
08790 
08791    p->subs[idx].f.frametype = AST_FRAME_NULL;
08792    p->subs[idx].f.datalen = 0;
08793    p->subs[idx].f.samples = 0;
08794    p->subs[idx].f.mallocd = 0;
08795    p->subs[idx].f.offset = 0;
08796    p->subs[idx].f.subclass.integer = 0;
08797    p->subs[idx].f.delivery = ast_tv(0,0);
08798    p->subs[idx].f.src = "dahdi_exception";
08799    p->subs[idx].f.data.ptr = NULL;
08800 
08801 
08802    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08803       /* If nobody owns us, absorb the event appropriately, otherwise
08804          we loop indefinitely.  This occurs when, during call waiting, the
08805          other end hangs up our channel so that it no longer exists, but we
08806          have neither FLASH'd nor ONHOOK'd to signify our desire to
08807          change to the other channel. */
08808       if (p->fake_event) {
08809          res = p->fake_event;
08810          p->fake_event = 0;
08811       } else
08812          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08813       /* Switch to real if there is one and this isn't something really silly... */
08814       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08815          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08816          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08817          p->owner = p->subs[SUB_REAL].owner;
08818          if (p->owner && ast_bridged_channel(p->owner))
08819             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08820          p->subs[SUB_REAL].needunhold = 1;
08821       }
08822       switch (res) {
08823       case DAHDI_EVENT_ONHOOK:
08824          dahdi_disable_ec(p);
08825          if (p->owner) {
08826             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08827             dahdi_ring_phone(p);
08828             p->callwaitingrepeat = 0;
08829             p->cidcwexpire = 0;
08830             p->cid_suppress_expire = 0;
08831          } else
08832             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08833          update_conf(p);
08834          break;
08835       case DAHDI_EVENT_RINGOFFHOOK:
08836          dahdi_enable_ec(p);
08837          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08838          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08839             p->subs[SUB_REAL].needanswer = 1;
08840             p->dialing = 0;
08841          }
08842          break;
08843       case DAHDI_EVENT_HOOKCOMPLETE:
08844       case DAHDI_EVENT_RINGERON:
08845       case DAHDI_EVENT_RINGEROFF:
08846          /* Do nothing */
08847          break;
08848       case DAHDI_EVENT_WINKFLASH:
08849          p->flashtime = ast_tvnow();
08850          if (p->owner) {
08851             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08852             if (p->owner->_state != AST_STATE_UP) {
08853                /* Answer if necessary */
08854                usedindex = dahdi_get_index(p->owner, p, 0);
08855                if (usedindex > -1) {
08856                   p->subs[usedindex].needanswer = 1;
08857                }
08858                ast_setstate(p->owner, AST_STATE_UP);
08859             }
08860             p->callwaitingrepeat = 0;
08861             p->cidcwexpire = 0;
08862             p->cid_suppress_expire = 0;
08863             if (ast_bridged_channel(p->owner))
08864                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08865             p->subs[SUB_REAL].needunhold = 1;
08866          } else
08867             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08868          update_conf(p);
08869          break;
08870       default:
08871          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08872       }
08873       f = &p->subs[idx].f;
08874       return f;
08875    }
08876    if (!(p->radio || (p->oprmode < 0)))
08877       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08878    /* If it's not us, return NULL immediately */
08879    if (ast != p->owner) {
08880       if (p->owner) {
08881          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08882       }
08883       f = &p->subs[idx].f;
08884       return f;
08885    }
08886 
08887    f = dahdi_handle_event(ast);
08888    if (!f) {
08889       const char *name = ast_strdupa(ast->name);
08890 
08891       /* Tell the CDR this DAHDI device hung up */
08892       ast_mutex_unlock(&p->lock);
08893       ast_channel_unlock(ast);
08894       ast_set_hangupsource(ast, name, 0);
08895       ast_channel_lock(ast);
08896       ast_mutex_lock(&p->lock);
08897    }
08898    return f;
08899 }
08900 
08901 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08902 {
08903    struct dahdi_pvt *p = ast->tech_pvt;
08904    struct ast_frame *f;
08905    ast_mutex_lock(&p->lock);
08906    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08907       struct analog_pvt *analog_p = p->sig_pvt;
08908       f = analog_exception(analog_p, ast);
08909    } else {
08910       f = __dahdi_exception(ast);
08911    }
08912    ast_mutex_unlock(&p->lock);
08913    return f;
08914 }
08915 
08916 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08917 {
08918    struct dahdi_pvt *p;
08919    int res;
08920    int idx;
08921    void *readbuf;
08922    struct ast_frame *f;
08923 
08924    /*
08925     * For analog channels, we must do deadlock avoidance because
08926     * analog ports can have more than one Asterisk channel using
08927     * the same private structure.
08928     */
08929    p = ast->tech_pvt;
08930    while (ast_mutex_trylock(&p->lock)) {
08931       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08932 
08933       /*
08934        * For PRI channels, we must refresh the private pointer because
08935        * the call could move to another B channel while the Asterisk
08936        * channel is unlocked.
08937        */
08938       p = ast->tech_pvt;
08939    }
08940 
08941    idx = dahdi_get_index(ast, p, 0);
08942 
08943    /* Hang up if we don't really exist */
08944    if (idx < 0)   {
08945       ast_log(LOG_WARNING, "We don't exist?\n");
08946       ast_mutex_unlock(&p->lock);
08947       return NULL;
08948    }
08949 
08950    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08951       ast_mutex_unlock(&p->lock);
08952       return NULL;
08953    }
08954 
08955    p->subs[idx].f.frametype = AST_FRAME_NULL;
08956    p->subs[idx].f.datalen = 0;
08957    p->subs[idx].f.samples = 0;
08958    p->subs[idx].f.mallocd = 0;
08959    p->subs[idx].f.offset = 0;
08960    p->subs[idx].f.subclass.integer = 0;
08961    p->subs[idx].f.delivery = ast_tv(0,0);
08962    p->subs[idx].f.src = "dahdi_read";
08963    p->subs[idx].f.data.ptr = NULL;
08964 
08965    /* make sure it sends initial key state as first frame */
08966    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08967    {
08968       struct dahdi_params ps;
08969 
08970       memset(&ps, 0, sizeof(ps));
08971       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08972          ast_mutex_unlock(&p->lock);
08973          return NULL;
08974       }
08975       p->firstradio = 1;
08976       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08977       if (ps.rxisoffhook)
08978       {
08979          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08980       }
08981       else
08982       {
08983          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08984       }
08985       ast_mutex_unlock(&p->lock);
08986       return &p->subs[idx].f;
08987    }
08988    if (p->ringt > 0) {
08989       if (!(--p->ringt)) {
08990          ast_mutex_unlock(&p->lock);
08991          return NULL;
08992       }
08993    }
08994 
08995 #ifdef HAVE_OPENR2
08996    if (p->mfcr2) {
08997       openr2_chan_process_event(p->r2chan);
08998       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08999          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09000          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09001           * now enqueue a progress frame to bridge the media up */
09002          if (p->mfcr2_call_accepted &&
09003              !p->mfcr2_progress && 
09004              ast->_state == AST_STATE_RINGING) {
09005             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09006             ast_queue_frame(p->owner, &f);
09007             p->mfcr2_progress = 1;
09008          }
09009       }
09010    }
09011 #endif
09012 
09013    if (p->subs[idx].needringing) {
09014       /* Send ringing frame if requested */
09015       p->subs[idx].needringing = 0;
09016       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09017       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09018       ast_setstate(ast, AST_STATE_RINGING);
09019       ast_mutex_unlock(&p->lock);
09020       return &p->subs[idx].f;
09021    }
09022 
09023    if (p->subs[idx].needbusy) {
09024       /* Send busy frame if requested */
09025       p->subs[idx].needbusy = 0;
09026       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09027       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09028       ast_mutex_unlock(&p->lock);
09029       return &p->subs[idx].f;
09030    }
09031 
09032    if (p->subs[idx].needcongestion) {
09033       /* Send congestion frame if requested */
09034       p->subs[idx].needcongestion = 0;
09035       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09036       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09037       ast_mutex_unlock(&p->lock);
09038       return &p->subs[idx].f;
09039    }
09040 
09041    if (p->subs[idx].needanswer) {
09042       /* Send answer frame if requested */
09043       p->subs[idx].needanswer = 0;
09044       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09045       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09046       ast_mutex_unlock(&p->lock);
09047       return &p->subs[idx].f;
09048    }
09049 #ifdef HAVE_OPENR2
09050    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09051       /* openr2 took care of reading and handling any event
09052         (needanswer, needbusy etc), if we continue we will read()
09053         twice, lets just return a null frame. This should only
09054         happen when openr2 is dialing out */
09055       ast_mutex_unlock(&p->lock);
09056       return &ast_null_frame;
09057    }
09058 #endif
09059 
09060    if (p->subs[idx].needflash) {
09061       /* Send answer frame if requested */
09062       p->subs[idx].needflash = 0;
09063       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09064       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09065       ast_mutex_unlock(&p->lock);
09066       return &p->subs[idx].f;
09067    }
09068 
09069    if (p->subs[idx].needhold) {
09070       /* Send answer frame if requested */
09071       p->subs[idx].needhold = 0;
09072       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09073       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09074       ast_mutex_unlock(&p->lock);
09075       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09076       return &p->subs[idx].f;
09077    }
09078 
09079    if (p->subs[idx].needunhold) {
09080       /* Send answer frame if requested */
09081       p->subs[idx].needunhold = 0;
09082       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09083       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09084       ast_mutex_unlock(&p->lock);
09085       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09086       return &p->subs[idx].f;
09087    }
09088 
09089    /*
09090     * If we have a fake_event, fake an exception to handle it only
09091     * if this channel owns the private.
09092     */
09093    if (p->fake_event && p->owner == ast) {
09094       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09095          struct analog_pvt *analog_p = p->sig_pvt;
09096 
09097          f = analog_exception(analog_p, ast);
09098       } else {
09099          f = __dahdi_exception(ast);
09100       }
09101       ast_mutex_unlock(&p->lock);
09102       return f;
09103    }
09104 
09105    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09106       if (!p->subs[idx].linear) {
09107          p->subs[idx].linear = 1;
09108          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09109          if (res)
09110             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09111       }
09112    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09113       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09114       if (p->subs[idx].linear) {
09115          p->subs[idx].linear = 0;
09116          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09117          if (res)
09118             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09119       }
09120    } else {
09121       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09122       ast_mutex_unlock(&p->lock);
09123       return NULL;
09124    }
09125    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09126    CHECK_BLOCKING(ast);
09127    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09128    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09129    /* Check for hangup */
09130    if (res < 0) {
09131       f = NULL;
09132       if (res == -1) {
09133          if (errno == EAGAIN) {
09134             /* Return "NULL" frame if there is nobody there */
09135             ast_mutex_unlock(&p->lock);
09136             return &p->subs[idx].f;
09137          } else if (errno == ELAST) {
09138             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09139                struct analog_pvt *analog_p = p->sig_pvt;
09140                f = analog_exception(analog_p, ast);
09141             } else {
09142                f = __dahdi_exception(ast);
09143             }
09144          } else
09145             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09146       }
09147       ast_mutex_unlock(&p->lock);
09148       return f;
09149    }
09150    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09151       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09152       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09153          struct analog_pvt *analog_p = p->sig_pvt;
09154          f = analog_exception(analog_p, ast);
09155       } else {
09156          f = __dahdi_exception(ast);
09157       }
09158       ast_mutex_unlock(&p->lock);
09159       return f;
09160    }
09161    if (p->tdd) { /* if in TDD mode, see if we receive that */
09162       int c;
09163 
09164       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09165       if (c < 0) {
09166          ast_debug(1,"tdd_feed failed\n");
09167          ast_mutex_unlock(&p->lock);
09168          return NULL;
09169       }
09170       if (c) { /* if a char to return */
09171          p->subs[idx].f.subclass.integer = 0;
09172          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09173          p->subs[idx].f.mallocd = 0;
09174          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09175          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09176          p->subs[idx].f.datalen = 1;
09177          *((char *) p->subs[idx].f.data.ptr) = c;
09178          ast_mutex_unlock(&p->lock);
09179          return &p->subs[idx].f;
09180       }
09181    }
09182    if (idx == SUB_REAL) {
09183       /* Ensure the CW timers decrement only on a single subchannel */
09184       if (p->cidcwexpire) {
09185          if (!--p->cidcwexpire) {
09186             /* Expired CID/CW */
09187             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09188             restore_conference(p);
09189          }
09190       }
09191       if (p->cid_suppress_expire) {
09192          --p->cid_suppress_expire;
09193       }
09194       if (p->callwaitingrepeat) {
09195          if (!--p->callwaitingrepeat) {
09196             /* Expired, Repeat callwaiting tone */
09197             ++p->callwaitrings;
09198             dahdi_callwait(ast);
09199          }
09200       }
09201    }
09202    if (p->subs[idx].linear) {
09203       p->subs[idx].f.datalen = READ_SIZE * 2;
09204    } else
09205       p->subs[idx].f.datalen = READ_SIZE;
09206 
09207    /* Handle CallerID Transmission */
09208    if ((p->owner == ast) && p->cidspill) {
09209       send_callerid(p);
09210    }
09211 
09212    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09213    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09214    p->subs[idx].f.samples = READ_SIZE;
09215    p->subs[idx].f.mallocd = 0;
09216    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09217    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09218 #if 0
09219    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09220 #endif
09221    if (p->dialing ||  p->radio || /* Transmitting something */
09222       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09223       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09224       ) {
09225       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09226          don't send anything */
09227       p->subs[idx].f.frametype = AST_FRAME_NULL;
09228       p->subs[idx].f.subclass.integer = 0;
09229       p->subs[idx].f.samples = 0;
09230       p->subs[idx].f.mallocd = 0;
09231       p->subs[idx].f.offset = 0;
09232       p->subs[idx].f.data.ptr = NULL;
09233       p->subs[idx].f.datalen= 0;
09234    }
09235    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09236       /* Perform busy detection etc on the dahdi line */
09237       int mute;
09238 
09239       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09240 
09241       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09242       mute = ast_dsp_was_muted(p->dsp);
09243       if (p->muting != mute) {
09244          p->muting = mute;
09245          dahdi_confmute(p, mute);
09246       }
09247 
09248       if (f) {
09249          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09250             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09251                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09252                   a busy */
09253                ast_frfree(f);
09254                f = NULL;
09255             }
09256          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09257             || f->frametype == AST_FRAME_DTMF_END) {
09258 #ifdef HAVE_PRI
09259             if (dahdi_sig_pri_lib_handles(p->sig)
09260                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09261                && p->pri
09262                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09263                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09264                /* Don't accept in-band DTMF when in overlap dial mode */
09265                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09266                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09267                   f->subclass.integer, f->subclass.integer, ast->name);
09268 
09269                f->frametype = AST_FRAME_NULL;
09270                f->subclass.integer = 0;
09271             }
09272 #endif
09273             /* DSP clears us of being pulse */
09274             p->pulsedial = 0;
09275          } else if (p->waitingfordt.tv_sec) {
09276             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09277                p->waitingfordt.tv_sec = 0;
09278                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09279                ast_frfree(f);
09280                f = NULL;
09281             } else if (f->frametype == AST_FRAME_VOICE) {
09282                f->frametype = AST_FRAME_NULL;
09283                f->subclass.integer = 0;
09284                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) {
09285                   p->waitingfordt.tv_sec = 0;
09286                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09287                   ast_dsp_set_features(p->dsp, p->dsp_features);
09288                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09289                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09290                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09291                      if (res < 0) {
09292                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09293                         p->dop.dialstr[0] = '\0';
09294                         ast_mutex_unlock(&p->lock);
09295                         ast_frfree(f);
09296                         return NULL;
09297                      } else {
09298                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09299                         p->dialing = 1;
09300                         p->dop.dialstr[0] = '\0';
09301                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09302                         ast_setstate(ast, AST_STATE_DIALING);
09303                      }
09304                   }
09305                }
09306             }
09307          }
09308       }
09309    } else
09310       f = &p->subs[idx].f;
09311 
09312    if (f) {
09313       switch (f->frametype) {
09314       case AST_FRAME_DTMF_BEGIN:
09315       case AST_FRAME_DTMF_END:
09316          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09317             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09318          } else {
09319             dahdi_handle_dtmf(ast, idx, &f);
09320          }
09321          break;
09322       case AST_FRAME_VOICE:
09323          if (p->cidspill || p->cid_suppress_expire) {
09324             /* We are/were sending a caller id spill.  Suppress any echo. */
09325             p->subs[idx].f.frametype = AST_FRAME_NULL;
09326             p->subs[idx].f.subclass.integer = 0;
09327             p->subs[idx].f.samples = 0;
09328             p->subs[idx].f.mallocd = 0;
09329             p->subs[idx].f.offset = 0;
09330             p->subs[idx].f.data.ptr = NULL;
09331             p->subs[idx].f.datalen= 0;
09332          }
09333          break;
09334       default:
09335          break;
09336       }
09337    }
09338 
09339    ast_mutex_unlock(&p->lock);
09340    return f;
09341 }
09342 
09343 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09344 {
09345    int sent=0;
09346    int size;
09347    int res;
09348    int fd;
09349    fd = p->subs[idx].dfd;
09350    while (len) {
09351       size = len;
09352       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09353          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09354       res = write(fd, buf, size);
09355       if (res != size) {
09356          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09357          return sent;
09358       }
09359       len -= size;
09360       buf += size;
09361    }
09362    return sent;
09363 }
09364 
09365 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09366 {
09367    struct dahdi_pvt *p = ast->tech_pvt;
09368    int res;
09369    int idx;
09370    idx = dahdi_get_index(ast, p, 0);
09371    if (idx < 0) {
09372       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09373       return -1;
09374    }
09375 
09376    /* Write a frame of (presumably voice) data */
09377    if (frame->frametype != AST_FRAME_VOICE) {
09378       if (frame->frametype != AST_FRAME_IMAGE)
09379          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09380       return 0;
09381    }
09382    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09383       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09384       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09385       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09386       return -1;
09387    }
09388    if (p->dialing) {
09389       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09390       return 0;
09391    }
09392    if (!p->owner) {
09393       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09394       return 0;
09395    }
09396    if (p->cidspill) {
09397       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09398          ast->name);
09399       return 0;
09400    }
09401    /* Return if it's not valid data */
09402    if (!frame->data.ptr || !frame->datalen)
09403       return 0;
09404 
09405    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09406       if (!p->subs[idx].linear) {
09407          p->subs[idx].linear = 1;
09408          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09409          if (res)
09410             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09411       }
09412       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09413    } else {
09414       /* x-law already */
09415       if (p->subs[idx].linear) {
09416          p->subs[idx].linear = 0;
09417          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09418          if (res)
09419             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09420       }
09421       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09422    }
09423    if (res < 0) {
09424       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09425       return -1;
09426    }
09427    return 0;
09428 }
09429 
09430 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09431 {
09432    struct dahdi_pvt *p = chan->tech_pvt;
09433    int res=-1;
09434    int idx;
09435    int func = DAHDI_FLASH;
09436 
09437    ast_mutex_lock(&p->lock);
09438    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09439    switch (p->sig) {
09440 #if defined(HAVE_PRI)
09441    case SIG_PRI_LIB_HANDLE_CASES:
09442       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09443       ast_mutex_unlock(&p->lock);
09444       return res;
09445 #endif   /* defined(HAVE_PRI) */
09446 #if defined(HAVE_SS7)
09447    case SIG_SS7:
09448       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09449       ast_mutex_unlock(&p->lock);
09450       return res;
09451 #endif   /* defined(HAVE_SS7) */
09452    default:
09453       break;
09454    }
09455 #ifdef HAVE_OPENR2
09456    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09457       ast_mutex_unlock(&p->lock);
09458       /* if this is an R2 call and the call is not yet accepted, we don't want the
09459          tone indications to mess up with the MF tones */
09460       return 0;
09461    }
09462 #endif
09463    idx = dahdi_get_index(chan, p, 0);
09464    if (idx == SUB_REAL) {
09465       switch (condition) {
09466       case AST_CONTROL_BUSY:
09467          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09468          break;
09469       case AST_CONTROL_RINGING:
09470          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09471 
09472          if (chan->_state != AST_STATE_UP) {
09473             if ((chan->_state != AST_STATE_RING) ||
09474                ((p->sig != SIG_FXSKS) &&
09475              (p->sig != SIG_FXSLS) &&
09476              (p->sig != SIG_FXSGS)))
09477             ast_setstate(chan, AST_STATE_RINGING);
09478          }
09479          break;
09480       case AST_CONTROL_INCOMPLETE:
09481          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09482          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09483          res = 0;
09484          break;
09485       case AST_CONTROL_PROCEEDING:
09486          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09487          /* don't continue in ast_indicate */
09488          res = 0;
09489          break;
09490       case AST_CONTROL_PROGRESS:
09491          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09492          /* don't continue in ast_indicate */
09493          res = 0;
09494          break;
09495       case AST_CONTROL_CONGESTION:
09496          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09497          switch (chan->hangupcause) {
09498          case AST_CAUSE_USER_BUSY:
09499          case AST_CAUSE_NORMAL_CLEARING:
09500          case 0:/* Cause has not been set. */
09501             /* Supply a more appropriate cause. */
09502             chan->hangupcause = AST_CAUSE_CONGESTION;
09503             break;
09504          default:
09505             break;
09506          }
09507          break;
09508       case AST_CONTROL_HOLD:
09509          ast_moh_start(chan, data, p->mohinterpret);
09510          break;
09511       case AST_CONTROL_UNHOLD:
09512          ast_moh_stop(chan);
09513          break;
09514       case AST_CONTROL_RADIO_KEY:
09515          if (p->radio)
09516             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09517          res = 0;
09518          break;
09519       case AST_CONTROL_RADIO_UNKEY:
09520          if (p->radio)
09521             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09522          res = 0;
09523          break;
09524       case AST_CONTROL_FLASH:
09525          /* flash hookswitch */
09526          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09527             /* Clear out the dial buffer */
09528             p->dop.dialstr[0] = '\0';
09529             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09530                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09531                   chan->name, strerror(errno));
09532             } else
09533                res = 0;
09534          } else
09535             res = 0;
09536          break;
09537       case AST_CONTROL_SRCUPDATE:
09538          res = 0;
09539          break;
09540       case -1:
09541          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09542          break;
09543       }
09544    } else {
09545       res = 0;
09546    }
09547    ast_mutex_unlock(&p->lock);
09548    return res;
09549 }
09550 
09551 #if defined(HAVE_PRI)
09552 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09553 #else
09554 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09555 #endif   /* defined(HAVE_PRI) */
09556 {
09557    struct ast_str *chan_name;
09558    int x, y;
09559 
09560    /* Create the new channel name tail. */
09561    if (!(chan_name = ast_str_create(32))) {
09562       return NULL;
09563    }
09564    if (i->channel == CHAN_PSEUDO) {
09565       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09566 #if defined(HAVE_PRI)
09567    } else if (i->pri) {
09568       ast_mutex_lock(&i->pri->lock);
09569       y = ++i->pri->new_chan_seq;
09570       if (is_outgoing) {
09571          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09572          address[0] = '\0';
09573       } else if (ast_strlen_zero(i->cid_subaddr)) {
09574          /* Put in caller-id number only since there is no subaddress. */
09575          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09576       } else {
09577          /* Put in caller-id number and subaddress. */
09578          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09579             i->cid_subaddr, y);
09580       }
09581       ast_mutex_unlock(&i->pri->lock);
09582 #endif   /* defined(HAVE_PRI) */
09583    } else {
09584       y = 1;
09585       do {
09586          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09587          for (x = 0; x < 3; ++x) {
09588             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09589                i->subs[x].owner->name + 6)) {
09590                break;
09591             }
09592          }
09593          ++y;
09594       } while (x < 3);
09595    }
09596    return chan_name;
09597 }
09598 
09599 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09600 {
09601    struct ast_channel *tmp;
09602    format_t deflaw;
09603    int x;
09604    int features;
09605    struct ast_str *chan_name;
09606    struct ast_variable *v;
09607    char *dashptr;
09608    char device_name[AST_CHANNEL_NAME];
09609 
09610    if (i->subs[idx].owner) {
09611       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09612       return NULL;
09613    }
09614 
09615 #if defined(HAVE_PRI)
09616    /*
09617     * The dnid has been stuffed with the called-number[:subaddress]
09618     * by dahdi_request() for outgoing calls.
09619     */
09620    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09621 #else
09622    chan_name = create_channel_name(i);
09623 #endif   /* defined(HAVE_PRI) */
09624    if (!chan_name) {
09625       return NULL;
09626    }
09627 
09628    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));
09629    ast_free(chan_name);
09630    if (!tmp)
09631       return NULL;
09632    tmp->tech = &dahdi_tech;
09633 #if defined(HAVE_PRI)
09634    if (i->pri) {
09635       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09636    }
09637 #endif   /* defined(HAVE_PRI) */
09638    ast_channel_cc_params_init(tmp, i->cc_params);
09639    if (law) {
09640       i->law = law;
09641       if (law == DAHDI_LAW_ALAW) {
09642          deflaw = AST_FORMAT_ALAW;
09643       } else {
09644          deflaw = AST_FORMAT_ULAW;
09645       }
09646    } else {
09647       switch (i->sig) {
09648       case SIG_PRI_LIB_HANDLE_CASES:
09649          /* Make sure companding law is known. */
09650          i->law = (i->law_default == DAHDI_LAW_ALAW)
09651             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09652          break;
09653       default:
09654          i->law = i->law_default;
09655          break;
09656       }
09657       if (i->law_default == DAHDI_LAW_ALAW) {
09658          deflaw = AST_FORMAT_ALAW;
09659       } else {
09660          deflaw = AST_FORMAT_ULAW;
09661       }
09662    }
09663    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09664    tmp->nativeformats = deflaw;
09665    /* Start out assuming ulaw since it's smaller :) */
09666    tmp->rawreadformat = deflaw;
09667    tmp->readformat = deflaw;
09668    tmp->rawwriteformat = deflaw;
09669    tmp->writeformat = deflaw;
09670    i->subs[idx].linear = 0;
09671    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09672    features = 0;
09673    if (idx == SUB_REAL) {
09674       if (i->busydetect && CANBUSYDETECT(i))
09675          features |= DSP_FEATURE_BUSY_DETECT;
09676       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09677          features |= DSP_FEATURE_CALL_PROGRESS;
09678       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09679          features |= DSP_FEATURE_WAITDIALTONE;
09680       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09681          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09682          features |= DSP_FEATURE_FAX_DETECT;
09683       }
09684       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09685       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09686          i->hardwaredtmf = 0;
09687          features |= DSP_FEATURE_DIGIT_DETECT;
09688       } else if (NEED_MFDETECT(i)) {
09689          i->hardwaredtmf = 1;
09690          features |= DSP_FEATURE_DIGIT_DETECT;
09691       }
09692    }
09693    if (features) {
09694       if (i->dsp) {
09695          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09696       } else {
09697          if (i->channel != CHAN_PSEUDO)
09698             i->dsp = ast_dsp_new();
09699          else
09700             i->dsp = NULL;
09701          if (i->dsp) {
09702             i->dsp_features = features;
09703 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09704             /* We cannot do progress detection until receive PROGRESS message */
09705             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09706                /* Remember requested DSP features, don't treat
09707                   talking as ANSWER */
09708                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09709                features = 0;
09710             }
09711 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09712             ast_dsp_set_features(i->dsp, features);
09713             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09714             if (!ast_strlen_zero(progzone))
09715                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09716             if (i->busydetect && CANBUSYDETECT(i)) {
09717                ast_dsp_set_busy_count(i->dsp, i->busycount);
09718                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09719             }
09720          }
09721       }
09722    }
09723 
09724    if (state == AST_STATE_RING)
09725       tmp->rings = 1;
09726    tmp->tech_pvt = i;
09727    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09728       /* Only FXO signalled stuff can be picked up */
09729       tmp->callgroup = i->callgroup;
09730       tmp->pickupgroup = i->pickupgroup;
09731    }
09732    if (!ast_strlen_zero(i->parkinglot))
09733       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09734    if (!ast_strlen_zero(i->language))
09735       ast_string_field_set(tmp, language, i->language);
09736    if (!i->owner)
09737       i->owner = tmp;
09738    if (!ast_strlen_zero(i->accountcode))
09739       ast_string_field_set(tmp, accountcode, i->accountcode);
09740    if (i->amaflags)
09741       tmp->amaflags = i->amaflags;
09742    i->subs[idx].owner = tmp;
09743    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09744    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09745       ast_string_field_set(tmp, call_forward, i->call_forward);
09746    }
09747    /* If we've been told "no ADSI" then enforce it */
09748    if (!i->adsi)
09749       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09750    if (!ast_strlen_zero(i->exten))
09751       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09752    if (!ast_strlen_zero(i->rdnis)) {
09753       tmp->redirecting.from.number.valid = 1;
09754       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09755    }
09756    if (!ast_strlen_zero(i->dnid)) {
09757       tmp->dialed.number.str = ast_strdup(i->dnid);
09758    }
09759 
09760    /* Don't use ast_set_callerid() here because it will
09761     * generate a needless NewCallerID event */
09762 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09763    if (!ast_strlen_zero(i->cid_ani)) {
09764       tmp->caller.ani.number.valid = 1;
09765       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09766    } else if (!ast_strlen_zero(i->cid_num)) {
09767       tmp->caller.ani.number.valid = 1;
09768       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09769    }
09770 #else
09771    if (!ast_strlen_zero(i->cid_num)) {
09772       tmp->caller.ani.number.valid = 1;
09773       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09774    }
09775 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09776    tmp->caller.id.name.presentation = i->callingpres;
09777    tmp->caller.id.number.presentation = i->callingpres;
09778    tmp->caller.id.number.plan = i->cid_ton;
09779    tmp->caller.ani2 = i->cid_ani2;
09780    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09781    /* clear the fake event in case we posted one before we had ast_channel */
09782    i->fake_event = 0;
09783    /* Assure there is no confmute on this channel */
09784    dahdi_confmute(i, 0);
09785    i->muting = 0;
09786    /* Configure the new channel jb */
09787    ast_jb_configure(tmp, &global_jbconf);
09788 
09789    /* Set initial device state */
09790    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09791    dashptr = strrchr(device_name, '-');
09792    if (dashptr) {
09793       *dashptr = '\0';
09794    }
09795    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09796 
09797    for (v = i->vars ; v ; v = v->next)
09798       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09799 
09800    ast_module_ref(ast_module_info->self);
09801 
09802    dahdi_ami_channel_event(i, tmp);
09803    if (startpbx) {
09804 #ifdef HAVE_OPENR2
09805       if (i->mfcr2call) {
09806          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09807       }
09808 #endif
09809       if (ast_pbx_start(tmp)) {
09810          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09811          ast_hangup(tmp);
09812          return NULL;
09813       }
09814    }
09815    return tmp;
09816 }
09817 
09818 
09819 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09820 {
09821    char c;
09822 
09823    *str = 0; /* start with empty output buffer */
09824    for (;;)
09825    {
09826       /* Wait for the first digit (up to specified ms). */
09827       c = ast_waitfordigit(chan, ms);
09828       /* if timeout, hangup or error, return as such */
09829       if (c < 1)
09830          return c;
09831       *str++ = c;
09832       *str = 0;
09833       if (strchr(term, c))
09834          return 1;
09835    }
09836 }
09837 
09838 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09839 {
09840    int j;
09841    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09842    for (;;)
09843    {
09844       /* set bits of interest */
09845       j = DAHDI_IOMUX_SIGEVENT;
09846       /* wait for some happening */
09847       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09848       /* exit loop if we have it */
09849       if (j & DAHDI_IOMUX_SIGEVENT) break;
09850    }
09851    /* get the event info */
09852    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09853    return 0;
09854 }
09855 
09856 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09857  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09858  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09859  *
09860  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09861  * DAHDI channel). Use this to enable or disable it.
09862  *
09863  * \bug the use of the word "channel" for those dahdichans is really confusing.
09864  */
09865 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09866 {
09867    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09868       return analog_dnd(dahdichan->sig_pvt, flag);
09869    }
09870 
09871    if (flag == -1) {
09872       return dahdichan->dnd;
09873    }
09874 
09875    /* Do not disturb */
09876    dahdichan->dnd = flag;
09877    ast_verb(3, "%s DND on channel %d\n",
09878          flag? "Enabled" : "Disabled",
09879          dahdichan->channel);
09880    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09881          "Channel: DAHDI/%d\r\n"
09882          "Status: %s\r\n", dahdichan->channel,
09883          flag? "enabled" : "disabled");
09884 
09885    return 0;
09886 }
09887 
09888 static int canmatch_featurecode(const char *exten)
09889 {
09890    int extlen = strlen(exten);
09891    const char *pickup_ext;
09892    if (!extlen) {
09893       return 1;
09894    }
09895    pickup_ext = ast_pickup_ext();
09896    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09897       return 1;
09898    }
09899    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09900    if (exten[0] == '*' && extlen < 3) {
09901       if (extlen == 1) {
09902          return 1;
09903       }
09904       /* "*0" should be processed before it gets here */
09905       switch (exten[1]) {
09906       case '6':
09907       case '7':
09908       case '8':
09909          return 1;
09910       }
09911    }
09912    return 0;
09913 }
09914 
09915 static void *analog_ss_thread(void *data)
09916 {
09917    struct ast_channel *chan = data;
09918    struct dahdi_pvt *p = chan->tech_pvt;
09919    char exten[AST_MAX_EXTENSION] = "";
09920    char exten2[AST_MAX_EXTENSION] = "";
09921    unsigned char buf[256];
09922    char dtmfcid[300];
09923    char dtmfbuf[300];
09924    struct callerid_state *cs = NULL;
09925    char *name = NULL, *number = NULL;
09926    int distMatches;
09927    int curRingData[3];
09928    int receivedRingT;
09929    int counter1;
09930    int counter;
09931    int samples = 0;
09932    struct ast_smdi_md_message *smdi_msg = NULL;
09933    int flags = 0;
09934    int i;
09935    int timeout;
09936    int getforward = 0;
09937    char *s1, *s2;
09938    int len = 0;
09939    int res;
09940    int idx;
09941 
09942    ast_mutex_lock(&ss_thread_lock);
09943    ss_thread_count++;
09944    ast_mutex_unlock(&ss_thread_lock);
09945    /* in the bizarre case where the channel has become a zombie before we
09946       even get started here, abort safely
09947    */
09948    if (!p) {
09949       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09950       ast_hangup(chan);
09951       goto quit;
09952    }
09953    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09954    idx = dahdi_get_index(chan, p, 1);
09955    if (idx < 0) {
09956       ast_log(LOG_WARNING, "Huh?\n");
09957       ast_hangup(chan);
09958       goto quit;
09959    }
09960    if (p->dsp)
09961       ast_dsp_digitreset(p->dsp);
09962    switch (p->sig) {
09963    case SIG_FEATD:
09964    case SIG_FEATDMF:
09965    case SIG_FEATDMF_TA:
09966    case SIG_E911:
09967    case SIG_FGC_CAMAMF:
09968    case SIG_FEATB:
09969    case SIG_EMWINK:
09970    case SIG_SF_FEATD:
09971    case SIG_SF_FEATDMF:
09972    case SIG_SF_FEATB:
09973    case SIG_SFWINK:
09974       if (dahdi_wink(p, idx))
09975          goto quit;
09976       /* Fall through */
09977    case SIG_EM:
09978    case SIG_EM_E1:
09979    case SIG_SF:
09980    case SIG_FGC_CAMA:
09981       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09982       if (p->dsp)
09983          ast_dsp_digitreset(p->dsp);
09984       /* set digit mode appropriately */
09985       if (p->dsp) {
09986          if (NEED_MFDETECT(p))
09987             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09988          else
09989             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09990       }
09991       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09992       /* Wait for the first digit only if immediate=no */
09993       if (!p->immediate)
09994          /* Wait for the first digit (up to 5 seconds). */
09995          res = ast_waitfordigit(chan, 5000);
09996       else
09997          res = 0;
09998       if (res > 0) {
09999          /* save first char */
10000          dtmfbuf[0] = res;
10001          switch (p->sig) {
10002          case SIG_FEATD:
10003          case SIG_SF_FEATD:
10004             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10005             if (res > 0)
10006                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10007             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10008             break;
10009          case SIG_FEATDMF_TA:
10010             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10011             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10012             if (dahdi_wink(p, idx)) goto quit;
10013             dtmfbuf[0] = 0;
10014             /* Wait for the first digit (up to 5 seconds). */
10015             res = ast_waitfordigit(chan, 5000);
10016             if (res <= 0) break;
10017             dtmfbuf[0] = res;
10018             /* fall through intentionally */
10019          case SIG_FEATDMF:
10020          case SIG_E911:
10021          case SIG_FGC_CAMAMF:
10022          case SIG_SF_FEATDMF:
10023             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10024             /* if international caca, do it again to get real ANO */
10025             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10026             {
10027                if (dahdi_wink(p, idx)) goto quit;
10028                dtmfbuf[0] = 0;
10029                /* Wait for the first digit (up to 5 seconds). */
10030                res = ast_waitfordigit(chan, 5000);
10031                if (res <= 0) break;
10032                dtmfbuf[0] = res;
10033                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10034             }
10035             if (res > 0) {
10036                /* if E911, take off hook */
10037                if (p->sig == SIG_E911)
10038                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10039                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10040             }
10041             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10042             break;
10043          case SIG_FEATB:
10044          case SIG_SF_FEATB:
10045             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10046             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10047             break;
10048          case SIG_EMWINK:
10049             /* if we received a '*', we are actually receiving Feature Group D
10050                dial syntax, so use that mode; otherwise, fall through to normal
10051                mode
10052             */
10053             if (res == '*') {
10054                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10055                if (res > 0)
10056                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10057                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10058                break;
10059             }
10060          default:
10061             /* If we got the first digit, get the rest */
10062             len = 1;
10063             dtmfbuf[len] = '\0';
10064             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10065                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10066                   timeout = matchdigittimeout;
10067                } else {
10068                   timeout = gendigittimeout;
10069                }
10070                res = ast_waitfordigit(chan, timeout);
10071                if (res < 0) {
10072                   ast_debug(1, "waitfordigit returned < 0...\n");
10073                   ast_hangup(chan);
10074                   goto quit;
10075                } else if (res) {
10076                   dtmfbuf[len++] = res;
10077                   dtmfbuf[len] = '\0';
10078                } else {
10079                   break;
10080                }
10081             }
10082             break;
10083          }
10084       }
10085       if (res == -1) {
10086          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10087          ast_hangup(chan);
10088          goto quit;
10089       } else if (res < 0) {
10090          ast_debug(1, "Got hung up before digits finished\n");
10091          ast_hangup(chan);
10092          goto quit;
10093       }
10094 
10095       if (p->sig == SIG_FGC_CAMA) {
10096          char anibuf[100];
10097 
10098          if (ast_safe_sleep(chan,1000) == -1) {
10099             ast_hangup(chan);
10100             goto quit;
10101          }
10102          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10103          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10104          res = my_getsigstr(chan, anibuf, "#", 10000);
10105          if ((res > 0) && (strlen(anibuf) > 2)) {
10106             if (anibuf[strlen(anibuf) - 1] == '#')
10107                anibuf[strlen(anibuf) - 1] = 0;
10108             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10109          }
10110          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10111       }
10112 
10113       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10114       if (ast_strlen_zero(exten))
10115          ast_copy_string(exten, "s", sizeof(exten));
10116       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10117          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10118          if (exten[0] == '*') {
10119             char *stringp=NULL;
10120             ast_copy_string(exten2, exten, sizeof(exten2));
10121             /* Parse out extension and callerid */
10122             stringp=exten2 +1;
10123             s1 = strsep(&stringp, "*");
10124             s2 = strsep(&stringp, "*");
10125             if (s2) {
10126                if (!ast_strlen_zero(p->cid_num))
10127                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10128                else
10129                   ast_set_callerid(chan, s1, NULL, s1);
10130                ast_copy_string(exten, s2, sizeof(exten));
10131             } else
10132                ast_copy_string(exten, s1, sizeof(exten));
10133          } else if (p->sig == SIG_FEATD)
10134             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10135       }
10136       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10137          if (exten[0] == '*') {
10138             char *stringp=NULL;
10139             ast_copy_string(exten2, exten, sizeof(exten2));
10140             /* Parse out extension and callerid */
10141             stringp=exten2 +1;
10142             s1 = strsep(&stringp, "#");
10143             s2 = strsep(&stringp, "#");
10144             if (s2) {
10145                if (!ast_strlen_zero(p->cid_num))
10146                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10147                else
10148                   if (*(s1 + 2))
10149                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10150                ast_copy_string(exten, s2 + 1, sizeof(exten));
10151             } else
10152                ast_copy_string(exten, s1 + 2, sizeof(exten));
10153          } else
10154             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10155       }
10156       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10157          if (exten[0] == '*') {
10158             char *stringp=NULL;
10159             ast_copy_string(exten2, exten, sizeof(exten2));
10160             /* Parse out extension and callerid */
10161             stringp=exten2 +1;
10162             s1 = strsep(&stringp, "#");
10163             s2 = strsep(&stringp, "#");
10164             if (s2 && (*(s2 + 1) == '0')) {
10165                if (*(s2 + 2))
10166                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10167             }
10168             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10169             else ast_copy_string(exten, "911", sizeof(exten));
10170          } else
10171             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10172       }
10173       if (p->sig == SIG_FEATB) {
10174          if (exten[0] == '*') {
10175             char *stringp=NULL;
10176             ast_copy_string(exten2, exten, sizeof(exten2));
10177             /* Parse out extension and callerid */
10178             stringp=exten2 +1;
10179             s1 = strsep(&stringp, "#");
10180             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10181          } else
10182             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10183       }
10184       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10185          dahdi_wink(p, idx);
10186          /* some switches require a minimum guard time between
10187             the last FGD wink and something that answers
10188             immediately. This ensures it */
10189          if (ast_safe_sleep(chan, 100)) {
10190             ast_hangup(chan);
10191             goto quit;
10192          }
10193       }
10194       dahdi_enable_ec(p);
10195       if (NEED_MFDETECT(p)) {
10196          if (p->dsp) {
10197             if (!p->hardwaredtmf)
10198                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10199             else {
10200                ast_dsp_free(p->dsp);
10201                p->dsp = NULL;
10202             }
10203          }
10204       }
10205 
10206       if (ast_exists_extension(chan, chan->context, exten, 1,
10207          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10208          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10209          if (p->dsp) ast_dsp_digitreset(p->dsp);
10210          res = ast_pbx_run(chan);
10211          if (res) {
10212             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10213             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10214          }
10215          goto quit;
10216       } else {
10217          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10218          sleep(2);
10219          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10220          if (res < 0)
10221             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10222          else
10223             sleep(1);
10224          res = ast_streamfile(chan, "ss-noservice", chan->language);
10225          if (res >= 0)
10226             ast_waitstream(chan, "");
10227          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10228          ast_hangup(chan);
10229          goto quit;
10230       }
10231       break;
10232    case SIG_FXOLS:
10233    case SIG_FXOGS:
10234    case SIG_FXOKS:
10235       /* Read the first digit */
10236       timeout = firstdigittimeout;
10237       /* If starting a threeway call, never timeout on the first digit so someone
10238          can use flash-hook as a "hold" feature */
10239       if (p->subs[SUB_THREEWAY].owner)
10240          timeout = 999999;
10241       while (len < AST_MAX_EXTENSION-1) {
10242          /* Read digit unless it's supposed to be immediate, in which case the
10243             only answer is 's' */
10244          if (p->immediate)
10245             res = 's';
10246          else
10247             res = ast_waitfordigit(chan, timeout);
10248          timeout = 0;
10249          if (res < 0) {
10250             ast_debug(1, "waitfordigit returned < 0...\n");
10251             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10252             ast_hangup(chan);
10253             goto quit;
10254          } else if (res) {
10255             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10256             exten[len++]=res;
10257             exten[len] = '\0';
10258          }
10259          if (!ast_ignore_pattern(chan->context, exten))
10260             tone_zone_play_tone(p->subs[idx].dfd, -1);
10261          else
10262             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10263          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10264             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10265                if (getforward) {
10266                   /* Record this as the forwarding extension */
10267                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10268                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10269                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10270                   if (res)
10271                      break;
10272                   usleep(500000);
10273                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10274                   sleep(1);
10275                   memset(exten, 0, sizeof(exten));
10276                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10277                   len = 0;
10278                   getforward = 0;
10279                } else {
10280                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10281                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10282                   if (!ast_strlen_zero(p->cid_num)) {
10283                      if (!p->hidecallerid)
10284                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10285                      else
10286                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10287                   }
10288                   if (!ast_strlen_zero(p->cid_name)) {
10289                      if (!p->hidecallerid)
10290                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10291                   }
10292                   ast_setstate(chan, AST_STATE_RING);
10293                   dahdi_enable_ec(p);
10294                   res = ast_pbx_run(chan);
10295                   if (res) {
10296                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10297                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10298                   }
10299                   goto quit;
10300                }
10301             } else {
10302                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10303                   so just set the timeout to matchdigittimeout and wait some more */
10304                timeout = matchdigittimeout;
10305             }
10306          } else if (res == 0) {
10307             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10308             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10309             dahdi_wait_event(p->subs[idx].dfd);
10310             ast_hangup(chan);
10311             goto quit;
10312          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10313             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10314             /* Disable call waiting if enabled */
10315             p->callwaiting = 0;
10316             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10317             if (res) {
10318                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10319                   chan->name, strerror(errno));
10320             }
10321             len = 0;
10322             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10323             memset(exten, 0, sizeof(exten));
10324             timeout = firstdigittimeout;
10325 
10326          } else if (!strcmp(exten,ast_pickup_ext())) {
10327             /* Scan all channels and see if there are any
10328              * ringing channels that have call groups
10329              * that equal this channels pickup group
10330              */
10331             if (idx == SUB_REAL) {
10332                /* Switch us from Third call to Call Wait */
10333                if (p->subs[SUB_THREEWAY].owner) {
10334                   /* If you make a threeway call and the *8# a call, it should actually
10335                      look like a callwait */
10336                   alloc_sub(p, SUB_CALLWAIT);
10337                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10338                   unalloc_sub(p, SUB_THREEWAY);
10339                }
10340                dahdi_enable_ec(p);
10341                if (ast_pickup_call(chan)) {
10342                   ast_debug(1, "No call pickup possible...\n");
10343                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10344                   dahdi_wait_event(p->subs[idx].dfd);
10345                }
10346                ast_hangup(chan);
10347                goto quit;
10348             } else {
10349                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10350                ast_hangup(chan);
10351                goto quit;
10352             }
10353 
10354          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10355             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10356             /* Disable Caller*ID if enabled */
10357             p->hidecallerid = 1;
10358             ast_party_number_free(&chan->caller.id.number);
10359             ast_party_number_init(&chan->caller.id.number);
10360             ast_party_name_free(&chan->caller.id.name);
10361             ast_party_name_init(&chan->caller.id.name);
10362             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10363             if (res) {
10364                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10365                   chan->name, strerror(errno));
10366             }
10367             len = 0;
10368             memset(exten, 0, sizeof(exten));
10369             timeout = firstdigittimeout;
10370          } else if (p->callreturn && !strcmp(exten, "*69")) {
10371             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372             break;
10373          } else if (!strcmp(exten, "*78")) {
10374             dahdi_dnd(p, 1);
10375             /* Do not disturb */
10376             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10377             getforward = 0;
10378             memset(exten, 0, sizeof(exten));
10379             len = 0;
10380          } else if (!strcmp(exten, "*79")) {
10381             dahdi_dnd(p, 0);
10382             /* Do not disturb */
10383             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384             getforward = 0;
10385             memset(exten, 0, sizeof(exten));
10386             len = 0;
10387          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10388             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10389             getforward = 1;
10390             memset(exten, 0, sizeof(exten));
10391             len = 0;
10392          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10393             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10394             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10395             memset(p->call_forward, 0, sizeof(p->call_forward));
10396             getforward = 0;
10397             memset(exten, 0, sizeof(exten));
10398             len = 0;
10399          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10400                   p->subs[SUB_THREEWAY].owner &&
10401                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10402             /* This is a three way call, the main call being a real channel,
10403                and we're parking the first call. */
10404             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10405                chan, exten, chan->context, 0, NULL);
10406             ast_verb(3, "Parking call to '%s'\n", chan->name);
10407             break;
10408          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10409             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10410             /* Enable Caller*ID if enabled */
10411             p->hidecallerid = 0;
10412             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10413             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10414             if (res) {
10415                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10416                   chan->name, strerror(errno));
10417             }
10418             len = 0;
10419             memset(exten, 0, sizeof(exten));
10420             timeout = firstdigittimeout;
10421          } else if (!strcmp(exten, "*0")) {
10422             struct ast_channel *nbridge =
10423                p->subs[SUB_THREEWAY].owner;
10424             struct dahdi_pvt *pbridge = NULL;
10425             /* set up the private struct of the bridged one, if any */
10426             if (nbridge && ast_bridged_channel(nbridge))
10427                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10428             if (nbridge && pbridge &&
10429                (nbridge->tech == &dahdi_tech) &&
10430                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10431                ISTRUNK(pbridge)) {
10432                int func = DAHDI_FLASH;
10433                /* Clear out the dial buffer */
10434                p->dop.dialstr[0] = '\0';
10435                /* flash hookswitch */
10436                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10437                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10438                      nbridge->name, strerror(errno));
10439                }
10440                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10441                unalloc_sub(p, SUB_THREEWAY);
10442                p->owner = p->subs[SUB_REAL].owner;
10443                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10444                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10445                ast_hangup(chan);
10446                goto quit;
10447             } else {
10448                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10449                dahdi_wait_event(p->subs[idx].dfd);
10450                tone_zone_play_tone(p->subs[idx].dfd, -1);
10451                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10452                unalloc_sub(p, SUB_THREEWAY);
10453                p->owner = p->subs[SUB_REAL].owner;
10454                ast_hangup(chan);
10455                goto quit;
10456             }
10457          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10458             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10459             && !canmatch_featurecode(exten)) {
10460             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10461                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10462                chan->context);
10463             break;
10464          }
10465          if (!timeout)
10466             timeout = gendigittimeout;
10467          if (len && !ast_ignore_pattern(chan->context, exten))
10468             tone_zone_play_tone(p->subs[idx].dfd, -1);
10469       }
10470       break;
10471    case SIG_FXSLS:
10472    case SIG_FXSGS:
10473    case SIG_FXSKS:
10474       /* check for SMDI messages */
10475       if (p->use_smdi && p->smdi_iface) {
10476          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10477 
10478          if (smdi_msg != NULL) {
10479             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10480 
10481             if (smdi_msg->type == 'B')
10482                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10483             else if (smdi_msg->type == 'N')
10484                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10485 
10486             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10487          } else {
10488             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10489          }
10490       }
10491 
10492       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10493          number = smdi_msg->calling_st;
10494 
10495       /* If we want caller id, we're in a prering state due to a polarity reversal
10496        * and we're set to use a polarity reversal to trigger the start of caller id,
10497        * grab the caller id and wait for ringing to start... */
10498       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10499                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10500          /* If set to use DTMF CID signalling, listen for DTMF */
10501          if (p->cid_signalling == CID_SIG_DTMF) {
10502             int k = 0;
10503             cs = NULL;
10504             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10505             dahdi_setlinear(p->subs[idx].dfd, 0);
10506             /*
10507              * We are the only party interested in the Rx stream since
10508              * we have not answered yet.  We don't need or even want DTMF
10509              * emulation.  The DTMF digits can come so fast that emulation
10510              * can drop some of them.
10511              */
10512             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10513             res = 4000;/* This is a typical OFF time between rings. */
10514             for (;;) {
10515                struct ast_frame *f;
10516                res = ast_waitfor(chan, res);
10517                if (res <= 0) {
10518                   /*
10519                    * We do not need to restore the dahdi_setlinear()
10520                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10521                    * are hanging up the channel.
10522                    */
10523                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10524                      "Exiting simple switch\n");
10525                   ast_hangup(chan);
10526                   goto quit;
10527                }
10528                f = ast_read(chan);
10529                if (!f)
10530                   break;
10531                if (f->frametype == AST_FRAME_DTMF) {
10532                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10533                      dtmfbuf[k++] = f->subclass.integer;
10534                   }
10535                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10536                   res = 4000;/* This is a typical OFF time between rings. */
10537                }
10538                ast_frfree(f);
10539                if (chan->_state == AST_STATE_RING ||
10540                   chan->_state == AST_STATE_RINGING)
10541                   break; /* Got ring */
10542             }
10543             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10544             dtmfbuf[k] = '\0';
10545             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10546             /* Got cid and ring. */
10547             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10548             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10549             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10550             /* If first byte is NULL, we have no cid */
10551             if (!ast_strlen_zero(dtmfcid))
10552                number = dtmfcid;
10553             else
10554                number = NULL;
10555          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10556          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10557             cs = callerid_new(p->cid_signalling);
10558             if (cs) {
10559                samples = 0;
10560 #if 1
10561                bump_gains(p);
10562 #endif
10563                /* Take out of linear mode for Caller*ID processing */
10564                dahdi_setlinear(p->subs[idx].dfd, 0);
10565 
10566                /* First we wait and listen for the Caller*ID */
10567                for (;;) {
10568                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10569                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10570                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10571                      callerid_free(cs);
10572                      ast_hangup(chan);
10573                      goto quit;
10574                   }
10575                   if (i & DAHDI_IOMUX_SIGEVENT) {
10576                      res = dahdi_get_event(p->subs[idx].dfd);
10577                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10578                      if (res == DAHDI_EVENT_NOALARM) {
10579                         p->inalarm = 0;
10580                      }
10581 
10582                      if (p->cid_signalling == CID_SIG_V23_JP) {
10583                         if (res == DAHDI_EVENT_RINGBEGIN) {
10584                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10585                            usleep(1);
10586                         }
10587                      } else {
10588                         res = 0;
10589                         break;
10590                      }
10591                   } else if (i & DAHDI_IOMUX_READ) {
10592                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10593                      if (res < 0) {
10594                         if (errno != ELAST) {
10595                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10596                            callerid_free(cs);
10597                            ast_hangup(chan);
10598                            goto quit;
10599                         }
10600                         break;
10601                      }
10602                      samples += res;
10603 
10604                      if (p->cid_signalling == CID_SIG_V23_JP) {
10605                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10606                      } else {
10607                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10608                      }
10609                      if (res < 0) {
10610                         /*
10611                          * The previous diagnostic message output likely
10612                          * explains why it failed.
10613                          */
10614                         ast_log(LOG_WARNING,
10615                            "Failed to decode CallerID on channel '%s'\n",
10616                            chan->name);
10617                         break;
10618                      } else if (res)
10619                         break;
10620                      else if (samples > (8000 * 10))
10621                         break;
10622                   }
10623                }
10624                if (res == 1) {
10625                   callerid_get(cs, &name, &number, &flags);
10626                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10627                }
10628 
10629                if (p->cid_signalling == CID_SIG_V23_JP) {
10630                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10631                   usleep(1);
10632                }
10633 
10634                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10635                res = 4000;/* This is a typical OFF time between rings. */
10636                for (;;) {
10637                   struct ast_frame *f;
10638                   res = ast_waitfor(chan, res);
10639                   if (res <= 0) {
10640                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10641                         "Exiting simple switch\n");
10642                      ast_hangup(chan);
10643                      goto quit;
10644                   }
10645                   if (!(f = ast_read(chan))) {
10646                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10647                      ast_hangup(chan);
10648                      goto quit;
10649                   }
10650                   ast_frfree(f);
10651                   if (chan->_state == AST_STATE_RING ||
10652                      chan->_state == AST_STATE_RINGING)
10653                      break; /* Got ring */
10654                }
10655 
10656                /* We must have a ring by now, so, if configured, lets try to listen for
10657                 * distinctive ringing */
10658                if (p->usedistinctiveringdetection) {
10659                   len = 0;
10660                   distMatches = 0;
10661                   /* Clear the current ring data array so we don't have old data in it. */
10662                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10663                      curRingData[receivedRingT] = 0;
10664                   receivedRingT = 0;
10665                   counter = 0;
10666                   counter1 = 0;
10667                   /* Check to see if context is what it should be, if not set to be. */
10668                   if (strcmp(p->context,p->defcontext) != 0) {
10669                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10670                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10671                   }
10672 
10673                   for (;;) {
10674                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10675                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10676                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10677                         callerid_free(cs);
10678                         ast_hangup(chan);
10679                         goto quit;
10680                      }
10681                      if (i & DAHDI_IOMUX_SIGEVENT) {
10682                         res = dahdi_get_event(p->subs[idx].dfd);
10683                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10684                         if (res == DAHDI_EVENT_NOALARM) {
10685                            p->inalarm = 0;
10686                         }
10687                         res = 0;
10688                         /* Let us detect distinctive ring */
10689 
10690                         curRingData[receivedRingT] = p->ringt;
10691 
10692                         if (p->ringt < p->ringt_base/2)
10693                            break;
10694                         /* Increment the ringT counter so we can match it against
10695                            values in chan_dahdi.conf for distinctive ring */
10696                         if (++receivedRingT == ARRAY_LEN(curRingData))
10697                            break;
10698                      } else if (i & DAHDI_IOMUX_READ) {
10699                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10700                         if (res < 0) {
10701                            if (errno != ELAST) {
10702                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10703                               callerid_free(cs);
10704                               ast_hangup(chan);
10705                               goto quit;
10706                            }
10707                            break;
10708                         }
10709                         if (p->ringt > 0) {
10710                            if (!(--p->ringt)) {
10711                               res = -1;
10712                               break;
10713                            }
10714                         }
10715                      }
10716                   }
10717                      /* this only shows up if you have n of the dring patterns filled in */
10718                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10719                   for (counter = 0; counter < 3; counter++) {
10720                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10721                      channel */
10722                      distMatches = 0;
10723                      for (counter1 = 0; counter1 < 3; counter1++) {
10724                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10725                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10726                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10727                            curRingData[counter1]);
10728                            distMatches++;
10729                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10730                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10731                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10732                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10733                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10734                            distMatches++;
10735                         }
10736                      }
10737 
10738                      if (distMatches == 3) {
10739                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10740                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10741                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10742                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10743                         break;
10744                      }
10745                   }
10746                }
10747                /* Restore linear mode (if appropriate) for Caller*ID processing */
10748                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10749 #if 1
10750                restore_gains(p);
10751 #endif
10752             } else
10753                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10754          } else {
10755             ast_log(LOG_WARNING, "Channel %s in prering "
10756                "state, but I have nothing to do. "
10757                "Terminating simple switch, should be "
10758                "restarted by the actual ring.\n",
10759                chan->name);
10760             ast_hangup(chan);
10761             goto quit;
10762          }
10763       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10764          if (p->cid_signalling == CID_SIG_DTMF) {
10765             int k = 0;
10766             cs = NULL;
10767             dahdi_setlinear(p->subs[idx].dfd, 0);
10768             res = 2000;
10769             for (;;) {
10770                struct ast_frame *f;
10771                res = ast_waitfor(chan, res);
10772                if (res <= 0) {
10773                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10774                      "Exiting simple switch\n");
10775                   ast_hangup(chan);
10776                   goto quit;
10777                }
10778                f = ast_read(chan);
10779                if (!f) {
10780                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10781                   ast_hangup(chan);
10782                   goto quit;
10783                }
10784                if (f->frametype == AST_FRAME_DTMF) {
10785                   dtmfbuf[k++] = f->subclass.integer;
10786                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10787                   res = 2000;
10788                }
10789                ast_frfree(f);
10790 
10791                if (p->ringt_base == p->ringt)
10792                   break;
10793             }
10794             dtmfbuf[k] = '\0';
10795             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10796             /* Got cid and ring. */
10797             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10798             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10799                dtmfcid, flags);
10800             /* If first byte is NULL, we have no cid */
10801             if (!ast_strlen_zero(dtmfcid))
10802                number = dtmfcid;
10803             else
10804                number = NULL;
10805             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10806          } else {
10807             /* FSK Bell202 callerID */
10808             cs = callerid_new(p->cid_signalling);
10809             if (cs) {
10810 #if 1
10811                bump_gains(p);
10812 #endif
10813                samples = 0;
10814                len = 0;
10815                distMatches = 0;
10816                /* Clear the current ring data array so we don't have old data in it. */
10817                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10818                   curRingData[receivedRingT] = 0;
10819                receivedRingT = 0;
10820                counter = 0;
10821                counter1 = 0;
10822                /* Check to see if context is what it should be, if not set to be. */
10823                if (strcmp(p->context,p->defcontext) != 0) {
10824                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10825                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10826                }
10827 
10828                /* Take out of linear mode for Caller*ID processing */
10829                dahdi_setlinear(p->subs[idx].dfd, 0);
10830                for (;;) {
10831                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10832                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10833                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10834                      callerid_free(cs);
10835                      ast_hangup(chan);
10836                      goto quit;
10837                   }
10838                   if (i & DAHDI_IOMUX_SIGEVENT) {
10839                      res = dahdi_get_event(p->subs[idx].dfd);
10840                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10841                      if (res == DAHDI_EVENT_NOALARM) {
10842                         p->inalarm = 0;
10843                      }
10844                      /* If we get a PR event, they hung up while processing calerid */
10845                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10846                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10847                         p->polarity = POLARITY_IDLE;
10848                         callerid_free(cs);
10849                         ast_hangup(chan);
10850                         goto quit;
10851                      }
10852                      res = 0;
10853                      /* Let us detect callerid when the telco uses distinctive ring */
10854 
10855                      curRingData[receivedRingT] = p->ringt;
10856 
10857                      if (p->ringt < p->ringt_base/2)
10858                         break;
10859                      /* Increment the ringT counter so we can match it against
10860                         values in chan_dahdi.conf for distinctive ring */
10861                      if (++receivedRingT == ARRAY_LEN(curRingData))
10862                         break;
10863                   } else if (i & DAHDI_IOMUX_READ) {
10864                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10865                      if (res < 0) {
10866                         if (errno != ELAST) {
10867                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10868                            callerid_free(cs);
10869                            ast_hangup(chan);
10870                            goto quit;
10871                         }
10872                         break;
10873                      }
10874                      if (p->ringt > 0) {
10875                         if (!(--p->ringt)) {
10876                            res = -1;
10877                            break;
10878                         }
10879                      }
10880                      samples += res;
10881                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10882                      if (res < 0) {
10883                         /*
10884                          * The previous diagnostic message output likely
10885                          * explains why it failed.
10886                          */
10887                         ast_log(LOG_WARNING,
10888                            "Failed to decode CallerID on channel '%s'\n",
10889                            chan->name);
10890                         break;
10891                      } else if (res)
10892                         break;
10893                      else if (samples > (8000 * 10))
10894                         break;
10895                   }
10896                }
10897                if (res == 1) {
10898                   callerid_get(cs, &name, &number, &flags);
10899                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10900                }
10901                if (distinctiveringaftercid == 1) {
10902                   /* Clear the current ring data array so we don't have old data in it. */
10903                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10904                      curRingData[receivedRingT] = 0;
10905                   }
10906                   receivedRingT = 0;
10907                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10908                   for (;;) {
10909                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10910                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10911                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10912                         callerid_free(cs);
10913                         ast_hangup(chan);
10914                         goto quit;
10915                      }
10916                      if (i & DAHDI_IOMUX_SIGEVENT) {
10917                         res = dahdi_get_event(p->subs[idx].dfd);
10918                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10919                         if (res == DAHDI_EVENT_NOALARM) {
10920                            p->inalarm = 0;
10921                         }
10922                         res = 0;
10923                         /* Let us detect callerid when the telco uses distinctive ring */
10924 
10925                         curRingData[receivedRingT] = p->ringt;
10926 
10927                         if (p->ringt < p->ringt_base/2)
10928                            break;
10929                         /* Increment the ringT counter so we can match it against
10930                            values in chan_dahdi.conf for distinctive ring */
10931                         if (++receivedRingT == ARRAY_LEN(curRingData))
10932                            break;
10933                      } else if (i & DAHDI_IOMUX_READ) {
10934                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10935                         if (res < 0) {
10936                            if (errno != ELAST) {
10937                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10938                               callerid_free(cs);
10939                               ast_hangup(chan);
10940                               goto quit;
10941                            }
10942                            break;
10943                         }
10944                         if (p->ringt > 0) {
10945                            if (!(--p->ringt)) {
10946                               res = -1;
10947                               break;
10948                            }
10949                         }
10950                      }
10951                   }
10952                }
10953                if (p->usedistinctiveringdetection) {
10954                   /* this only shows up if you have n of the dring patterns filled in */
10955                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10956 
10957                   for (counter = 0; counter < 3; counter++) {
10958                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10959                      channel */
10960                      /* this only shows up if you have n of the dring patterns filled in */
10961                      ast_verb(3, "Checking %d,%d,%d\n",
10962                            p->drings.ringnum[counter].ring[0],
10963                            p->drings.ringnum[counter].ring[1],
10964                            p->drings.ringnum[counter].ring[2]);
10965                      distMatches = 0;
10966                      for (counter1 = 0; counter1 < 3; counter1++) {
10967                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10968                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10969                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10970                            curRingData[counter1]);
10971                            distMatches++;
10972                         }
10973                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10974                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10975                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10976                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10977                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10978                            distMatches++;
10979                         }
10980                      }
10981                      if (distMatches == 3) {
10982                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10983                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10984                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10985                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10986                         break;
10987                      }
10988                   }
10989                }
10990                /* Restore linear mode (if appropriate) for Caller*ID processing */
10991                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10992 #if 1
10993                restore_gains(p);
10994 #endif
10995                if (res < 0) {
10996                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10997                }
10998             } else
10999                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11000          }
11001       } else
11002          cs = NULL;
11003 
11004       if (number)
11005          ast_shrink_phone_number(number);
11006       ast_set_callerid(chan, number, name, number);
11007 
11008       if (smdi_msg)
11009          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11010 
11011       if (cs)
11012          callerid_free(cs);
11013 
11014       my_handle_notify_message(chan, p, flags, -1);
11015 
11016       ast_setstate(chan, AST_STATE_RING);
11017       chan->rings = 1;
11018       p->ringt = p->ringt_base;
11019       res = ast_pbx_run(chan);
11020       if (res) {
11021          ast_hangup(chan);
11022          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11023       }
11024       goto quit;
11025    default:
11026       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11027       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11028       if (res < 0)
11029             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11030    }
11031    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11032    if (res < 0)
11033          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11034    ast_hangup(chan);
11035 quit:
11036    ast_mutex_lock(&ss_thread_lock);
11037    ss_thread_count--;
11038    ast_cond_signal(&ss_thread_complete);
11039    ast_mutex_unlock(&ss_thread_lock);
11040    return NULL;
11041 }
11042 
11043 struct mwi_thread_data {
11044    struct dahdi_pvt *pvt;
11045    unsigned char buf[READ_SIZE];
11046    size_t len;
11047 };
11048 
11049 static int calc_energy(const unsigned char *buf, int len, format_t law)
11050 {
11051    int x;
11052    int sum = 0;
11053 
11054    if (!len)
11055       return 0;
11056 
11057    for (x = 0; x < len; x++)
11058       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11059 
11060    return sum / len;
11061 }
11062 
11063 static void *mwi_thread(void *data)
11064 {
11065    struct mwi_thread_data *mtd = data;
11066    struct callerid_state *cs;
11067    pthread_t threadid;
11068    int samples = 0;
11069    char *name, *number;
11070    int flags;
11071    int i, res;
11072    unsigned int spill_done = 0;
11073    int spill_result = -1;
11074 
11075    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11076       goto quit_no_clean;
11077    }
11078 
11079    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11080 
11081    bump_gains(mtd->pvt);
11082 
11083    for (;;) {
11084       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11085       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11086          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11087          goto quit;
11088       }
11089 
11090       if (i & DAHDI_IOMUX_SIGEVENT) {
11091          struct ast_channel *chan;
11092 
11093          /* If we get an event, screen out events that we do not act on.
11094           * Otherwise, cancel and go to the simple switch to let it deal with it.
11095           */
11096          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11097 
11098          switch (res) {
11099          case DAHDI_EVENT_NEONMWI_ACTIVE:
11100          case DAHDI_EVENT_NEONMWI_INACTIVE:
11101          case DAHDI_EVENT_NONE:
11102          case DAHDI_EVENT_BITSCHANGED:
11103             break;
11104          case DAHDI_EVENT_NOALARM:
11105             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11106                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11107 
11108                analog_p->inalarm = 0;
11109             }
11110             mtd->pvt->inalarm = 0;
11111             handle_clear_alarms(mtd->pvt);
11112             break;
11113          case DAHDI_EVENT_ALARM:
11114             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11115                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11116 
11117                analog_p->inalarm = 1;
11118             }
11119             mtd->pvt->inalarm = 1;
11120             res = get_alarms(mtd->pvt);
11121             handle_alarms(mtd->pvt, res);
11122             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11123          default:
11124             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11125             callerid_free(cs);
11126 
11127             restore_gains(mtd->pvt);
11128             mtd->pvt->ringt = mtd->pvt->ringt_base;
11129 
11130             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11131                int result;
11132 
11133                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11134                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11135                } else {
11136                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11137                }
11138                if (result) {
11139                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11140                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11141                   if (res < 0)
11142                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11143                   ast_hangup(chan);
11144                }
11145             } else {
11146                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11147             }
11148             goto quit_no_clean;
11149          }
11150       } else if (i & DAHDI_IOMUX_READ) {
11151          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11152             if (errno != ELAST) {
11153                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11154                goto quit;
11155             }
11156             break;
11157          }
11158          samples += res;
11159          if (!spill_done) {
11160             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11161                /*
11162                 * The previous diagnostic message output likely
11163                 * explains why it failed.
11164                 */
11165                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11166                break;
11167             } else if (spill_result) {
11168                spill_done = 1;
11169             }
11170          } else {
11171             /* keep reading data until the energy level drops below the threshold
11172                so we don't get another 'trigger' on the remaining carrier signal
11173             */
11174             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11175                break;
11176          }
11177          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11178             break;
11179       }
11180    }
11181 
11182    if (spill_result == 1) {
11183       callerid_get(cs, &name, &number, &flags);
11184       if (flags & CID_MSGWAITING) {
11185          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11186          notify_message(mtd->pvt->mailbox, 1);
11187       } else if (flags & CID_NOMSGWAITING) {
11188          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11189          notify_message(mtd->pvt->mailbox, 0);
11190       } else {
11191          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11192       }
11193    }
11194 
11195 
11196 quit:
11197    callerid_free(cs);
11198 
11199    restore_gains(mtd->pvt);
11200 
11201 quit_no_clean:
11202    mtd->pvt->mwimonitoractive = 0;
11203    ast_free(mtd);
11204 
11205    return NULL;
11206 }
11207 
11208 /*
11209 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11210 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11211 * that are sent out via FXS port on voicemail state change.  The execution of
11212 * the mwi send is state driven and can either generate a ring pulse prior to
11213 * sending the fsk spill or simply send an fsk spill.
11214 */
11215 static int mwi_send_init(struct dahdi_pvt * pvt)
11216 {
11217    int x;
11218 
11219 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11220    /* Determine how this spill is to be sent */
11221    if (pvt->mwisend_rpas) {
11222       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11223       pvt->mwisendactive = 1;
11224    } else if (pvt->mwisend_fsk) {
11225       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11226       pvt->mwisendactive = 1;
11227    } else {
11228       pvt->mwisendactive = 0;
11229       return 0;
11230    }
11231 #else
11232    if (mwisend_rpas) {
11233       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11234    } else {
11235       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11236    }
11237    pvt->mwisendactive = 1;
11238 #endif
11239 
11240    if (pvt->cidspill) {
11241       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11242       ast_free(pvt->cidspill);
11243       pvt->cidspill = NULL;
11244       pvt->cidpos = 0;
11245       pvt->cidlen = 0;
11246    }
11247    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11248    if (!pvt->cidspill) {
11249       pvt->mwisendactive = 0;
11250       return -1;
11251    }
11252    x = DAHDI_FLUSH_BOTH;
11253    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11254    x = 3000;
11255    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11256 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11257    if (pvt->mwisend_fsk) {
11258 #endif
11259       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11260                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11261       pvt->cidpos = 0;
11262 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11263    }
11264 #endif
11265    return 0;
11266 }
11267 
11268 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11269 {
11270    struct timeval    now;
11271    int         res;
11272 
11273    /* sanity check to catch if this had been interrupted previously
11274    *  i.e. state says there is more to do but there is no spill allocated
11275    */
11276    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11277       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11278    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11279       /* Normal processing -- Perform mwi send action */
11280       switch ( pvt->mwisend_data.mwisend_current) {
11281       case MWI_SEND_SA:
11282          /* Send the Ring Pulse Signal Alert */
11283          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11284          if (res) {
11285             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11286             goto quit;
11287          }
11288          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11289          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11290          break;
11291       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11292          break;
11293       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11294 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11295          if (pvt->mwisend_fsk) {
11296 #endif
11297             gettimeofday(&now, NULL);
11298             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11299                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11300             }
11301 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11302          } else { /* support for mwisendtype=nofsk */
11303             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11304          }
11305 #endif
11306          break;
11307       case MWI_SEND_SPILL:
11308          /* We read some number of bytes.  Write an equal amount of data */
11309          if(0 < num_read) {
11310             if (num_read > pvt->cidlen - pvt->cidpos)
11311                num_read = pvt->cidlen - pvt->cidpos;
11312             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11313             if (res > 0) {
11314                pvt->cidpos += res;
11315                if (pvt->cidpos >= pvt->cidlen) {
11316                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11317                }
11318             } else {
11319                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11320                goto quit;
11321             }
11322          }
11323          break;
11324       case MWI_SEND_CLEANUP:
11325          /* For now, do nothing */
11326          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11327          break;
11328       default:
11329          /* Should not get here, punt*/
11330          goto quit;
11331       }
11332    }
11333 
11334    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11335       if (pvt->cidspill) {
11336          ast_free(pvt->cidspill);
11337          pvt->cidspill = NULL;
11338          pvt->cidpos = 0;
11339          pvt->cidlen = 0;
11340       }
11341       pvt->mwisendactive = 0;
11342    }
11343    return 0;
11344 quit:
11345    if (pvt->cidspill) {
11346       ast_free(pvt->cidspill);
11347       pvt->cidspill = NULL;
11348       pvt->cidpos = 0;
11349       pvt->cidlen = 0;
11350    }
11351    pvt->mwisendactive = 0;
11352    return -1;
11353 }
11354 
11355 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11356 {
11357    int handled = 0;
11358 
11359    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11360       switch (event) {
11361       case DAHDI_EVENT_RINGEROFF:
11362          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11363             handled = 1;
11364 
11365             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11366                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11367                ast_free(pvt->cidspill);
11368                pvt->cidspill = NULL;
11369                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11370                pvt->mwisendactive = 0;
11371             } else {
11372                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11373                gettimeofday(&pvt->mwisend_data.pause, NULL);
11374             }
11375          }
11376          break;
11377       /* Going off hook, I need to punt this spill */
11378       case DAHDI_EVENT_RINGOFFHOOK:
11379          if (pvt->cidspill) {
11380             ast_free(pvt->cidspill);
11381             pvt->cidspill = NULL;
11382             pvt->cidpos = 0;
11383             pvt->cidlen = 0;
11384          }
11385          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11386          pvt->mwisendactive = 0;
11387          break;
11388       case DAHDI_EVENT_RINGERON:
11389       case DAHDI_EVENT_HOOKCOMPLETE:
11390          break;
11391       default:
11392          break;
11393       }
11394    }
11395    return handled;
11396 }
11397 
11398 /* destroy a DAHDI channel, identified by its number */
11399 static int dahdi_destroy_channel_bynum(int channel)
11400 {
11401    struct dahdi_pvt *cur;
11402 
11403    ast_mutex_lock(&iflock);
11404    for (cur = iflist; cur; cur = cur->next) {
11405       if (cur->channel == channel) {
11406          int x = DAHDI_FLASH;
11407 
11408          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11409          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11410 
11411          destroy_channel(cur, 1);
11412          ast_mutex_unlock(&iflock);
11413          ast_module_unref(ast_module_info->self);
11414          return RESULT_SUCCESS;
11415       }
11416    }
11417    ast_mutex_unlock(&iflock);
11418    return RESULT_FAILURE;
11419 }
11420 
11421 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11422 {
11423    int res;
11424    pthread_t threadid;
11425    struct ast_channel *chan;
11426 
11427    /* Handle an event on a given channel for the monitor thread. */
11428 
11429    switch (event) {
11430    case DAHDI_EVENT_NONE:
11431    case DAHDI_EVENT_BITSCHANGED:
11432       break;
11433    case DAHDI_EVENT_WINKFLASH:
11434    case DAHDI_EVENT_RINGOFFHOOK:
11435       if (i->inalarm) break;
11436       if (i->radio) break;
11437       /* Got a ring/answer.  What kind of channel are we? */
11438       switch (i->sig) {
11439       case SIG_FXOLS:
11440       case SIG_FXOGS:
11441       case SIG_FXOKS:
11442          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11443          if (res && (errno == EBUSY))
11444             break;
11445 
11446          /* Cancel VMWI spill */
11447          ast_free(i->cidspill);
11448          i->cidspill = NULL;
11449          restore_conference(i);
11450 
11451          if (i->immediate) {
11452             dahdi_enable_ec(i);
11453             /* The channel is immediately up.  Start right away */
11454             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11455             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11456             if (!chan) {
11457                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11458                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11459                if (res < 0)
11460                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11461             }
11462          } else {
11463             /* Check for callerid, digits, etc */
11464             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11465             if (chan) {
11466                if (has_voicemail(i))
11467                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11468                else
11469                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11470                if (res < 0)
11471                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11472                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11473                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11474                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11475                   if (res < 0)
11476                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11477                   ast_hangup(chan);
11478                }
11479             } else
11480                ast_log(LOG_WARNING, "Unable to create channel\n");
11481          }
11482          break;
11483       case SIG_FXSLS:
11484       case SIG_FXSGS:
11485       case SIG_FXSKS:
11486             i->ringt = i->ringt_base;
11487             /* Fall through */
11488       case SIG_EMWINK:
11489       case SIG_FEATD:
11490       case SIG_FEATDMF:
11491       case SIG_FEATDMF_TA:
11492       case SIG_E911:
11493       case SIG_FGC_CAMA:
11494       case SIG_FGC_CAMAMF:
11495       case SIG_FEATB:
11496       case SIG_EM:
11497       case SIG_EM_E1:
11498       case SIG_SFWINK:
11499       case SIG_SF_FEATD:
11500       case SIG_SF_FEATDMF:
11501       case SIG_SF_FEATB:
11502       case SIG_SF:
11503          /* Check for callerid, digits, etc */
11504          if (i->cid_start == CID_START_POLARITY_IN) {
11505             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11506          } else {
11507             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11508          }
11509 
11510          if (!chan) {
11511             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11512          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11513             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11514             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11515             if (res < 0) {
11516                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11517             }
11518             ast_hangup(chan);
11519          }
11520          break;
11521       default:
11522          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11523          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11524          if (res < 0)
11525             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11526          return NULL;
11527       }
11528       break;
11529    case DAHDI_EVENT_NOALARM:
11530       switch (i->sig) {
11531 #if defined(HAVE_PRI)
11532       case SIG_PRI_LIB_HANDLE_CASES:
11533          ast_mutex_lock(&i->lock);
11534          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11535          ast_mutex_unlock(&i->lock);
11536          break;
11537 #endif   /* defined(HAVE_PRI) */
11538 #if defined(HAVE_SS7)
11539       case SIG_SS7:
11540          sig_ss7_set_alarm(i->sig_pvt, 0);
11541          break;
11542 #endif   /* defined(HAVE_SS7) */
11543       default:
11544          i->inalarm = 0;
11545          break;
11546       }
11547       handle_clear_alarms(i);
11548       break;
11549    case DAHDI_EVENT_ALARM:
11550       switch (i->sig) {
11551 #if defined(HAVE_PRI)
11552       case SIG_PRI_LIB_HANDLE_CASES:
11553          ast_mutex_lock(&i->lock);
11554          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11555          ast_mutex_unlock(&i->lock);
11556          break;
11557 #endif   /* defined(HAVE_PRI) */
11558 #if defined(HAVE_SS7)
11559       case SIG_SS7:
11560          sig_ss7_set_alarm(i->sig_pvt, 1);
11561          break;
11562 #endif   /* defined(HAVE_SS7) */
11563       default:
11564          i->inalarm = 1;
11565          break;
11566       }
11567       res = get_alarms(i);
11568       handle_alarms(i, res);
11569       /* fall thru intentionally */
11570    case DAHDI_EVENT_ONHOOK:
11571       if (i->radio)
11572          break;
11573       /* Back on hook.  Hang up. */
11574       switch (i->sig) {
11575       case SIG_FXOLS:
11576       case SIG_FXOGS:
11577       case SIG_FEATD:
11578       case SIG_FEATDMF:
11579       case SIG_FEATDMF_TA:
11580       case SIG_E911:
11581       case SIG_FGC_CAMA:
11582       case SIG_FGC_CAMAMF:
11583       case SIG_FEATB:
11584       case SIG_EM:
11585       case SIG_EM_E1:
11586       case SIG_EMWINK:
11587       case SIG_SF_FEATD:
11588       case SIG_SF_FEATDMF:
11589       case SIG_SF_FEATB:
11590       case SIG_SF:
11591       case SIG_SFWINK:
11592       case SIG_FXSLS:
11593       case SIG_FXSGS:
11594       case SIG_FXSKS:
11595       case SIG_FXOKS:
11596          dahdi_disable_ec(i);
11597          /* Diddle the battery for the zhone */
11598 #ifdef ZHONE_HACK
11599          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11600          usleep(1);
11601 #endif
11602          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11603          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11604          break;
11605       case SIG_SS7:
11606       case SIG_PRI_LIB_HANDLE_CASES:
11607          dahdi_disable_ec(i);
11608          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11609          break;
11610       default:
11611          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11612          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11613          return NULL;
11614       }
11615       break;
11616    case DAHDI_EVENT_POLARITY:
11617       switch (i->sig) {
11618       case SIG_FXSLS:
11619       case SIG_FXSKS:
11620       case SIG_FXSGS:
11621          /* We have already got a PR before the channel was
11622             created, but it wasn't handled. We need polarity
11623             to be REV for remote hangup detection to work.
11624             At least in Spain */
11625          if (i->hanguponpolarityswitch)
11626             i->polarity = POLARITY_REV;
11627          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11628             i->polarity = POLARITY_REV;
11629             ast_verb(2, "Starting post polarity "
11630                "CID detection on channel %d\n",
11631                i->channel);
11632             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11633             if (!chan) {
11634                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11635             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11636                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11637                ast_hangup(chan);
11638             }
11639          }
11640          break;
11641       default:
11642          ast_log(LOG_WARNING, "handle_init_event detected "
11643             "polarity reversal on non-FXO (SIG_FXS) "
11644             "interface %d\n", i->channel);
11645       }
11646       break;
11647    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11648       ast_log(LOG_NOTICE,
11649             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11650             i->channel);
11651       return i;
11652    case DAHDI_EVENT_NEONMWI_ACTIVE:
11653       if (i->mwimonitor_neon) {
11654          notify_message(i->mailbox, 1);
11655          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11656       }
11657       break;
11658    case DAHDI_EVENT_NEONMWI_INACTIVE:
11659       if (i->mwimonitor_neon) {
11660          notify_message(i->mailbox, 0);
11661          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11662       }
11663       break;
11664    }
11665    return NULL;
11666 }
11667 
11668 static void *do_monitor(void *data)
11669 {
11670    int count, res, res2, spoint, pollres=0;
11671    struct dahdi_pvt *i;
11672    struct dahdi_pvt *last = NULL;
11673    struct dahdi_pvt *doomed;
11674    time_t thispass = 0, lastpass = 0;
11675    int found;
11676    char buf[1024];
11677    struct pollfd *pfds=NULL;
11678    int lastalloc = -1;
11679    /* This thread monitors all the frame relay interfaces which are not yet in use
11680       (and thus do not have a separate thread) indefinitely */
11681    /* From here on out, we die whenever asked */
11682 #if 0
11683    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11684       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11685       return NULL;
11686    }
11687    ast_debug(1, "Monitor starting...\n");
11688 #endif
11689    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11690 
11691    for (;;) {
11692       /* Lock the interface list */
11693       ast_mutex_lock(&iflock);
11694       if (!pfds || (lastalloc != ifcount)) {
11695          if (pfds) {
11696             ast_free(pfds);
11697             pfds = NULL;
11698          }
11699          if (ifcount) {
11700             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11701                ast_mutex_unlock(&iflock);
11702                return NULL;
11703             }
11704          }
11705          lastalloc = ifcount;
11706       }
11707       /* Build the stuff we're going to poll on, that is the socket of every
11708          dahdi_pvt that does not have an associated owner channel */
11709       count = 0;
11710       for (i = iflist; i; i = i->next) {
11711          ast_mutex_lock(&i->lock);
11712          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11713             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11714                struct analog_pvt *p = i->sig_pvt;
11715 
11716                if (!p) {
11717                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11718                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11719                   /* This needs to be watched, as it lacks an owner */
11720                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11721                   pfds[count].events = POLLPRI;
11722                   pfds[count].revents = 0;
11723                   /* Message waiting or r2 channels also get watched for reading */
11724                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11725                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11726                      pfds[count].events |= POLLIN;
11727                   }
11728                   count++;
11729                }
11730             } else {
11731                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11732                   /* This needs to be watched, as it lacks an owner */
11733                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11734                   pfds[count].events = POLLPRI;
11735                   pfds[count].revents = 0;
11736                   /* If we are monitoring for VMWI or sending CID, we need to
11737                      read from the channel as well */
11738                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11739                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11740                      pfds[count].events |= POLLIN;
11741                   }
11742                   count++;
11743                }
11744             }
11745          }
11746          ast_mutex_unlock(&i->lock);
11747       }
11748       /* Okay, now that we know what to do, release the interface lock */
11749       ast_mutex_unlock(&iflock);
11750 
11751       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11752       pthread_testcancel();
11753       /* Wait at least a second for something to happen */
11754       res = poll(pfds, count, 1000);
11755       pthread_testcancel();
11756       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11757 
11758       /* Okay, poll has finished.  Let's see what happened.  */
11759       if (res < 0) {
11760          if ((errno != EAGAIN) && (errno != EINTR))
11761             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11762          continue;
11763       }
11764       /* Alright, lock the interface list again, and let's look and see what has
11765          happened */
11766       ast_mutex_lock(&iflock);
11767       found = 0;
11768       spoint = 0;
11769       lastpass = thispass;
11770       thispass = time(NULL);
11771       doomed = NULL;
11772       for (i = iflist;; i = i->next) {
11773          if (doomed) {
11774             int res;
11775             res = dahdi_destroy_channel_bynum(doomed->channel);
11776             if (res != RESULT_SUCCESS) {
11777                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11778             }
11779             doomed = NULL;
11780          }
11781          if (!i) {
11782             break;
11783          }
11784 
11785          if (thispass != lastpass) {
11786             if (!found && ((i == last) || ((i == iflist) && !last))) {
11787                last = i;
11788                if (last) {
11789                   struct analog_pvt *analog_p = last->sig_pvt;
11790                   /* Only allow MWI to be initiated on a quiescent fxs port */
11791                   if (analog_p
11792                      && !last->mwisendactive
11793                      && (last->sig & __DAHDI_SIG_FXO)
11794                      && !analog_p->fxsoffhookstate
11795                      && !last->owner
11796                      && !ast_strlen_zero(last->mailbox)
11797                      && (thispass - analog_p->onhooktime > 3)) {
11798                      res = has_voicemail(last);
11799                      if (analog_p->msgstate != res) {
11800                         /* Set driver resources for signalling VMWI */
11801                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11802                         if (res2) {
11803                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11804                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11805                         }
11806                         /* If enabled for FSK spill then initiate it */
11807                         if (mwi_send_init(last)) {
11808                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11809                         }
11810                         analog_p->msgstate = res;
11811                         found ++;
11812                      }
11813                   }
11814                   last = last->next;
11815                }
11816             }
11817          }
11818          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11819             if (i->radio && !i->owner)
11820             {
11821                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11822                if (res)
11823                {
11824                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11825                   /* Don't hold iflock while handling init events */
11826                   ast_mutex_unlock(&iflock);
11827                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11828                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11829                   else
11830                      doomed = handle_init_event(i, res);
11831                   ast_mutex_lock(&iflock);
11832                }
11833                continue;
11834             }
11835             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11836             if (pollres & POLLIN) {
11837                if (i->owner || i->subs[SUB_REAL].owner) {
11838 #ifdef HAVE_PRI
11839                   if (!i->pri)
11840 #endif
11841                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11842                   continue;
11843                }
11844                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11845                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11846                   continue;
11847                }
11848                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11849                if (res > 0) {
11850                   if (i->mwimonitor_fsk) {
11851                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11852                         pthread_attr_t attr;
11853                         pthread_t threadid;
11854                         struct mwi_thread_data *mtd;
11855 
11856                         pthread_attr_init(&attr);
11857                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11858 
11859                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11860                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11861                            mtd->pvt = i;
11862                            memcpy(mtd->buf, buf, res);
11863                            mtd->len = res;
11864                            i->mwimonitoractive = 1;
11865                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11866                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11867                               i->mwimonitoractive = 0;
11868                               ast_free(mtd);
11869                            }
11870                         }
11871                      }
11872                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11873                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11874                      int energy;
11875                      struct timeval now;
11876                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11877                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11878                      */
11879                      if (1 == i->dtmfcid_holdoff_state) {
11880                         gettimeofday(&i->dtmfcid_delay, NULL);
11881                         i->dtmfcid_holdoff_state = 2;
11882                      } else if (2 == i->dtmfcid_holdoff_state) {
11883                         gettimeofday(&now, NULL);
11884                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11885                            i->dtmfcid_holdoff_state = 0;
11886                         }
11887                      } else {
11888                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11889                         if (!i->mwisendactive && energy > dtmfcid_level) {
11890                            pthread_t threadid;
11891                            struct ast_channel *chan;
11892                            ast_mutex_unlock(&iflock);
11893                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11894                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11895                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11896                               i->dtmfcid_holdoff_state = 1;
11897                            } else {
11898                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11899                               if (!chan) {
11900                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11901                               } else {
11902                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11903                                  if (res) {
11904                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11905                                     ast_hangup(chan);
11906                                  } else {
11907                                     i->dtmfcid_holdoff_state = 1;
11908                                  }
11909                               }
11910                            }
11911                            ast_mutex_lock(&iflock);
11912                         }
11913                      }
11914                   }
11915                   if (i->mwisendactive) {
11916                      mwi_send_process_buffer(i, res);
11917                   }
11918                } else {
11919                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11920                }
11921             }
11922             if (pollres & POLLPRI) {
11923                if (i->owner || i->subs[SUB_REAL].owner) {
11924 #ifdef HAVE_PRI
11925                   if (!i->pri)
11926 #endif
11927                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11928                   continue;
11929                }
11930                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11931                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11932                /* Don't hold iflock while handling init events */
11933                ast_mutex_unlock(&iflock);
11934                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11935                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11936                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11937                   else
11938                      doomed = handle_init_event(i, res);
11939                }
11940                ast_mutex_lock(&iflock);
11941             }
11942          }
11943       }
11944       ast_mutex_unlock(&iflock);
11945    }
11946    /* Never reached */
11947    return NULL;
11948 
11949 }
11950 
11951 static int restart_monitor(void)
11952 {
11953    /* If we're supposed to be stopped -- stay stopped */
11954    if (monitor_thread == AST_PTHREADT_STOP)
11955       return 0;
11956    ast_mutex_lock(&monlock);
11957    if (monitor_thread == pthread_self()) {
11958       ast_mutex_unlock(&monlock);
11959       ast_log(LOG_WARNING, "Cannot kill myself\n");
11960       return -1;
11961    }
11962    if (monitor_thread != AST_PTHREADT_NULL) {
11963       /* Wake up the thread */
11964       pthread_kill(monitor_thread, SIGURG);
11965    } else {
11966       /* Start a new monitor */
11967       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11968          ast_mutex_unlock(&monlock);
11969          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11970          return -1;
11971       }
11972    }
11973    ast_mutex_unlock(&monlock);
11974    return 0;
11975 }
11976 
11977 #if defined(HAVE_PRI)
11978 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11979 {
11980    int x;
11981    int trunkgroup;
11982    /* Get appropriate trunk group if there is one */
11983    trunkgroup = pris[*span].mastertrunkgroup;
11984    if (trunkgroup) {
11985       /* Select a specific trunk group */
11986       for (x = 0; x < NUM_SPANS; x++) {
11987          if (pris[x].pri.trunkgroup == trunkgroup) {
11988             *span = x;
11989             return 0;
11990          }
11991       }
11992       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11993       *span = -1;
11994    } else {
11995       if (pris[*span].pri.trunkgroup) {
11996          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);
11997          *span = -1;
11998       } else if (pris[*span].mastertrunkgroup) {
11999          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12000          *span = -1;
12001       } else {
12002          if (si->totalchans == 31) {
12003             /* E1 */
12004             pris[*span].dchannels[0] = 16 + offset;
12005          } else if (si->totalchans == 24) {
12006             /* T1 or J1 */
12007             pris[*span].dchannels[0] = 24 + offset;
12008          } else if (si->totalchans == 3) {
12009             /* BRI */
12010             pris[*span].dchannels[0] = 3 + offset;
12011          } else {
12012             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);
12013             *span = -1;
12014             return 0;
12015          }
12016          pris[*span].pri.span = *span + 1;
12017       }
12018    }
12019    return 0;
12020 }
12021 #endif   /* defined(HAVE_PRI) */
12022 
12023 #if defined(HAVE_PRI)
12024 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12025 {
12026    struct dahdi_spaninfo si;
12027    struct dahdi_params p;
12028    int fd;
12029    int span;
12030    int ospan=0;
12031    int x,y;
12032    for (x = 0; x < NUM_SPANS; x++) {
12033       if (pris[x].pri.trunkgroup == trunkgroup) {
12034          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12035          return -1;
12036       }
12037    }
12038    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12039       if (!channels[y])
12040          break;
12041       memset(&si, 0, sizeof(si));
12042       memset(&p, 0, sizeof(p));
12043       fd = open("/dev/dahdi/channel", O_RDWR);
12044       if (fd < 0) {
12045          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12046          return -1;
12047       }
12048       x = channels[y];
12049       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12050          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12051          close(fd);
12052          return -1;
12053       }
12054       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12055          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12056          return -1;
12057       }
12058       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12059          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12060          close(fd);
12061          return -1;
12062       }
12063       span = p.spanno - 1;
12064       if (pris[span].pri.trunkgroup) {
12065          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12066          close(fd);
12067          return -1;
12068       }
12069       if (pris[span].pri.pvts[0]) {
12070          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12071          close(fd);
12072          return -1;
12073       }
12074       if (!y) {
12075          pris[span].pri.trunkgroup = trunkgroup;
12076          ospan = span;
12077       }
12078       pris[ospan].dchannels[y] = channels[y];
12079       pris[span].pri.span = span + 1;
12080       close(fd);
12081    }
12082    return 0;
12083 }
12084 #endif   /* defined(HAVE_PRI) */
12085 
12086 #if defined(HAVE_PRI)
12087 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12088 {
12089    if (pris[span].mastertrunkgroup) {
12090       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);
12091       return -1;
12092    }
12093    pris[span].mastertrunkgroup = trunkgroup;
12094    pris[span].prilogicalspan = logicalspan;
12095    return 0;
12096 }
12097 #endif   /* defined(HAVE_PRI) */
12098 
12099 #if defined(HAVE_SS7)
12100 static unsigned int parse_pointcode(const char *pcstring)
12101 {
12102    unsigned int code1, code2, code3;
12103    int numvals;
12104 
12105    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12106    if (numvals == 1)
12107       return code1;
12108    if (numvals == 3)
12109       return (code1 << 16) | (code2 << 8) | code3;
12110 
12111    return 0;
12112 }
12113 #endif   /* defined(HAVE_SS7) */
12114 
12115 #if defined(HAVE_SS7)
12116 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12117 {
12118    if ((linkset < 0) || (linkset >= NUM_SPANS))
12119       return NULL;
12120    else
12121       return &linksets[linkset - 1];
12122 }
12123 #endif   /* defined(HAVE_SS7) */
12124 
12125 #ifdef HAVE_OPENR2
12126 static void dahdi_r2_destroy_links(void)
12127 {
12128    int i = 0;
12129    if (!r2links) {
12130       return;
12131    }
12132    for (; i < r2links_count; i++) {
12133       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12134          pthread_cancel(r2links[i]->r2master);
12135          pthread_join(r2links[i]->r2master, NULL);
12136          openr2_context_delete(r2links[i]->protocol_context);
12137       }
12138       ast_free(r2links[i]);
12139    }
12140    ast_free(r2links);
12141    r2links = NULL;
12142    r2links_count = 0;
12143 }
12144 
12145 #define R2_LINK_CAPACITY 10
12146 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12147 {
12148    struct dahdi_mfcr2 *new_r2link = NULL;
12149    struct dahdi_mfcr2 **new_r2links = NULL;
12150    /* this function is called just when starting up and no monitor threads have been launched,
12151       no need to lock monitored_count member */
12152    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12153       new_r2link = ast_calloc(1, sizeof(**r2links));
12154       if (!new_r2link) {
12155          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12156          return NULL;
12157       }
12158       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12159       if (!new_r2links) {
12160          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12161          ast_free(new_r2link);
12162          return NULL;
12163       }
12164       r2links = new_r2links;
12165       new_r2link->r2master = AST_PTHREADT_NULL;
12166       r2links[r2links_count] = new_r2link;
12167       r2links_count++;
12168       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12169    }
12170    return r2links[r2links_count - 1];
12171 }
12172 
12173 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12174 {
12175    char tmplogdir[] = "/tmp";
12176    char logdir[OR2_MAX_PATH];
12177    int threshold = 0;
12178    int snres = 0;
12179    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12180          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12181          conf->mfcr2.max_dnis);
12182    if (!r2_link->protocol_context) {
12183       return -1;
12184    }
12185    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12186    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12187 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12188    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12189 #endif
12190    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12191    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12192    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12193    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12194    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12195    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12196       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12197          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12198       }
12199    } else {
12200       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12201       if (snres >= sizeof(logdir)) {
12202          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12203          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12204             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12205          }
12206       } else {
12207          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12208             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12209          }
12210       }
12211    }
12212    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12213       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12214          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12215       }
12216    }
12217    r2_link->monitored_count = 0;
12218    return 0;
12219 }
12220 #endif
12221 
12222 /* converts a DAHDI sigtype to signalling as can be configured from
12223  * chan_dahdi.conf.
12224  * While both have basically the same values, this will later be the
12225  * place to add filters and sanity checks
12226  */
12227 static int sigtype_to_signalling(int sigtype)
12228 {
12229    return sigtype;
12230 }
12231 
12232 /*!
12233  * \internal
12234  * \brief Get file name and channel number from (subdir,number)
12235  *
12236  * \param subdir name of the subdirectory under /dev/dahdi/
12237  * \param channel name of device file under /dev/dahdi/<subdir>/
12238  * \param path buffer to put file name in
12239  * \param pathlen maximal length of path
12240  *
12241  * \retval minor number of dahdi channel.
12242  * \retval -errno on error.
12243  */
12244 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12245 {
12246    struct stat stbuf;
12247    int      num;
12248 
12249    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12250    if (stat(path, &stbuf) < 0) {
12251       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12252       return -errno;
12253    }
12254    if (!S_ISCHR(stbuf.st_mode)) {
12255       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12256       return -EINVAL;
12257    }
12258    num = minor(stbuf.st_rdev);
12259    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12260    return num;
12261 
12262 }
12263 
12264 /*!
12265  * \internal
12266  * \brief Initialize/create a channel interface.
12267  *
12268  * \param channel Channel interface number to initialize/create.
12269  * \param conf Configuration parameters to initialize interface with.
12270  * \param reloading What we are doing now:
12271  * 0 - initial module load,
12272  * 1 - module reload,
12273  * 2 - module restart
12274  *
12275  * \retval Interface-pointer initialized/created
12276  * \retval NULL if error
12277  */
12278 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12279 {
12280    /* Make a dahdi_pvt structure for this interface */
12281    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12282    char fn[80];
12283    struct dahdi_bufferinfo bi;
12284 
12285    int res;
12286 #if defined(HAVE_PRI)
12287    int span = 0;
12288 #endif   /* defined(HAVE_PRI) */
12289    int here = 0;/*!< TRUE if the channel interface already exists. */
12290    int x;
12291    struct analog_pvt *analog_p = NULL;
12292    struct dahdi_params p;
12293 #if defined(HAVE_PRI)
12294    struct dahdi_spaninfo si;
12295    struct sig_pri_chan *pri_chan = NULL;
12296 #endif   /* defined(HAVE_PRI) */
12297 #if defined(HAVE_SS7)
12298    struct sig_ss7_chan *ss7_chan = NULL;
12299 #endif   /* defined(HAVE_SS7) */
12300 
12301    /* Search channel interface list to see if it already exists. */
12302    for (tmp = iflist; tmp; tmp = tmp->next) {
12303       if (!tmp->destroy) {
12304          if (tmp->channel == channel) {
12305             /* The channel interface already exists. */
12306             here = 1;
12307             break;
12308          }
12309          if (tmp->channel > channel) {
12310             /* No way it can be in the sorted list. */
12311             tmp = NULL;
12312             break;
12313          }
12314       }
12315    }
12316 
12317    if (!here && reloading != 1) {
12318       tmp = ast_calloc(1, sizeof(*tmp));
12319       if (!tmp) {
12320          return NULL;
12321       }
12322       tmp->cc_params = ast_cc_config_params_init();
12323       if (!tmp->cc_params) {
12324          ast_free(tmp);
12325          return NULL;
12326       }
12327       ast_mutex_init(&tmp->lock);
12328       ifcount++;
12329       for (x = 0; x < 3; x++)
12330          tmp->subs[x].dfd = -1;
12331       tmp->channel = channel;
12332       tmp->priindication_oob = conf->chan.priindication_oob;
12333    }
12334 
12335    if (tmp) {
12336       int chan_sig = conf->chan.sig;
12337 
12338       /* If there are variables in tmp before it is updated to match the new config, clear them */
12339       if (reloading && tmp->vars) {
12340          ast_variables_destroy(tmp->vars);
12341          tmp->vars = NULL;
12342       }
12343 
12344 
12345       if (!here) {
12346          /* Can only get here if this is a new channel interface being created. */
12347          if ((channel != CHAN_PSEUDO)) {
12348             int count = 0;
12349 
12350             snprintf(fn, sizeof(fn), "%d", channel);
12351             /* Open non-blocking */
12352             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12353             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 */
12354                usleep(1);
12355                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12356                count++;
12357             }
12358             /* Allocate a DAHDI structure */
12359             if (tmp->subs[SUB_REAL].dfd < 0) {
12360                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);
12361                destroy_dahdi_pvt(tmp);
12362                return NULL;
12363             }
12364             memset(&p, 0, sizeof(p));
12365             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12366             if (res < 0) {
12367                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12368                destroy_dahdi_pvt(tmp);
12369                return NULL;
12370             }
12371             if (conf->is_sig_auto)
12372                chan_sig = sigtype_to_signalling(p.sigtype);
12373             if (p.sigtype != (chan_sig & 0x3ffff)) {
12374                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));
12375                destroy_dahdi_pvt(tmp);
12376                return NULL;
12377             }
12378             tmp->law_default = p.curlaw;
12379             tmp->law = p.curlaw;
12380             tmp->span = p.spanno;
12381 #if defined(HAVE_PRI)
12382             span = p.spanno - 1;
12383 #endif   /* defined(HAVE_PRI) */
12384          } else {
12385             chan_sig = 0;
12386          }
12387          tmp->sig = chan_sig;
12388          tmp->outsigmod = conf->chan.outsigmod;
12389 
12390          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12391             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12392             if (!analog_p) {
12393                destroy_dahdi_pvt(tmp);
12394                return NULL;
12395             }
12396             tmp->sig_pvt = analog_p;
12397          }
12398 #if defined(HAVE_SS7)
12399          if (chan_sig == SIG_SS7) {
12400             struct dahdi_ss7 *ss7;
12401             int clear = 0;
12402 
12403             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12404                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12405                destroy_dahdi_pvt(tmp);
12406                return NULL;
12407             }
12408 
12409             ss7 = ss7_resolve_linkset(cur_linkset);
12410             if (!ss7) {
12411                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12412                destroy_dahdi_pvt(tmp);
12413                return NULL;
12414             }
12415             ss7->ss7.span = cur_linkset;
12416             if (cur_cicbeginswith < 0) {
12417                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12418                destroy_dahdi_pvt(tmp);
12419                return NULL;
12420             }
12421             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12422             if (!ss7_chan) {
12423                destroy_dahdi_pvt(tmp);
12424                return NULL;
12425             }
12426             tmp->sig_pvt = ss7_chan;
12427             tmp->ss7 = &ss7->ss7;
12428 
12429             ss7_chan->channel = tmp->channel;
12430             ss7_chan->cic = cur_cicbeginswith++;
12431 
12432             /* DB: Add CIC's DPC information */
12433             ss7_chan->dpc = cur_defaultdpc;
12434 
12435             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12436 
12437             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12438             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12439             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12440             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12441 
12442             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12443             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12444          }
12445 #endif   /* defined(HAVE_SS7) */
12446 #ifdef HAVE_OPENR2
12447          if (chan_sig == SIG_MFCR2) {
12448             struct dahdi_mfcr2 *r2_link;
12449             r2_link = dahdi_r2_get_link();
12450             if (!r2_link) {
12451                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12452                destroy_dahdi_pvt(tmp);
12453                return NULL;
12454             }
12455             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12456                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12457                destroy_dahdi_pvt(tmp);
12458                return NULL;
12459             }
12460             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12461                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12462                destroy_dahdi_pvt(tmp);
12463                return NULL;
12464             }
12465             r2_link->pvts[r2_link->numchans++] = tmp;
12466             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12467                                         tmp->subs[SUB_REAL].dfd,
12468                                         NULL, NULL);
12469             if (!tmp->r2chan) {
12470                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12471                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12472                destroy_dahdi_pvt(tmp);
12473                return NULL;
12474             }
12475             tmp->mfcr2 = r2_link;
12476             if (conf->mfcr2.call_files) {
12477                openr2_chan_enable_call_files(tmp->r2chan);
12478             }
12479             openr2_chan_set_client_data(tmp->r2chan, tmp);
12480             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12481             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12482             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12483             tmp->mfcr2_category = conf->mfcr2.category;
12484             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12485             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12486             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12487             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12488             tmp->mfcr2call = 0;
12489             tmp->mfcr2_dnis_index = 0;
12490             tmp->mfcr2_ani_index = 0;
12491             r2_link->monitored_count++;
12492          }
12493 #endif
12494 #ifdef HAVE_PRI
12495          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12496             int offset;
12497             int matchesdchan;
12498             int x,y;
12499             int myswitchtype = 0;
12500 
12501             offset = 0;
12502             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12503                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12504                destroy_dahdi_pvt(tmp);
12505                return NULL;
12506             }
12507             if (span >= NUM_SPANS) {
12508                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12509                destroy_dahdi_pvt(tmp);
12510                return NULL;
12511             } else {
12512                si.spanno = 0;
12513                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12514                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12515                   destroy_dahdi_pvt(tmp);
12516                   return NULL;
12517                }
12518                /* Store the logical span first based upon the real span */
12519                tmp->logicalspan = pris[span].prilogicalspan;
12520                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12521                if (span < 0) {
12522                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12523                   destroy_dahdi_pvt(tmp);
12524                   return NULL;
12525                }
12526                myswitchtype = conf->pri.pri.switchtype;
12527                /* Make sure this isn't a d-channel */
12528                matchesdchan=0;
12529                for (x = 0; x < NUM_SPANS; x++) {
12530                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12531                      if (pris[x].dchannels[y] == tmp->channel) {
12532                         matchesdchan = 1;
12533                         break;
12534                      }
12535                   }
12536                }
12537                if (!matchesdchan) {
12538                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12539                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12540                      destroy_dahdi_pvt(tmp);
12541                      return NULL;
12542                   }
12543                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12544                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12545                      destroy_dahdi_pvt(tmp);
12546                      return NULL;
12547                   }
12548                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12549                      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));
12550                      destroy_dahdi_pvt(tmp);
12551                      return NULL;
12552                   }
12553                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12554                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12555                      destroy_dahdi_pvt(tmp);
12556                      return NULL;
12557                   }
12558                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12559                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12560                      destroy_dahdi_pvt(tmp);
12561                      return NULL;
12562                   }
12563                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12564                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12565                      destroy_dahdi_pvt(tmp);
12566                      return NULL;
12567                   }
12568                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12569                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12570                      destroy_dahdi_pvt(tmp);
12571                      return NULL;
12572                   }
12573                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12574                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12575                         pris[span].pri.trunkgroup);
12576                      destroy_dahdi_pvt(tmp);
12577                      return NULL;
12578                   }
12579 
12580                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12581                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12582                   if (!pri_chan) {
12583                      destroy_dahdi_pvt(tmp);
12584                      return NULL;
12585                   }
12586                   tmp->sig_pvt = pri_chan;
12587                   tmp->pri = &pris[span].pri;
12588 
12589                   tmp->priexclusive = conf->chan.priexclusive;
12590 
12591                   if (!tmp->pri->cc_params) {
12592                      tmp->pri->cc_params = ast_cc_config_params_init();
12593                      if (!tmp->pri->cc_params) {
12594                         destroy_dahdi_pvt(tmp);
12595                         return NULL;
12596                      }
12597                   }
12598                   ast_cc_copy_config_params(tmp->pri->cc_params,
12599                      conf->chan.cc_params);
12600 
12601                   pris[span].pri.sig = chan_sig;
12602                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12603                   pris[span].pri.switchtype = myswitchtype;
12604                   pris[span].pri.nsf = conf->pri.pri.nsf;
12605                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12606                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12607                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12608                   pris[span].pri.minunused = conf->pri.pri.minunused;
12609                   pris[span].pri.minidle = conf->pri.pri.minidle;
12610                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12611                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12612                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12613 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12614                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12615 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12616 #ifdef HAVE_PRI_INBANDDISCONNECT
12617                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12618 #endif
12619 #if defined(HAVE_PRI_CALL_HOLD)
12620                   pris[span].pri.hold_disconnect_transfer =
12621                      conf->pri.pri.hold_disconnect_transfer;
12622 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12623 #if defined(HAVE_PRI_CCSS)
12624                   pris[span].pri.cc_ptmp_recall_mode =
12625                      conf->pri.pri.cc_ptmp_recall_mode;
12626                   pris[span].pri.cc_qsig_signaling_link_req =
12627                      conf->pri.pri.cc_qsig_signaling_link_req;
12628                   pris[span].pri.cc_qsig_signaling_link_rsp =
12629                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12630 #endif   /* defined(HAVE_PRI_CCSS) */
12631 #if defined(HAVE_PRI_CALL_WAITING)
12632                   pris[span].pri.max_call_waiting_calls =
12633                      conf->pri.pri.max_call_waiting_calls;
12634                   pris[span].pri.allow_call_waiting_calls =
12635                      conf->pri.pri.allow_call_waiting_calls;
12636 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12637                   pris[span].pri.transfer = conf->chan.transfer;
12638                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12639 #if defined(HAVE_PRI_L2_PERSISTENCE)
12640                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12641 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12642 #if defined(HAVE_PRI_AOC_EVENTS)
12643                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12644                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12645 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12646                   if (chan_sig == SIG_BRI_PTMP) {
12647                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12648                   } else {
12649                      /* Option does not apply to this line type. */
12650                      pris[span].pri.layer1_ignored = 0;
12651                   }
12652                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12653                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12654                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12655 #if defined(HAVE_PRI_MWI)
12656                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12657                      conf->pri.pri.mwi_mailboxes,
12658                      sizeof(pris[span].pri.mwi_mailboxes));
12659 #endif   /* defined(HAVE_PRI_MWI) */
12660                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12661                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12662                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12663                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12664                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12665                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12666                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12667                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12668 
12669                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12670                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12671                   }
12672 
12673 #if defined(HAVE_PRI_CALL_WAITING)
12674                   /* Channel initial config parameters. */
12675                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12676                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12677                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12678                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12679                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12680                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12681                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12682                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12683                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12684                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12685 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12686                } else {
12687                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12688                   destroy_dahdi_pvt(tmp);
12689                   return NULL;
12690                }
12691             }
12692          }
12693 #endif
12694       } else {
12695          /* already exists in interface list */
12696          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));
12697          chan_sig = tmp->sig;
12698          if (tmp->subs[SUB_REAL].dfd > -1) {
12699             memset(&p, 0, sizeof(p));
12700             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12701          }
12702       }
12703       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12704       switch (chan_sig) {
12705       case SIG_FXSKS:
12706       case SIG_FXSLS:
12707       case SIG_EM:
12708       case SIG_EM_E1:
12709       case SIG_EMWINK:
12710       case SIG_FEATD:
12711       case SIG_FEATDMF:
12712       case SIG_FEATDMF_TA:
12713       case SIG_FEATB:
12714       case SIG_E911:
12715       case SIG_SF:
12716       case SIG_SFWINK:
12717       case SIG_FGC_CAMA:
12718       case SIG_FGC_CAMAMF:
12719       case SIG_SF_FEATD:
12720       case SIG_SF_FEATDMF:
12721       case SIG_SF_FEATB:
12722          p.starttime = 250;
12723          break;
12724       }
12725 
12726       if (tmp->radio) {
12727          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12728          p.channo = channel;
12729          p.rxwinktime = 1;
12730          p.rxflashtime = 1;
12731          p.starttime = 1;
12732          p.debouncetime = 5;
12733       } else {
12734          p.channo = channel;
12735          /* Override timing settings based on config file */
12736          if (conf->timing.prewinktime >= 0)
12737             p.prewinktime = conf->timing.prewinktime;
12738          if (conf->timing.preflashtime >= 0)
12739             p.preflashtime = conf->timing.preflashtime;
12740          if (conf->timing.winktime >= 0)
12741             p.winktime = conf->timing.winktime;
12742          if (conf->timing.flashtime >= 0)
12743             p.flashtime = conf->timing.flashtime;
12744          if (conf->timing.starttime >= 0)
12745             p.starttime = conf->timing.starttime;
12746          if (conf->timing.rxwinktime >= 0)
12747             p.rxwinktime = conf->timing.rxwinktime;
12748          if (conf->timing.rxflashtime >= 0)
12749             p.rxflashtime = conf->timing.rxflashtime;
12750          if (conf->timing.debouncetime >= 0)
12751             p.debouncetime = conf->timing.debouncetime;
12752       }
12753 
12754       /* don't set parms on a pseudo-channel */
12755       if (tmp->subs[SUB_REAL].dfd >= 0)
12756       {
12757          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12758          if (res < 0) {
12759             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12760             destroy_dahdi_pvt(tmp);
12761             return NULL;
12762          }
12763       }
12764 #if 1
12765       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12766          memset(&bi, 0, sizeof(bi));
12767          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12768          if (!res) {
12769             bi.txbufpolicy = conf->chan.buf_policy;
12770             bi.rxbufpolicy = conf->chan.buf_policy;
12771             bi.numbufs = conf->chan.buf_no;
12772             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12773             if (res < 0) {
12774                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12775             }
12776          } else {
12777             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12778          }
12779          tmp->buf_policy = conf->chan.buf_policy;
12780          tmp->buf_no = conf->chan.buf_no;
12781          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12782          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12783          tmp->faxbuf_no = conf->chan.faxbuf_no;
12784          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12785           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12786           * The reason the ioctl call above failed should to be determined before worrying about the
12787           * faxbuffer-related ioctl calls */
12788          tmp->bufsize = bi.bufsize;
12789       }
12790 #endif
12791       tmp->immediate = conf->chan.immediate;
12792       tmp->transfertobusy = conf->chan.transfertobusy;
12793       if (chan_sig & __DAHDI_SIG_FXS) {
12794          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12795          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12796          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12797       }
12798       tmp->ringt_base = ringt_base;
12799       tmp->firstradio = 0;
12800       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12801          tmp->permcallwaiting = conf->chan.callwaiting;
12802       else
12803          tmp->permcallwaiting = 0;
12804       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12805       tmp->destroy = 0;
12806       tmp->drings = conf->chan.drings;
12807 
12808       /* 10 is a nice default. */
12809       if (tmp->drings.ringnum[0].range == 0)
12810          tmp->drings.ringnum[0].range = 10;
12811       if (tmp->drings.ringnum[1].range == 0)
12812          tmp->drings.ringnum[1].range = 10;
12813       if (tmp->drings.ringnum[2].range == 0)
12814          tmp->drings.ringnum[2].range = 10;
12815 
12816       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12817       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12818       tmp->threewaycalling = conf->chan.threewaycalling;
12819       tmp->adsi = conf->chan.adsi;
12820       tmp->use_smdi = conf->chan.use_smdi;
12821       tmp->permhidecallerid = conf->chan.hidecallerid;
12822       tmp->hidecalleridname = conf->chan.hidecalleridname;
12823       tmp->callreturn = conf->chan.callreturn;
12824       tmp->echocancel = conf->chan.echocancel;
12825       tmp->echotraining = conf->chan.echotraining;
12826       tmp->pulse = conf->chan.pulse;
12827       if (tmp->echocancel.head.tap_length) {
12828          tmp->echocanbridged = conf->chan.echocanbridged;
12829       } else {
12830          if (conf->chan.echocanbridged)
12831             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12832          tmp->echocanbridged = 0;
12833       }
12834       tmp->busydetect = conf->chan.busydetect;
12835       tmp->busycount = conf->chan.busycount;
12836       tmp->busy_tonelength = conf->chan.busy_tonelength;
12837       tmp->busy_quietlength = conf->chan.busy_quietlength;
12838       tmp->callprogress = conf->chan.callprogress;
12839       tmp->waitfordialtone = conf->chan.waitfordialtone;
12840       tmp->cancallforward = conf->chan.cancallforward;
12841       tmp->dtmfrelax = conf->chan.dtmfrelax;
12842       tmp->callwaiting = tmp->permcallwaiting;
12843       tmp->hidecallerid = tmp->permhidecallerid;
12844       tmp->channel = channel;
12845       tmp->stripmsd = conf->chan.stripmsd;
12846       tmp->use_callerid = conf->chan.use_callerid;
12847       tmp->cid_signalling = conf->chan.cid_signalling;
12848       tmp->cid_start = conf->chan.cid_start;
12849       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12850       tmp->restrictcid = conf->chan.restrictcid;
12851       tmp->use_callingpres = conf->chan.use_callingpres;
12852       if (tmp->usedistinctiveringdetection) {
12853          if (!tmp->use_callerid) {
12854             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12855             tmp->use_callerid = 1;
12856          }
12857       }
12858 
12859       if (tmp->cid_signalling == CID_SIG_SMDI) {
12860          if (!tmp->use_smdi) {
12861             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12862             tmp->use_smdi = 1;
12863          }
12864       }
12865       if (tmp->use_smdi) {
12866          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12867          if (!(tmp->smdi_iface)) {
12868             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12869             tmp->use_smdi = 0;
12870          }
12871       }
12872 
12873       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12874       tmp->amaflags = conf->chan.amaflags;
12875       if (!here) {
12876          tmp->confno = -1;
12877          tmp->propconfno = -1;
12878       }
12879       tmp->canpark = conf->chan.canpark;
12880       tmp->transfer = conf->chan.transfer;
12881       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12882       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12883       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12884       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12885       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12886       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12887       tmp->cid_ton = 0;
12888       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12889          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12890          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12891       } else {
12892          tmp->cid_num[0] = '\0';
12893          tmp->cid_name[0] = '\0';
12894       }
12895 #if defined(HAVE_PRI)
12896       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12897          tmp->cid_tag[0] = '\0';
12898       } else
12899 #endif   /* defined(HAVE_PRI) */
12900       {
12901          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12902       }
12903       tmp->cid_subaddr[0] = '\0';
12904       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12905       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12906          char *mailbox, *context;
12907          mailbox = context = ast_strdupa(tmp->mailbox);
12908          strsep(&context, "@");
12909          if (ast_strlen_zero(context))
12910             context = "default";
12911          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12912             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12913             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12914             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12915             AST_EVENT_IE_END);
12916       }
12917 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12918       tmp->mwisend_setting = conf->chan.mwisend_setting;
12919       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12920       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12921 #endif
12922 
12923       tmp->group = conf->chan.group;
12924       tmp->callgroup = conf->chan.callgroup;
12925       tmp->pickupgroup= conf->chan.pickupgroup;
12926       if (conf->chan.vars) {
12927          struct ast_variable *v, *tmpvar;
12928                    for (v = conf->chan.vars ; v ; v = v->next) {
12929                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12930                                   tmpvar->next = tmp->vars;
12931                                    tmp->vars = tmpvar;
12932                            }
12933                   }
12934       }
12935       tmp->cid_rxgain = conf->chan.cid_rxgain;
12936       tmp->rxgain = conf->chan.rxgain;
12937       tmp->txgain = conf->chan.txgain;
12938       tmp->txdrc = conf->chan.txdrc;
12939       tmp->rxdrc = conf->chan.rxdrc;
12940       tmp->tonezone = conf->chan.tonezone;
12941       if (tmp->subs[SUB_REAL].dfd > -1) {
12942          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12943          if (tmp->dsp)
12944             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12945          update_conf(tmp);
12946          if (!here) {
12947             switch (chan_sig) {
12948             case SIG_PRI_LIB_HANDLE_CASES:
12949             case SIG_SS7:
12950             case SIG_MFCR2:
12951                break;
12952             default:
12953                /* Hang it up to be sure it's good */
12954                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12955                break;
12956             }
12957          }
12958          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12959          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12960             /* the dchannel is down so put the channel in alarm */
12961             switch (tmp->sig) {
12962 #ifdef HAVE_PRI
12963             case SIG_PRI_LIB_HANDLE_CASES:
12964                sig_pri_set_alarm(tmp->sig_pvt, 1);
12965                break;
12966 #endif
12967 #if defined(HAVE_SS7)
12968             case SIG_SS7:
12969                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12970                break;
12971 #endif   /* defined(HAVE_SS7) */
12972             default:
12973                /* The only sig submodule left should be sig_analog. */
12974                analog_p = tmp->sig_pvt;
12975                if (analog_p) {
12976                   analog_p->inalarm = 1;
12977                }
12978                tmp->inalarm = 1;
12979                break;
12980             }
12981             handle_alarms(tmp, res);
12982          }
12983       }
12984 
12985       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12986       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12987       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12988       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12989       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12990 
12991       if (!here) {
12992          tmp->locallyblocked = 0;
12993          tmp->remotelyblocked = 0;
12994          switch (tmp->sig) {
12995 #if defined(HAVE_PRI)
12996          case SIG_PRI_LIB_HANDLE_CASES:
12997             tmp->inservice = 1;/* Inservice until actually implemented. */
12998 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12999             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13000             if (chan_sig == SIG_PRI) {
13001                char db_chan_name[20];
13002                char db_answer[5];
13003 
13004                /*
13005                 * Initialize the active out-of-service status
13006                 * and delete any record if the feature is not enabled.
13007                 */
13008                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13009                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13010                   unsigned *why;
13011 
13012                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13013                   if (tmp->pri->enable_service_message_support) {
13014                      char state;
13015 
13016                      sscanf(db_answer, "%1c:%30u", &state, why);
13017 
13018                      /* Ensure that only the implemented bits could be set.*/
13019                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13020                   }
13021                   if (!*why) {
13022                      ast_db_del(db_chan_name, SRVST_DBKEY);
13023                   }
13024                }
13025             }
13026 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13027             break;
13028 #endif   /* defined(HAVE_PRI) */
13029 #if defined(HAVE_SS7)
13030          case SIG_SS7:
13031             tmp->inservice = 0;
13032             break;
13033 #endif   /* defined(HAVE_SS7) */
13034          default:
13035              /* We default to in service on protocols that don't have a reset */
13036             tmp->inservice = 1;
13037             break;
13038          }
13039       }
13040 
13041       switch (tmp->sig) {
13042 #if defined(HAVE_PRI)
13043       case SIG_PRI_LIB_HANDLE_CASES:
13044          if (pri_chan) {
13045             pri_chan->channel = tmp->channel;
13046             pri_chan->hidecallerid = tmp->hidecallerid;
13047             pri_chan->hidecalleridname = tmp->hidecalleridname;
13048             pri_chan->immediate = tmp->immediate;
13049             pri_chan->inalarm = tmp->inalarm;
13050             pri_chan->priexclusive = tmp->priexclusive;
13051             pri_chan->priindication_oob = tmp->priindication_oob;
13052             pri_chan->use_callerid = tmp->use_callerid;
13053             pri_chan->use_callingpres = tmp->use_callingpres;
13054             ast_copy_string(pri_chan->context, tmp->context,
13055                sizeof(pri_chan->context));
13056             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13057                sizeof(pri_chan->mohinterpret));
13058             pri_chan->stripmsd = tmp->stripmsd;
13059          }
13060          break;
13061 #endif   /* defined(HAVE_PRI) */
13062 #if defined(HAVE_SS7)
13063       case SIG_SS7:
13064          if (ss7_chan) {
13065             ss7_chan->inalarm = tmp->inalarm;
13066 
13067             ss7_chan->stripmsd = tmp->stripmsd;
13068             ss7_chan->hidecallerid = tmp->hidecallerid;
13069             ss7_chan->use_callerid = tmp->use_callerid;
13070             ss7_chan->use_callingpres = tmp->use_callingpres;
13071             ss7_chan->immediate = tmp->immediate;
13072             ss7_chan->locallyblocked = tmp->locallyblocked;
13073             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13074             ast_copy_string(ss7_chan->context, tmp->context,
13075                sizeof(ss7_chan->context));
13076             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13077                sizeof(ss7_chan->mohinterpret));
13078          }
13079          break;
13080 #endif   /* defined(HAVE_SS7) */
13081       default:
13082          /* The only sig submodule left should be sig_analog. */
13083          analog_p = tmp->sig_pvt;
13084          if (analog_p) {
13085             analog_p->channel = tmp->channel;
13086             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13087             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13088             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13089             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13090             analog_p->callreturn = conf->chan.callreturn;
13091             analog_p->cancallforward = conf->chan.cancallforward;
13092             analog_p->canpark = conf->chan.canpark;
13093             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13094             analog_p->immediate = conf->chan.immediate;
13095             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13096             analog_p->pulse = conf->chan.pulse;
13097             analog_p->threewaycalling = conf->chan.threewaycalling;
13098             analog_p->transfer = conf->chan.transfer;
13099             analog_p->transfertobusy = conf->chan.transfertobusy;
13100             analog_p->use_callerid = tmp->use_callerid;
13101             analog_p->use_smdi = tmp->use_smdi;
13102             analog_p->smdi_iface = tmp->smdi_iface;
13103             analog_p->outsigmod = ANALOG_SIG_NONE;
13104             analog_p->echotraining = conf->chan.echotraining;
13105             analog_p->cid_signalling = conf->chan.cid_signalling;
13106             analog_p->stripmsd = conf->chan.stripmsd;
13107             switch (conf->chan.cid_start) {
13108             case CID_START_POLARITY:
13109                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13110                break;
13111             case CID_START_POLARITY_IN:
13112                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13113                break;
13114             case CID_START_DTMF_NOALERT:
13115                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13116                break;
13117             default:
13118                analog_p->cid_start = ANALOG_CID_START_RING;
13119                break;
13120             }
13121             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13122             analog_p->ringt = conf->chan.ringt;
13123             analog_p->ringt_base = ringt_base;
13124             analog_p->onhooktime = time(NULL);
13125             if (chan_sig & __DAHDI_SIG_FXO) {
13126                memset(&p, 0, sizeof(p));
13127                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13128                if (!res) {
13129                   analog_p->fxsoffhookstate = p.rxisoffhook;
13130                }
13131 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13132                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13133 #endif
13134             }
13135             analog_p->msgstate = -1;
13136 
13137             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13138             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13139             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13140 
13141             analog_config_complete(analog_p);
13142          }
13143          break;
13144       }
13145 #if defined(HAVE_PRI)
13146       if (tmp->channel == CHAN_PSEUDO) {
13147          /*
13148           * Save off pseudo channel buffer policy values for dynamic creation of
13149           * no B channel interfaces.
13150           */
13151          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13152          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13153          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13154          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13155       }
13156 #endif   /* defined(HAVE_PRI) */
13157    }
13158    if (tmp && !here) {
13159       /* Add the new channel interface to the sorted channel interface list. */
13160       dahdi_iflist_insert(tmp);
13161    }
13162    return tmp;
13163 }
13164 
13165 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13166 {
13167 #if defined(HAVE_PRI)
13168    if (0 < span) {
13169       /* The channel must be on the specified PRI span. */
13170       if (!p->pri || p->pri->span != span) {
13171          return 0;
13172       }
13173       if (!groupmatch && channelmatch == -1) {
13174          /* Match any group since it only needs to be on the PRI span. */
13175          *groupmatched = 1;
13176          return 1;
13177       }
13178    }
13179 #endif   /* defined(HAVE_PRI) */
13180    /* check group matching */
13181    if (groupmatch) {
13182       if ((p->group & groupmatch) != groupmatch)
13183          /* Doesn't match the specified group, try the next one */
13184          return 0;
13185       *groupmatched = 1;
13186    }
13187    /* Check to see if we have a channel match */
13188    if (channelmatch != -1) {
13189       if (p->channel != channelmatch)
13190          /* Doesn't match the specified channel, try the next one */
13191          return 0;
13192       *channelmatched = 1;
13193    }
13194 
13195    return 1;
13196 }
13197 
13198 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13199 {
13200    struct dahdi_pvt *p = *pvt;
13201 
13202    if (p->inalarm)
13203       return 0;
13204 
13205    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13206       return analog_available(p->sig_pvt);
13207 
13208    switch (p->sig) {
13209 #if defined(HAVE_PRI)
13210    case SIG_PRI_LIB_HANDLE_CASES:
13211       {
13212          struct sig_pri_chan *pvt_chan;
13213          int res;
13214 
13215          pvt_chan = p->sig_pvt;
13216          res = sig_pri_available(&pvt_chan, is_specific_channel);
13217          *pvt = pvt_chan->chan_pvt;
13218          return res;
13219       }
13220 #endif   /* defined(HAVE_PRI) */
13221 #if defined(HAVE_SS7)
13222    case SIG_SS7:
13223       return sig_ss7_available(p->sig_pvt);
13224 #endif   /* defined(HAVE_SS7) */
13225    default:
13226       break;
13227    }
13228 
13229    if (p->locallyblocked || p->remotelyblocked) {
13230       return 0;
13231    }
13232 
13233    /* If no owner definitely available */
13234    if (!p->owner) {
13235 #ifdef HAVE_OPENR2
13236       /* Trust MFC/R2 */
13237       if (p->mfcr2) {
13238          if (p->mfcr2call) {
13239             return 0;
13240          } else {
13241             return 1;
13242          }
13243       }
13244 #endif
13245       return 1;
13246    }
13247 
13248    return 0;
13249 }
13250 
13251 #if defined(HAVE_PRI)
13252 #if defined(HAVE_PRI_CALL_WAITING)
13253 /*!
13254  * \internal
13255  * \brief Init the private channel configuration using the span controller.
13256  * \since 1.8
13257  *
13258  * \param priv Channel to init the configuration.
13259  * \param pri sig_pri PRI control structure.
13260  *
13261  * \note Assumes the pri->lock is already obtained.
13262  *
13263  * \return Nothing
13264  */
13265 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13266 {
13267    struct dahdi_pvt *pvt = priv;
13268 
13269    pvt->stripmsd = pri->ch_cfg.stripmsd;
13270    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13271    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13272    pvt->immediate = pri->ch_cfg.immediate;
13273    pvt->priexclusive = pri->ch_cfg.priexclusive;
13274    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13275    pvt->use_callerid = pri->ch_cfg.use_callerid;
13276    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13277    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13278    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13279 }
13280 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13281 #endif   /* defined(HAVE_PRI) */
13282 
13283 #if defined(HAVE_PRI)
13284 /*!
13285  * \internal
13286  * \brief Create a no B channel interface.
13287  * \since 1.8
13288  *
13289  * \param pri sig_pri span controller to add interface.
13290  *
13291  * \note Assumes the pri->lock is already obtained.
13292  *
13293  * \retval array-index into private pointer array on success.
13294  * \retval -1 on error.
13295  */
13296 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13297 {
13298    int pvt_idx;
13299    int res;
13300    unsigned idx;
13301    struct dahdi_pvt *pvt;
13302    struct sig_pri_chan *chan;
13303    struct dahdi_bufferinfo bi;
13304 
13305    static int nobch_channel = CHAN_PSEUDO;
13306 
13307    /* Find spot in the private pointer array for new interface. */
13308    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13309       if (!pri->pvts[pvt_idx]) {
13310          break;
13311       }
13312    }
13313    if (pri->numchans == pvt_idx) {
13314       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13315          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13316          return -1;
13317       }
13318 
13319       /* Add new spot to the private pointer array. */
13320       pri->pvts[pvt_idx] = NULL;
13321       ++pri->numchans;
13322    }
13323 
13324    pvt = ast_calloc(1, sizeof(*pvt));
13325    if (!pvt) {
13326       return -1;
13327    }
13328    pvt->cc_params = ast_cc_config_params_init();
13329    if (!pvt->cc_params) {
13330       ast_free(pvt);
13331       return -1;
13332    }
13333    ast_mutex_init(&pvt->lock);
13334    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13335       pvt->subs[idx].dfd = -1;
13336    }
13337    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13338    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13339    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13340    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13341 
13342    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13343    if (!chan) {
13344       destroy_dahdi_pvt(pvt);
13345       return -1;
13346    }
13347    chan->no_b_channel = 1;
13348 
13349    /*
13350     * Pseudo channel companding law.
13351     * Needed for outgoing call waiting calls.
13352     * XXX May need to make this determined by switchtype or user option.
13353     */
13354    pvt->law_default = DAHDI_LAW_ALAW;
13355 
13356    pvt->sig = pri->sig;
13357    pvt->outsigmod = -1;
13358    pvt->pri = pri;
13359    pvt->sig_pvt = chan;
13360    pri->pvts[pvt_idx] = chan;
13361 
13362    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13363    if (pvt->subs[SUB_REAL].dfd < 0) {
13364       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13365          strerror(errno));
13366       destroy_dahdi_pvt(pvt);
13367       return -1;
13368    }
13369    memset(&bi, 0, sizeof(bi));
13370    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13371    if (!res) {
13372       pvt->bufsize = bi.bufsize;
13373       bi.txbufpolicy = pvt->buf_policy;
13374       bi.rxbufpolicy = pvt->buf_policy;
13375       bi.numbufs = pvt->buf_no;
13376       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13377       if (res < 0) {
13378          ast_log(LOG_WARNING,
13379             "Unable to set buffer policy on no B channel interface: %s\n",
13380             strerror(errno));
13381       }
13382    } else
13383       ast_log(LOG_WARNING,
13384          "Unable to check buffer policy on no B channel interface: %s\n",
13385          strerror(errno));
13386 
13387    --nobch_channel;
13388    if (CHAN_PSEUDO < nobch_channel) {
13389       nobch_channel = CHAN_PSEUDO - 1;
13390    }
13391    pvt->channel = nobch_channel;
13392    pvt->span = pri->span;
13393    chan->channel = pvt->channel;
13394 
13395    dahdi_nobch_insert(pri, pvt);
13396 
13397    return pvt_idx;
13398 }
13399 #endif   /* defined(HAVE_PRI) */
13400 
13401 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13402    structures; it makes no attempt to safely copy regular channel private
13403    structures that might contain reference-counted object pointers and other
13404    scary bits
13405 */
13406 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13407 {
13408    struct dahdi_pvt *p;
13409    struct dahdi_bufferinfo bi;
13410    int res;
13411 
13412    p = ast_malloc(sizeof(*p));
13413    if (!p) {
13414       return NULL;
13415    }
13416    *p = *src;
13417 
13418    /* Must deep copy the cc_params. */
13419    p->cc_params = ast_cc_config_params_init();
13420    if (!p->cc_params) {
13421       ast_free(p);
13422       return NULL;
13423    }
13424    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13425 
13426    p->which_iflist = DAHDI_IFLIST_NONE;
13427    p->next = NULL;
13428    p->prev = NULL;
13429    ast_mutex_init(&p->lock);
13430    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13431    if (p->subs[SUB_REAL].dfd < 0) {
13432       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13433       destroy_dahdi_pvt(p);
13434       return NULL;
13435    }
13436    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13437    if (!res) {
13438       bi.txbufpolicy = src->buf_policy;
13439       bi.rxbufpolicy = src->buf_policy;
13440       bi.numbufs = src->buf_no;
13441       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13442       if (res < 0) {
13443          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13444       }
13445    } else
13446       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13447    p->destroy = 1;
13448    dahdi_iflist_insert(p);
13449    return p;
13450 }
13451 
13452 struct dahdi_starting_point {
13453    /*! Group matching mask.  Zero if not specified. */
13454    ast_group_t groupmatch;
13455    /*! DAHDI channel to match with.  -1 if not specified. */
13456    int channelmatch;
13457    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13458    int rr_starting_point;
13459    /*! ISDN span where channels can be picked (Zero if not specified) */
13460    int span;
13461    /*! Analog channel distinctive ring cadance index. */
13462    int cadance;
13463    /*! Dialing option. c/r/d if present and valid. */
13464    char opt;
13465    /*! TRUE if to search the channel list backwards. */
13466    char backwards;
13467    /*! TRUE if search is done with round robin sequence. */
13468    char roundrobin;
13469 };
13470 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13471 {
13472    char *dest;
13473    char *s;
13474    int x;
13475    int res = 0;
13476    struct dahdi_pvt *p;
13477    char *subdir = NULL;
13478    AST_DECLARE_APP_ARGS(args,
13479       AST_APP_ARG(group);  /* channel/group token */
13480       //AST_APP_ARG(ext);  /* extension token */
13481       //AST_APP_ARG(opts); /* options token */
13482       AST_APP_ARG(other);  /* Any remining unused arguments */
13483    );
13484 
13485    /*
13486     * data is ---v
13487     * Dial(DAHDI/pseudo[/extension[/options]])
13488     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13489     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13490     * Dial(DAHDI/i<span>[/extension[/options]])
13491     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13492     *
13493     * i - ISDN span channel restriction.
13494     *     Used by CC to ensure that the CC recall goes out the same span.
13495     *     Also to make ISDN channel names dialable when the sequence number
13496     *     is stripped off.  (Used by DTMF attended transfer feature.)
13497     *
13498     * g - channel group allocation search forward
13499     * G - channel group allocation search backward
13500     * r - channel group allocation round robin search forward
13501     * R - channel group allocation round robin search backward
13502     *
13503     * c - Wait for DTMF digit to confirm answer
13504     * r<cadance#> - Set distintive ring cadance number
13505     * d - Force bearer capability for ISDN/SS7 call to digital.
13506     */
13507 
13508    if (data) {
13509       dest = ast_strdupa(data);
13510    } else {
13511       ast_log(LOG_WARNING, "Channel requested with no data\n");
13512       return NULL;
13513    }
13514    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13515    if (!args.argc || ast_strlen_zero(args.group)) {
13516       ast_log(LOG_WARNING, "No channel/group specified\n");
13517       return NULL;
13518    }
13519 
13520    /* Initialize the output parameters */
13521    memset(param, 0, sizeof(*param));
13522    param->channelmatch = -1;
13523 
13524    if (strchr(args.group, '!') != NULL) {
13525       char *prev = args.group;
13526       while ((s = strchr(prev, '!')) != NULL) {
13527          *s++ = '/';
13528          prev = s;
13529       }
13530       *(prev - 1) = '\0';
13531       subdir = args.group;
13532       args.group = prev;
13533    } else if (args.group[0] == 'i') {
13534       /* Extract the ISDN span channel restriction specifier. */
13535       res = sscanf(args.group + 1, "%30d", &x);
13536       if (res < 1) {
13537          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13538          return NULL;
13539       }
13540       param->span = x;
13541 
13542       /* Remove the ISDN span channel restriction specifier. */
13543       s = strchr(args.group, '-');
13544       if (!s) {
13545          /* Search all groups since we are ISDN span restricted. */
13546          return iflist;
13547       }
13548       args.group = s + 1;
13549       res = 0;
13550    }
13551    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13552       /* Retrieve the group number */
13553       s = args.group + 1;
13554       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13555       if (res < 1) {
13556          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13557          return NULL;
13558       }
13559       param->groupmatch = ((ast_group_t) 1 << x);
13560 
13561       if (toupper(args.group[0]) == 'G') {
13562          if (args.group[0] == 'G') {
13563             param->backwards = 1;
13564             p = ifend;
13565          } else
13566             p = iflist;
13567       } else {
13568          if (ARRAY_LEN(round_robin) <= x) {
13569             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13570                x, data);
13571             return NULL;
13572          }
13573          if (args.group[0] == 'R') {
13574             param->backwards = 1;
13575             p = round_robin[x] ? round_robin[x]->prev : ifend;
13576             if (!p)
13577                p = ifend;
13578          } else {
13579             p = round_robin[x] ? round_robin[x]->next : iflist;
13580             if (!p)
13581                p = iflist;
13582          }
13583          param->roundrobin = 1;
13584          param->rr_starting_point = x;
13585       }
13586    } else {
13587       s = args.group;
13588       if (!strcasecmp(s, "pseudo")) {
13589          /* Special case for pseudo */
13590          x = CHAN_PSEUDO;
13591          param->channelmatch = x;
13592       } else {
13593          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13594          if (res < 1) {
13595             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13596             return NULL;
13597          } else {
13598             param->channelmatch = x;
13599          }
13600       }
13601       if (subdir) {
13602          char path[PATH_MAX];
13603          struct stat stbuf;
13604 
13605          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13606                subdir, param->channelmatch);
13607          if (stat(path, &stbuf) < 0) {
13608             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13609                   path, strerror(errno));
13610             return NULL;
13611          }
13612          if (!S_ISCHR(stbuf.st_mode)) {
13613             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13614                   path);
13615             return NULL;
13616          }
13617          param->channelmatch = minor(stbuf.st_rdev);
13618       }
13619 
13620       p = iflist;
13621    }
13622 
13623    if (param->opt == 'r' && res < 3) {
13624       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13625       param->opt = '\0';
13626    }
13627 
13628    return p;
13629 }
13630 
13631 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13632 {
13633    int callwait = 0;
13634    struct dahdi_pvt *p;
13635    struct ast_channel *tmp = NULL;
13636    struct dahdi_pvt *exitpvt;
13637    int channelmatched = 0;
13638    int groupmatched = 0;
13639 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13640    int transcapdigital = 0;
13641 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13642    struct dahdi_starting_point start;
13643 
13644    ast_mutex_lock(&iflock);
13645    p = determine_starting_point(data, &start);
13646    if (!p) {
13647       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13648       ast_mutex_unlock(&iflock);
13649       return NULL;
13650    }
13651 
13652    /* Search for an unowned channel */
13653    exitpvt = p;
13654    while (p && !tmp) {
13655       if (start.roundrobin)
13656          round_robin[start.rr_starting_point] = p;
13657 
13658       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13659          && available(&p, channelmatched)) {
13660          ast_debug(1, "Using channel %d\n", p->channel);
13661 
13662          callwait = (p->owner != NULL);
13663 #ifdef HAVE_OPENR2
13664          if (p->mfcr2) {
13665             ast_mutex_lock(&p->lock);
13666             if (p->mfcr2call) {
13667                ast_mutex_unlock(&p->lock);
13668                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13669                goto next;
13670             }
13671             p->mfcr2call = 1;
13672             ast_mutex_unlock(&p->lock);
13673          }
13674 #endif
13675          if (p->channel == CHAN_PSEUDO) {
13676             p = duplicate_pseudo(p);
13677             if (!p) {
13678                break;
13679             }
13680          }
13681 
13682          p->distinctivering = 0;
13683          /* Make special notes */
13684          switch (start.opt) {
13685          case '\0':
13686             /* No option present. */
13687             break;
13688          case 'c':
13689             /* Confirm answer */
13690             p->confirmanswer = 1;
13691             break;
13692          case 'r':
13693             /* Distinctive ring */
13694             p->distinctivering = start.cadance;
13695             break;
13696          case 'd':
13697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13698             /* If this is an ISDN call, make it digital */
13699             transcapdigital = AST_TRANS_CAP_DIGITAL;
13700 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13701             break;
13702          default:
13703             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13704             break;
13705          }
13706 
13707          p->outgoing = 1;
13708          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13709             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13710 #ifdef HAVE_PRI
13711          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13712             /*
13713              * We already have the B channel reserved for this call.  We
13714              * just need to make sure that dahdi_hangup() has completed
13715              * cleaning up before continuing.
13716              */
13717             ast_mutex_lock(&p->lock);
13718             ast_mutex_unlock(&p->lock);
13719 
13720             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13721                sizeof(p->dnid));
13722             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13723 #endif
13724 #if defined(HAVE_SS7)
13725          } else if (p->sig == SIG_SS7) {
13726             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13727 #endif   /* defined(HAVE_SS7) */
13728          } else {
13729             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13730          }
13731          if (!tmp) {
13732             p->outgoing = 0;
13733 #if defined(HAVE_PRI)
13734             switch (p->sig) {
13735             case SIG_PRI_LIB_HANDLE_CASES:
13736 #if defined(HAVE_PRI_CALL_WAITING)
13737                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13738                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13739                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13740                }
13741 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13742                /*
13743                 * This should be the last thing to clear when we are done with
13744                 * the channel.
13745                 */
13746                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13747                break;
13748             default:
13749                break;
13750             }
13751 #endif   /* defined(HAVE_PRI) */
13752          } else {
13753             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13754          }
13755          break;
13756       }
13757 #ifdef HAVE_OPENR2
13758 next:
13759 #endif
13760       if (start.backwards) {
13761          p = p->prev;
13762          if (!p)
13763             p = ifend;
13764       } else {
13765          p = p->next;
13766          if (!p)
13767             p = iflist;
13768       }
13769       /* stop when you roll to the one that we started from */
13770       if (p == exitpvt)
13771          break;
13772    }
13773    ast_mutex_unlock(&iflock);
13774    restart_monitor();
13775    if (cause && !tmp) {
13776       if (callwait || channelmatched) {
13777          *cause = AST_CAUSE_BUSY;
13778       } else if (groupmatched) {
13779          *cause = AST_CAUSE_CONGESTION;
13780       } else {
13781          /*
13782           * We did not match any channel requested.
13783           * Dialplan error requesting non-existant channel?
13784           */
13785       }
13786    }
13787 
13788    return tmp;
13789 }
13790 
13791 /*!
13792  * \internal
13793  * \brief Determine the device state for a given DAHDI device if we can.
13794  * \since 1.8
13795  *
13796  * \param data DAHDI device name after "DAHDI/".
13797  *
13798  * \retval device_state enum ast_device_state value.
13799  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13800  */
13801 static int dahdi_devicestate(void *data)
13802 {
13803 #if defined(HAVE_PRI)
13804    char *device;
13805    unsigned span;
13806    int res;
13807 
13808    device = data;
13809 
13810    if (*device != 'I') {
13811       /* The request is not for an ISDN span device. */
13812       return AST_DEVICE_UNKNOWN;
13813    }
13814    res = sscanf(device, "I%30u", &span);
13815    if (res != 1 || !span || NUM_SPANS < span) {
13816       /* Bad format for ISDN span device name. */
13817       return AST_DEVICE_UNKNOWN;
13818    }
13819    device = strchr(device, '/');
13820    if (!device) {
13821       /* Bad format for ISDN span device name. */
13822       return AST_DEVICE_UNKNOWN;
13823    }
13824 
13825    /*
13826     * Since there are currently no other span devstate's defined,
13827     * it must be congestion.
13828     */
13829 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13830    ++device;
13831    if (!strcmp(device, "congestion"))
13832 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13833    {
13834       return pris[span - 1].pri.congestion_devstate;
13835    }
13836 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13837    else if (!strcmp(device, "threshold")) {
13838       return pris[span - 1].pri.threshold_devstate;
13839    }
13840    return AST_DEVICE_UNKNOWN;
13841 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13842 #else
13843    return AST_DEVICE_UNKNOWN;
13844 #endif   /* defined(HAVE_PRI) */
13845 }
13846 
13847 /*!
13848  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13849  * \since 1.8
13850  *
13851  * \param inbound Incoming asterisk channel.
13852  * \param dest Same dial string passed to dahdi_request().
13853  * \param callback Callback into CC core to announce a busy channel available for CC.
13854  *
13855  * \details
13856  * This callback acts like a forked dial with all prongs of the fork busy.
13857  * Essentially, for each channel that could have taken the call, indicate that
13858  * it is busy.
13859  *
13860  * \retval 0 on success.
13861  * \retval -1 on error.
13862  */
13863 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13864 {
13865    struct dahdi_pvt *p;
13866    struct dahdi_pvt *exitpvt;
13867    struct dahdi_starting_point start;
13868    int groupmatched = 0;
13869    int channelmatched = 0;
13870 
13871    ast_mutex_lock(&iflock);
13872    p = determine_starting_point(dest, &start);
13873    if (!p) {
13874       ast_mutex_unlock(&iflock);
13875       return -1;
13876    }
13877    exitpvt = p;
13878    for (;;) {
13879       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13880          /* We found a potential match. call the callback */
13881          struct ast_str *device_name;
13882          char *dash;
13883          const char *monitor_type;
13884          char dialstring[AST_CHANNEL_NAME];
13885          char full_device_name[AST_CHANNEL_NAME];
13886 
13887          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13888          case AST_CC_MONITOR_NEVER:
13889             break;
13890          case AST_CC_MONITOR_NATIVE:
13891          case AST_CC_MONITOR_ALWAYS:
13892          case AST_CC_MONITOR_GENERIC:
13893 #if defined(HAVE_PRI)
13894             if (dahdi_sig_pri_lib_handles(p->sig)) {
13895                /*
13896                 * ISDN is in a trunk busy condition so we need to monitor
13897                 * the span congestion device state.
13898                 */
13899                snprintf(full_device_name, sizeof(full_device_name),
13900                   "DAHDI/I%d/congestion", p->pri->span);
13901             } else
13902 #endif   /* defined(HAVE_PRI) */
13903             {
13904 #if defined(HAVE_PRI)
13905                device_name = create_channel_name(p, 1, "");
13906 #else
13907                device_name = create_channel_name(p);
13908 #endif   /* defined(HAVE_PRI) */
13909                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13910                   device_name ? ast_str_buffer(device_name) : "");
13911                ast_free(device_name);
13912                /*
13913                 * The portion after the '-' in the channel name is either a random
13914                 * number, a sequence number, or a subchannel number. None are
13915                 * necessary so strip them off.
13916                 */
13917                dash = strrchr(full_device_name, '-');
13918                if (dash) {
13919                   *dash = '\0';
13920                }
13921             }
13922             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13923 
13924             /*
13925              * Analog can only do generic monitoring.
13926              * ISDN is in a trunk busy condition and any "device" is going
13927              * to be busy until a B channel becomes available.  The generic
13928              * monitor can do this task.
13929              */
13930             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13931             callback(inbound,
13932 #if defined(HAVE_PRI)
13933                p->pri ? p->pri->cc_params : p->cc_params,
13934 #else
13935                p->cc_params,
13936 #endif   /* defined(HAVE_PRI) */
13937                monitor_type, full_device_name, dialstring, NULL);
13938             break;
13939          }
13940       }
13941       p = start.backwards ? p->prev : p->next;
13942       if (!p) {
13943          p = start.backwards ? ifend : iflist;
13944       }
13945       if (p == exitpvt) {
13946          break;
13947       }
13948    }
13949    ast_mutex_unlock(&iflock);
13950    return 0;
13951 }
13952 
13953 #if defined(HAVE_SS7)
13954 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13955 {
13956    int i;
13957 
13958    if (ss7) {
13959       for (i = 0; i < NUM_SPANS; i++) {
13960          if (linksets[i].ss7.ss7 == ss7) {
13961             ast_verbose("[%d] %s", i + 1, s);
13962             return;
13963          }
13964       }
13965    }
13966    ast_verbose("%s", s);
13967 }
13968 #endif   /* defined(HAVE_SS7) */
13969 
13970 #if defined(HAVE_SS7)
13971 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13972 {
13973    int i;
13974 
13975    if (ss7) {
13976       for (i = 0; i < NUM_SPANS; i++) {
13977          if (linksets[i].ss7.ss7 == ss7) {
13978             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13979             return;
13980          }
13981       }
13982    }
13983    ast_log(LOG_ERROR, "%s", s);
13984 }
13985 #endif   /* defined(HAVE_SS7) */
13986 
13987 #if defined(HAVE_OPENR2)
13988 static void *mfcr2_monitor(void *data)
13989 {
13990    struct dahdi_mfcr2 *mfcr2 = data;
13991    /* we should be using pthread_key_create
13992       and allocate pollers dynamically.
13993       I think do_monitor() could be leaking, since it
13994       could be cancelled at any time and is not
13995       using thread keys, why?, */
13996    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13997    int res = 0;
13998    int i = 0;
13999    int oldstate = 0;
14000    int quit_loop = 0;
14001    int maxsleep = 20;
14002    int was_idle = 0;
14003    int pollsize = 0;
14004    /* now that we're ready to get calls, unblock our side and
14005       get current line state */
14006    for (i = 0; i < mfcr2->numchans; i++) {
14007       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14008       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14009    }
14010    while (1) {
14011       /* we trust here that the mfcr2 channel list will not ever change once
14012          the module is loaded */
14013       pollsize = 0;
14014       for (i = 0; i < mfcr2->numchans; i++) {
14015          pollers[i].revents = 0;
14016          pollers[i].events = 0;
14017          if (mfcr2->pvts[i]->owner) {
14018             continue;
14019          }
14020          if (!mfcr2->pvts[i]->r2chan) {
14021             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14022             quit_loop = 1;
14023             break;
14024          }
14025          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14026          pollers[i].events = POLLIN | POLLPRI;
14027          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14028          pollsize++;
14029       }
14030       if (quit_loop) {
14031          break;
14032       }
14033       if (pollsize == 0) {
14034          if (!was_idle) {
14035             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14036             was_idle = 1;
14037          }
14038          poll(NULL, 0, maxsleep);
14039          continue;
14040       }
14041       was_idle = 0;
14042       /* probably poll() is a valid cancel point, lets just be on the safe side
14043          by calling pthread_testcancel */
14044       pthread_testcancel();
14045       res = poll(pollers, mfcr2->numchans, maxsleep);
14046       pthread_testcancel();
14047       if ((res < 0) && (errno != EINTR)) {
14048          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14049          break;
14050       }
14051       /* do we want to allow to cancel while processing events? */
14052       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14053       for (i = 0; i < mfcr2->numchans; i++) {
14054          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14055             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14056          }
14057       }
14058       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14059    }
14060    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14061    return 0;
14062 }
14063 #endif /* HAVE_OPENR2 */
14064 
14065 #if defined(HAVE_PRI)
14066 static void dahdi_pri_message(struct pri *pri, char *s)
14067 {
14068    int x;
14069    int y;
14070    int dchan = -1;
14071    int span = -1;
14072    int dchancount = 0;
14073 
14074    if (pri) {
14075       for (x = 0; x < NUM_SPANS; x++) {
14076          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14077             if (pris[x].pri.dchans[y]) {
14078                dchancount++;
14079             }
14080 
14081             if (pris[x].pri.dchans[y] == pri) {
14082                dchan = y;
14083             }
14084          }
14085          if (dchan >= 0) {
14086             span = x;
14087             break;
14088          }
14089          dchancount = 0;
14090       }
14091       if (-1 < span) {
14092          if (1 < dchancount) {
14093             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14094          } else {
14095             ast_verbose("PRI Span: %d %s", span + 1, s);
14096          }
14097       } else {
14098          ast_verbose("PRI Span: ? %s", s);
14099       }
14100    } else {
14101       ast_verbose("PRI Span: ? %s", s);
14102    }
14103 
14104    ast_mutex_lock(&pridebugfdlock);
14105 
14106    if (pridebugfd >= 0) {
14107       if (write(pridebugfd, s, strlen(s)) < 0) {
14108          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14109       }
14110    }
14111 
14112    ast_mutex_unlock(&pridebugfdlock);
14113 }
14114 #endif   /* defined(HAVE_PRI) */
14115 
14116 #if defined(HAVE_PRI)
14117 static void dahdi_pri_error(struct pri *pri, char *s)
14118 {
14119    int x;
14120    int y;
14121    int dchan = -1;
14122    int span = -1;
14123    int dchancount = 0;
14124 
14125    if (pri) {
14126       for (x = 0; x < NUM_SPANS; x++) {
14127          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14128             if (pris[x].pri.dchans[y]) {
14129                dchancount++;
14130             }
14131 
14132             if (pris[x].pri.dchans[y] == pri) {
14133                dchan = y;
14134             }
14135          }
14136          if (dchan >= 0) {
14137             span = x;
14138             break;
14139          }
14140          dchancount = 0;
14141       }
14142       if (-1 < span) {
14143          if (1 < dchancount) {
14144             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14145          } else {
14146             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14147          }
14148       } else {
14149          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14150       }
14151    } else {
14152       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14153    }
14154 
14155    ast_mutex_lock(&pridebugfdlock);
14156 
14157    if (pridebugfd >= 0) {
14158       if (write(pridebugfd, s, strlen(s)) < 0) {
14159          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14160       }
14161    }
14162 
14163    ast_mutex_unlock(&pridebugfdlock);
14164 }
14165 #endif   /* defined(HAVE_PRI) */
14166 
14167 #if defined(HAVE_PRI)
14168 static int prepare_pri(struct dahdi_pri *pri)
14169 {
14170    int i, res, x;
14171    struct dahdi_params p;
14172    struct dahdi_bufferinfo bi;
14173    struct dahdi_spaninfo si;
14174 
14175    pri->pri.calls = &dahdi_pri_callbacks;
14176 
14177    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14178       if (!pri->dchannels[i])
14179          break;
14180       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14181       x = pri->dchannels[i];
14182       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14183          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14184          return -1;
14185       }
14186       memset(&p, 0, sizeof(p));
14187       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14188       if (res) {
14189          dahdi_close_pri_fd(pri, i);
14190          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14191          return -1;
14192       }
14193       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14194          dahdi_close_pri_fd(pri, i);
14195          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14196          return -1;
14197       }
14198       memset(&si, 0, sizeof(si));
14199       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14200       if (res) {
14201          dahdi_close_pri_fd(pri, i);
14202          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14203       }
14204       if (!si.alarms) {
14205          pri_event_noalarm(&pri->pri, i, 1);
14206       } else {
14207          pri_event_alarm(&pri->pri, i, 1);
14208       }
14209       memset(&bi, 0, sizeof(bi));
14210       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14211       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14212       bi.numbufs = 32;
14213       bi.bufsize = 1024;
14214       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14215          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14216          dahdi_close_pri_fd(pri, i);
14217          return -1;
14218       }
14219       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14220    }
14221    return 0;
14222 }
14223 #endif   /* defined(HAVE_PRI) */
14224 
14225 #if defined(HAVE_PRI)
14226 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14227 {
14228    int which, span;
14229    char *ret = NULL;
14230 
14231    if (pos != rpos)
14232       return ret;
14233 
14234    for (which = span = 0; span < NUM_SPANS; span++) {
14235       if (pris[span].pri.pri && ++which > state) {
14236          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14237             ret = NULL;
14238          }
14239          break;
14240       }
14241    }
14242    return ret;
14243 }
14244 #endif   /* defined(HAVE_PRI) */
14245 
14246 #if defined(HAVE_PRI)
14247 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14248 {
14249    return complete_span_helper(line,word,pos,state,3);
14250 }
14251 #endif   /* defined(HAVE_PRI) */
14252 
14253 #if defined(HAVE_PRI)
14254 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14255 {
14256    int myfd;
14257    switch (cmd) {
14258    case CLI_INIT:
14259       e->command = "pri set debug file";
14260       e->usage = "Usage: pri set debug file [output-file]\n"
14261          "       Sends PRI debug output to the specified output file\n";
14262       return NULL;
14263    case CLI_GENERATE:
14264       return NULL;
14265    }
14266    if (a->argc < 5)
14267       return CLI_SHOWUSAGE;
14268 
14269    if (ast_strlen_zero(a->argv[4]))
14270       return CLI_SHOWUSAGE;
14271 
14272    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14273    if (myfd < 0) {
14274       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14275       return CLI_SUCCESS;
14276    }
14277 
14278    ast_mutex_lock(&pridebugfdlock);
14279 
14280    if (pridebugfd >= 0)
14281       close(pridebugfd);
14282 
14283    pridebugfd = myfd;
14284    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14285    ast_mutex_unlock(&pridebugfdlock);
14286    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14287    return CLI_SUCCESS;
14288 }
14289 #endif   /* defined(HAVE_PRI) */
14290 
14291 #if defined(HAVE_PRI)
14292 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14293 {
14294    int span;
14295    int x;
14296    int level = 0;
14297    switch (cmd) {
14298    case CLI_INIT:
14299       e->command = "pri set debug {on|off|0|1|2} span";
14300       e->usage =
14301          "Usage: pri set debug {<level>|on|off} span <span>\n"
14302          "       Enables debugging on a given PRI span\n";
14303       return NULL;
14304    case CLI_GENERATE:
14305       return complete_span_4(a->line, a->word, a->pos, a->n);
14306    }
14307    if (a->argc < 6) {
14308       return CLI_SHOWUSAGE;
14309    }
14310 
14311    if (!strcasecmp(a->argv[3], "on")) {
14312       level = 1;
14313    } else if (!strcasecmp(a->argv[3], "off")) {
14314       level = 0;
14315    } else {
14316       level = atoi(a->argv[3]);
14317    }
14318    span = atoi(a->argv[5]);
14319    if ((span < 1) || (span > NUM_SPANS)) {
14320       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14321       return CLI_SUCCESS;
14322    }
14323    if (!pris[span-1].pri.pri) {
14324       ast_cli(a->fd, "No PRI running on span %d\n", span);
14325       return CLI_SUCCESS;
14326    }
14327 
14328    /* Set debug level in libpri */
14329    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14330       if (pris[span - 1].pri.dchans[x]) {
14331          switch (level) {
14332          case 0:
14333             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14334             break;
14335          case 1:
14336             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14337             break;
14338          default:
14339             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14340             break;
14341          }
14342       }
14343    }
14344    if (level == 0) {
14345       /* Close the debugging file if it's set */
14346       ast_mutex_lock(&pridebugfdlock);
14347       if (0 <= pridebugfd) {
14348          close(pridebugfd);
14349          pridebugfd = -1;
14350          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14351             pridebugfilename);
14352       }
14353       ast_mutex_unlock(&pridebugfdlock);
14354    }
14355    pris[span - 1].pri.debug = (level) ? 1 : 0;
14356    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14357    return CLI_SUCCESS;
14358 }
14359 #endif   /* defined(HAVE_PRI) */
14360 
14361 #if defined(HAVE_PRI)
14362 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14363 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14364 {
14365    unsigned *why;
14366    int channel;
14367    int trunkgroup;
14368    int x, y, fd = a->fd;
14369    int interfaceid = 0;
14370    char db_chan_name[20], db_answer[5];
14371    struct dahdi_pvt *tmp;
14372    struct dahdi_pri *pri;
14373 
14374    if (a->argc < 5 || a->argc > 6)
14375       return CLI_SHOWUSAGE;
14376    if (strchr(a->argv[4], ':')) {
14377       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14378          return CLI_SHOWUSAGE;
14379       if ((trunkgroup < 1) || (channel < 1))
14380          return CLI_SHOWUSAGE;
14381       pri = NULL;
14382       for (x=0;x<NUM_SPANS;x++) {
14383          if (pris[x].pri.trunkgroup == trunkgroup) {
14384             pri = pris + x;
14385             break;
14386          }
14387       }
14388       if (!pri) {
14389          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14390          return CLI_FAILURE;
14391       }
14392    } else
14393       channel = atoi(a->argv[4]);
14394 
14395    if (a->argc == 6)
14396       interfaceid = atoi(a->argv[5]);
14397 
14398    /* either servicing a D-Channel */
14399    for (x = 0; x < NUM_SPANS; x++) {
14400       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14401          if (pris[x].dchannels[y] == channel) {
14402             pri = pris + x;
14403             if (pri->pri.enable_service_message_support) {
14404                ast_mutex_lock(&pri->pri.lock);
14405                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14406                ast_mutex_unlock(&pri->pri.lock);
14407             } else {
14408                ast_cli(fd,
14409                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14410                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14411             }
14412             return CLI_SUCCESS;
14413          }
14414       }
14415    }
14416 
14417    /* or servicing a B-Channel */
14418    ast_mutex_lock(&iflock);
14419    for (tmp = iflist; tmp; tmp = tmp->next) {
14420       if (tmp->pri && tmp->channel == channel) {
14421          ast_mutex_unlock(&iflock);
14422          ast_mutex_lock(&tmp->pri->lock);
14423          if (!tmp->pri->enable_service_message_support) {
14424             ast_mutex_unlock(&tmp->pri->lock);
14425             ast_cli(fd,
14426                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14427                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14428             return CLI_SUCCESS;
14429          }
14430          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14431          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14432          switch(changestatus) {
14433          case 0: /* enable */
14434             /* Near end wants to be in service now. */
14435             ast_db_del(db_chan_name, SRVST_DBKEY);
14436             *why &= ~SRVST_NEAREND;
14437             if (*why) {
14438                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14439                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14440             } else {
14441                dahdi_pri_update_span_devstate(tmp->pri);
14442             }
14443             break;
14444          /* case 1:  -- loop */
14445          case 2: /* disable */
14446             /* Near end wants to be out-of-service now. */
14447             ast_db_del(db_chan_name, SRVST_DBKEY);
14448             *why |= SRVST_NEAREND;
14449             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14450             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14451             dahdi_pri_update_span_devstate(tmp->pri);
14452             break;
14453          /* case 3:  -- continuity */
14454          /* case 4:  -- shutdown */
14455          default:
14456             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14457             break;
14458          }
14459          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14460          ast_mutex_unlock(&tmp->pri->lock);
14461          return CLI_SUCCESS;
14462       }
14463    }
14464    ast_mutex_unlock(&iflock);
14465 
14466    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14467    return CLI_FAILURE;
14468 }
14469 
14470 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14471 {
14472    switch (cmd) {
14473    case CLI_INIT:
14474       e->command = "pri service enable channel";
14475       e->usage =
14476          "Usage: pri service enable channel <channel> [<interface id>]\n"
14477          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14478          "  to restore a channel to service, with optional interface id\n"
14479          "  as agreed upon with remote switch operator\n";
14480       return NULL;
14481    case CLI_GENERATE:
14482       return NULL;
14483    }
14484    return handle_pri_service_generic(e, cmd, a, 0);
14485 }
14486 
14487 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14488 {
14489    switch (cmd) {
14490    case CLI_INIT:
14491       e->command = "pri service disable channel";
14492       e->usage =
14493          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14494          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14495          "  to remove a channel from service, with optional interface id\n"
14496          "  as agreed upon with remote switch operator\n";
14497       return NULL;
14498    case CLI_GENERATE:
14499       return NULL;
14500    }
14501    return handle_pri_service_generic(e, cmd, a, 2);
14502 }
14503 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14504 #endif   /* defined(HAVE_PRI) */
14505 
14506 #if defined(HAVE_PRI)
14507 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14508 {
14509    int span;
14510 
14511    switch (cmd) {
14512    case CLI_INIT:
14513       e->command = "pri show channels";
14514       e->usage =
14515          "Usage: pri show channels\n"
14516          "       Displays PRI channel information such as the current mapping\n"
14517          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14518          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14519          "       are not associated with any B channel.\n";
14520       return NULL;
14521    case CLI_GENERATE:
14522       return NULL;
14523    }
14524 
14525    if (a->argc != 3)
14526       return CLI_SHOWUSAGE;
14527 
14528    sig_pri_cli_show_channels_header(a->fd);
14529    for (span = 0; span < NUM_SPANS; ++span) {
14530       if (pris[span].pri.pri) {
14531          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14532       }
14533    }
14534    return CLI_SUCCESS;
14535 }
14536 #endif   /* defined(HAVE_PRI) */
14537 
14538 #if defined(HAVE_PRI)
14539 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14540 {
14541    int span;
14542 
14543    switch (cmd) {
14544    case CLI_INIT:
14545       e->command = "pri show spans";
14546       e->usage =
14547          "Usage: pri show spans\n"
14548          "       Displays PRI span information\n";
14549       return NULL;
14550    case CLI_GENERATE:
14551       return NULL;
14552    }
14553 
14554    if (a->argc != 3)
14555       return CLI_SHOWUSAGE;
14556 
14557    for (span = 0; span < NUM_SPANS; span++) {
14558       if (pris[span].pri.pri) {
14559          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14560       }
14561    }
14562    return CLI_SUCCESS;
14563 }
14564 #endif   /* defined(HAVE_PRI) */
14565 
14566 #if defined(HAVE_PRI)
14567 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14568 {
14569    int span;
14570 
14571    switch (cmd) {
14572    case CLI_INIT:
14573       e->command = "pri show span";
14574       e->usage =
14575          "Usage: pri show span <span>\n"
14576          "       Displays PRI Information on a given PRI span\n";
14577       return NULL;
14578    case CLI_GENERATE:
14579       return complete_span_4(a->line, a->word, a->pos, a->n);
14580    }
14581 
14582    if (a->argc < 4)
14583       return CLI_SHOWUSAGE;
14584    span = atoi(a->argv[3]);
14585    if ((span < 1) || (span > NUM_SPANS)) {
14586       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14587       return CLI_SUCCESS;
14588    }
14589    if (!pris[span-1].pri.pri) {
14590       ast_cli(a->fd, "No PRI running on span %d\n", span);
14591       return CLI_SUCCESS;
14592    }
14593 
14594    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14595 
14596    return CLI_SUCCESS;
14597 }
14598 #endif   /* defined(HAVE_PRI) */
14599 
14600 #if defined(HAVE_PRI)
14601 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14602 {
14603    int x;
14604    int span;
14605    int count=0;
14606    int debug;
14607 
14608    switch (cmd) {
14609    case CLI_INIT:
14610       e->command = "pri show debug";
14611       e->usage =
14612          "Usage: pri show debug\n"
14613          "  Show the debug state of pri spans\n";
14614       return NULL;
14615    case CLI_GENERATE:
14616       return NULL;
14617    }
14618 
14619    for (span = 0; span < NUM_SPANS; span++) {
14620       if (pris[span].pri.pri) {
14621          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14622             if (pris[span].pri.dchans[x]) {
14623                debug = pri_get_debug(pris[span].pri.dchans[x]);
14624                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" );
14625                count++;
14626             }
14627          }
14628       }
14629 
14630    }
14631    ast_mutex_lock(&pridebugfdlock);
14632    if (pridebugfd >= 0)
14633       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14634    ast_mutex_unlock(&pridebugfdlock);
14635 
14636    if (!count)
14637       ast_cli(a->fd, "No PRI running\n");
14638    return CLI_SUCCESS;
14639 }
14640 #endif   /* defined(HAVE_PRI) */
14641 
14642 #if defined(HAVE_PRI)
14643 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14644 {
14645    switch (cmd) {
14646    case CLI_INIT:
14647       e->command = "pri show version";
14648       e->usage =
14649          "Usage: pri show version\n"
14650          "Show libpri version information\n";
14651       return NULL;
14652    case CLI_GENERATE:
14653       return NULL;
14654    }
14655 
14656    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14657 
14658    return CLI_SUCCESS;
14659 }
14660 #endif   /* defined(HAVE_PRI) */
14661 
14662 #if defined(HAVE_PRI)
14663 static struct ast_cli_entry dahdi_pri_cli[] = {
14664    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14665 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14666    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14667    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14668 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14669    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14670    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14671    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14672    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14673    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14674    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14675 };
14676 #endif   /* defined(HAVE_PRI) */
14677 
14678 #ifdef HAVE_OPENR2
14679 
14680 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14681 {
14682    switch (cmd) {
14683    case CLI_INIT:
14684       e->command = "mfcr2 show version";
14685       e->usage =
14686          "Usage: mfcr2 show version\n"
14687          "       Shows the version of the OpenR2 library being used.\n";
14688       return NULL;
14689    case CLI_GENERATE:
14690       return NULL;
14691    }
14692    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14693    return CLI_SUCCESS;
14694 }
14695 
14696 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14697 {
14698 #define FORMAT "%4s %40s\n"
14699    int i = 0;
14700    int numvariants = 0;
14701    const openr2_variant_entry_t *variants;
14702    switch (cmd) {
14703    case CLI_INIT:
14704       e->command = "mfcr2 show variants";
14705       e->usage =
14706          "Usage: mfcr2 show variants\n"
14707          "       Shows the list of MFC/R2 variants supported.\n";
14708       return NULL;
14709    case CLI_GENERATE:
14710       return NULL;
14711    }
14712    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14713       ast_cli(a->fd, "Failed to get list of variants.\n");
14714       return CLI_FAILURE;
14715    }
14716    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14717    for (i = 0; i < numvariants; i++) {
14718       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14719    }
14720    return CLI_SUCCESS;
14721 #undef FORMAT
14722 }
14723 
14724 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14725 {
14726 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14727    int filtertype = 0;
14728    int targetnum = 0;
14729    char channo[5];
14730    char anino[5];
14731    char dnisno[5];
14732    struct dahdi_pvt *p;
14733    openr2_context_t *r2context;
14734    openr2_variant_t r2variant;
14735    switch (cmd) {
14736    case CLI_INIT:
14737       e->command = "mfcr2 show channels [group|context]";
14738       e->usage =
14739          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14740          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14741       return NULL;
14742    case CLI_GENERATE:
14743       return NULL;
14744    }
14745    if (!((a->argc == 3) || (a->argc == 5))) {
14746       return CLI_SHOWUSAGE;
14747    }
14748    if (a->argc == 5) {
14749       if (!strcasecmp(a->argv[3], "group")) {
14750          targetnum = atoi(a->argv[4]);
14751          if ((targetnum < 0) || (targetnum > 63))
14752             return CLI_SHOWUSAGE;
14753          targetnum = 1 << targetnum;
14754          filtertype = 1;
14755       } else if (!strcasecmp(a->argv[3], "context")) {
14756          filtertype = 2;
14757       } else {
14758          return CLI_SHOWUSAGE;
14759       }
14760    }
14761    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14762    ast_mutex_lock(&iflock);
14763    for (p = iflist; p; p = p->next) {
14764       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14765          continue;
14766       }
14767       if (filtertype) {
14768          switch(filtertype) {
14769          case 1: /* mfcr2 show channels group <group> */
14770             if (p->group != targetnum) {
14771                continue;
14772             }
14773             break;
14774          case 2: /* mfcr2 show channels context <context> */
14775             if (strcasecmp(p->context, a->argv[4])) {
14776                continue;
14777             }
14778             break;
14779          default:
14780             ;
14781          }
14782       }
14783       r2context = openr2_chan_get_context(p->r2chan);
14784       r2variant = openr2_context_get_variant(r2context);
14785       snprintf(channo, sizeof(channo), "%d", p->channel);
14786       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14787       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14788       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14789             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14790             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14791             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14792    }
14793    ast_mutex_unlock(&iflock);
14794    return CLI_SUCCESS;
14795 #undef FORMAT
14796 }
14797 
14798 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14799 {
14800    struct dahdi_pvt *p = NULL;
14801    int channo = 0;
14802    char *toklevel = NULL;
14803    char *saveptr = NULL;
14804    char *logval = NULL;
14805    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14806    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14807    switch (cmd) {
14808    case CLI_INIT:
14809       e->command = "mfcr2 set debug";
14810       e->usage =
14811          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14812          "       Set a new logging level for the specified channel.\n"
14813          "       If no channel is specified the logging level will be applied to all channels.\n";
14814       return NULL;
14815    case CLI_GENERATE:
14816       return NULL;
14817    }
14818    if (a->argc < 4) {
14819       return CLI_SHOWUSAGE;
14820    }
14821    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14822    logval = ast_strdupa(a->argv[3]);
14823    toklevel = strtok_r(logval, ",", &saveptr);
14824    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14825       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14826       return CLI_FAILURE;
14827    } else if (OR2_LOG_NOTHING == tmplevel) {
14828       loglevel = tmplevel;
14829    } else {
14830       loglevel |= tmplevel;
14831       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14832          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14833             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14834             continue;
14835          }
14836          loglevel |= tmplevel;
14837       }
14838    }
14839    ast_mutex_lock(&iflock);
14840    for (p = iflist; p; p = p->next) {
14841       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14842          continue;
14843       }
14844       if ((channo != -1) && (p->channel != channo )) {
14845          continue;
14846       }
14847       openr2_chan_set_log_level(p->r2chan, loglevel);
14848       if (channo != -1) {
14849          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14850          break;
14851       }
14852    }
14853    if ((channo != -1) && !p) {
14854       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14855    }
14856    if (channo == -1) {
14857       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14858    }
14859    ast_mutex_unlock(&iflock);
14860    return CLI_SUCCESS;
14861 }
14862 
14863 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14864 {
14865    struct dahdi_pvt *p = NULL;
14866    int channo = 0;
14867    switch (cmd) {
14868    case CLI_INIT:
14869       e->command = "mfcr2 call files [on|off]";
14870       e->usage =
14871          "Usage: mfcr2 call files [on|off] <channel>\n"
14872          "       Enable call files creation on the specified channel.\n"
14873          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14874       return NULL;
14875    case CLI_GENERATE:
14876       return NULL;
14877    }
14878    if (a->argc < 4) {
14879       return CLI_SHOWUSAGE;
14880    }
14881    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14882    ast_mutex_lock(&iflock);
14883    for (p = iflist; p; p = p->next) {
14884       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14885          continue;
14886       }
14887       if ((channo != -1) && (p->channel != channo )) {
14888          continue;
14889       }
14890       if (ast_true(a->argv[3])) {
14891          openr2_chan_enable_call_files(p->r2chan);
14892       } else {
14893          openr2_chan_disable_call_files(p->r2chan);
14894       }
14895       if (channo != -1) {
14896          if (ast_true(a->argv[3])) {
14897             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14898          } else {
14899             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14900          }
14901          break;
14902       }
14903    }
14904    if ((channo != -1) && !p) {
14905       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14906    }
14907    if (channo == -1) {
14908       if (ast_true(a->argv[3])) {
14909          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14910       } else {
14911          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14912       }
14913    }
14914    ast_mutex_unlock(&iflock);
14915    return CLI_SUCCESS;
14916 }
14917 
14918 static char *handle_mfcr2_set_idle(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 set idle";
14925       e->usage =
14926          "Usage: mfcr2 set idle <channel>\n"
14927          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14928          "       Force the given channel into IDLE state.\n"
14929          "       If no channel is specified, all channels will be set to IDLE.\n";
14930       return NULL;
14931    case CLI_GENERATE:
14932       return NULL;
14933    }
14934    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14935    ast_mutex_lock(&iflock);
14936    for (p = iflist; p; p = p->next) {
14937       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14938          continue;
14939       }
14940       if ((channo != -1) && (p->channel != channo )) {
14941          continue;
14942       }
14943       openr2_chan_set_idle(p->r2chan);
14944       ast_mutex_lock(&p->lock);
14945       p->locallyblocked = 0;
14946       p->mfcr2call = 0;
14947       ast_mutex_unlock(&p->lock);
14948       if (channo != -1) {
14949          break;
14950       }
14951    }
14952    if ((channo != -1) && !p) {
14953       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14954    }
14955    ast_mutex_unlock(&iflock);
14956    return CLI_SUCCESS;
14957 }
14958 
14959 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14960 {
14961    struct dahdi_pvt *p = NULL;
14962    int channo = 0;
14963    switch (cmd) {
14964    case CLI_INIT:
14965       e->command = "mfcr2 set blocked";
14966       e->usage =
14967          "Usage: mfcr2 set blocked <channel>\n"
14968          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14969          "       Force the given channel into BLOCKED state.\n"
14970          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14971       return NULL;
14972    case CLI_GENERATE:
14973       return NULL;
14974    }
14975    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14976    ast_mutex_lock(&iflock);
14977    for (p = iflist; p; p = p->next) {
14978       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14979          continue;
14980       }
14981       if ((channo != -1) && (p->channel != channo )) {
14982          continue;
14983       }
14984       openr2_chan_set_blocked(p->r2chan);
14985       ast_mutex_lock(&p->lock);
14986       p->locallyblocked = 1;
14987       ast_mutex_unlock(&p->lock);
14988       if (channo != -1) {
14989          break;
14990       }
14991    }
14992    if ((channo != -1) && !p) {
14993       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14994    }
14995    ast_mutex_unlock(&iflock);
14996    return CLI_SUCCESS;
14997 }
14998 
14999 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15000    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15001    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15002    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15003    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15004    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15005    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15006    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15007 };
15008 
15009 #endif /* HAVE_OPENR2 */
15010 
15011 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15012 {
15013    int channel;
15014    int ret;
15015    switch (cmd) {
15016    case CLI_INIT:
15017       e->command = "dahdi destroy channel";
15018       e->usage =
15019          "Usage: dahdi destroy channel <chan num>\n"
15020          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15021       return NULL;
15022    case CLI_GENERATE:
15023       return NULL;
15024    }
15025    if (a->argc != 4)
15026       return CLI_SHOWUSAGE;
15027 
15028    channel = atoi(a->argv[3]);
15029    ret = dahdi_destroy_channel_bynum(channel);
15030    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15031 }
15032 
15033 static void dahdi_softhangup_all(void)
15034 {
15035    struct dahdi_pvt *p;
15036 retry:
15037    ast_mutex_lock(&iflock);
15038    for (p = iflist; p; p = p->next) {
15039       ast_mutex_lock(&p->lock);
15040       if (p->owner && !p->restartpending) {
15041          if (ast_channel_trylock(p->owner)) {
15042             if (option_debug > 2)
15043                ast_verbose("Avoiding deadlock\n");
15044             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15045             ast_mutex_unlock(&p->lock);
15046             ast_mutex_unlock(&iflock);
15047             goto retry;
15048          }
15049          if (option_debug > 2)
15050             ast_verbose("Softhanging up on %s\n", p->owner->name);
15051          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15052          p->restartpending = 1;
15053          num_restart_pending++;
15054          ast_channel_unlock(p->owner);
15055       }
15056       ast_mutex_unlock(&p->lock);
15057    }
15058    ast_mutex_unlock(&iflock);
15059 }
15060 
15061 static int setup_dahdi(int reload);
15062 static int dahdi_restart(void)
15063 {
15064 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15065    int i, j;
15066 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15067    int cancel_code;
15068    struct dahdi_pvt *p;
15069 
15070    ast_mutex_lock(&restart_lock);
15071    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15072    dahdi_softhangup_all();
15073    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15074 #ifdef HAVE_OPENR2
15075    dahdi_r2_destroy_links();
15076 #endif
15077 
15078 #if defined(HAVE_PRI)
15079    for (i = 0; i < NUM_SPANS; i++) {
15080       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15081          cancel_code = pthread_cancel(pris[i].pri.master);
15082          pthread_kill(pris[i].pri.master, SIGURG);
15083          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);
15084          pthread_join(pris[i].pri.master, NULL);
15085          ast_debug(4, "Joined thread of span %d\n", i);
15086       }
15087    }
15088 #endif
15089 
15090 #if defined(HAVE_SS7)
15091    for (i = 0; i < NUM_SPANS; i++) {
15092       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15093          cancel_code = pthread_cancel(linksets[i].ss7.master);
15094          pthread_kill(linksets[i].ss7.master, SIGURG);
15095          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);
15096          pthread_join(linksets[i].ss7.master, NULL);
15097          ast_debug(4, "Joined thread of span %d\n", i);
15098       }
15099    }
15100 #endif   /* defined(HAVE_SS7) */
15101 
15102    ast_mutex_lock(&monlock);
15103    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15104       cancel_code = pthread_cancel(monitor_thread);
15105       pthread_kill(monitor_thread, SIGURG);
15106       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15107       pthread_join(monitor_thread, NULL);
15108       ast_debug(4, "Joined monitor thread\n");
15109    }
15110    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15111 
15112    ast_mutex_lock(&ss_thread_lock);
15113    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15114       int x = DAHDI_FLASH;
15115       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15116 
15117       ast_mutex_lock(&iflock);
15118       for (p = iflist; p; p = p->next) {
15119          if (p->owner) {
15120             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15121             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15122          }
15123       }
15124       ast_mutex_unlock(&iflock);
15125       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15126    }
15127 
15128    /* ensure any created channels before monitor threads were stopped are hungup */
15129    dahdi_softhangup_all();
15130    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15131    destroy_all_channels();
15132    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15133 
15134    ast_mutex_unlock(&monlock);
15135 
15136 #ifdef HAVE_PRI
15137    for (i = 0; i < NUM_SPANS; i++) {
15138       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15139          dahdi_close_pri_fd(&(pris[i]), j);
15140    }
15141 
15142    memset(pris, 0, sizeof(pris));
15143    for (i = 0; i < NUM_SPANS; i++) {
15144       sig_pri_init_pri(&pris[i].pri);
15145    }
15146    pri_set_error(dahdi_pri_error);
15147    pri_set_message(dahdi_pri_message);
15148 #endif
15149 #if defined(HAVE_SS7)
15150    for (i = 0; i < NUM_SPANS; i++) {
15151       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15152          dahdi_close_ss7_fd(&(linksets[i]), j);
15153    }
15154 
15155    memset(linksets, 0, sizeof(linksets));
15156    for (i = 0; i < NUM_SPANS; i++) {
15157       sig_ss7_init_linkset(&linksets[i].ss7);
15158    }
15159    ss7_set_error(dahdi_ss7_error);
15160    ss7_set_message(dahdi_ss7_message);
15161 #endif   /* defined(HAVE_SS7) */
15162 
15163    if (setup_dahdi(2) != 0) {
15164       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15165       ast_mutex_unlock(&ss_thread_lock);
15166       return 1;
15167    }
15168    ast_mutex_unlock(&ss_thread_lock);
15169    ast_mutex_unlock(&restart_lock);
15170    return 0;
15171 }
15172 
15173 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15174 {
15175    switch (cmd) {
15176    case CLI_INIT:
15177       e->command = "dahdi restart";
15178       e->usage =
15179          "Usage: dahdi restart\n"
15180          "  Restarts the DAHDI channels: destroys them all and then\n"
15181          "  re-reads them from chan_dahdi.conf.\n"
15182          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15183          "";
15184       return NULL;
15185    case CLI_GENERATE:
15186       return NULL;
15187    }
15188    if (a->argc != 2)
15189       return CLI_SHOWUSAGE;
15190 
15191    if (dahdi_restart() != 0)
15192       return CLI_FAILURE;
15193    return CLI_SUCCESS;
15194 }
15195 
15196 static int action_dahdirestart(struct mansession *s, const struct message *m)
15197 {
15198    if (dahdi_restart() != 0) {
15199       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15200       return 1;
15201    }
15202    astman_send_ack(s, m, "DAHDIRestart: Success");
15203    return 0;
15204 }
15205 
15206 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15207 {
15208 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15209 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15210    unsigned int targetnum = 0;
15211    int filtertype = 0;
15212    struct dahdi_pvt *tmp = NULL;
15213    char tmps[20] = "";
15214    char statestr[20] = "";
15215    char blockstr[20] = "";
15216 
15217    switch (cmd) {
15218    case CLI_INIT:
15219       e->command = "dahdi show channels [group|context]";
15220       e->usage =
15221          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15222          "  Shows a list of available channels with optional filtering\n"
15223          "  <group> must be a number between 0 and 63\n";
15224       return NULL;
15225    case CLI_GENERATE:
15226       return NULL;
15227    }
15228 
15229    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15230 
15231    if (!((a->argc == 3) || (a->argc == 5)))
15232       return CLI_SHOWUSAGE;
15233 
15234    if (a->argc == 5) {
15235       if (!strcasecmp(a->argv[3], "group")) {
15236          targetnum = atoi(a->argv[4]);
15237          if ((targetnum < 0) || (targetnum > 63))
15238             return CLI_SHOWUSAGE;
15239          targetnum = 1 << targetnum;
15240          filtertype = 1;
15241       } else if (!strcasecmp(a->argv[3], "context")) {
15242          filtertype = 2;
15243       }
15244    }
15245 
15246    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15247    ast_mutex_lock(&iflock);
15248    for (tmp = iflist; tmp; tmp = tmp->next) {
15249       if (filtertype) {
15250          switch(filtertype) {
15251          case 1: /* dahdi show channels group <group> */
15252             if (!(tmp->group & targetnum)) {
15253                continue;
15254             }
15255             break;
15256          case 2: /* dahdi show channels context <context> */
15257             if (strcasecmp(tmp->context, a->argv[4])) {
15258                continue;
15259             }
15260             break;
15261          default:
15262             break;
15263          }
15264       }
15265       if (tmp->channel > 0) {
15266          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15267       } else
15268          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15269 
15270       if (tmp->locallyblocked)
15271          blockstr[0] = 'L';
15272       else
15273          blockstr[0] = ' ';
15274 
15275       if (tmp->remotelyblocked)
15276          blockstr[1] = 'R';
15277       else
15278          blockstr[1] = ' ';
15279 
15280       blockstr[2] = '\0';
15281 
15282       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15283 
15284       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15285    }
15286    ast_mutex_unlock(&iflock);
15287    return CLI_SUCCESS;
15288 #undef FORMAT
15289 #undef FORMAT2
15290 }
15291 
15292 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15293 {
15294    int channel;
15295    struct dahdi_pvt *tmp = NULL;
15296    struct dahdi_confinfo ci;
15297    struct dahdi_params ps;
15298    int x;
15299 
15300    switch (cmd) {
15301    case CLI_INIT:
15302       e->command = "dahdi show channel";
15303       e->usage =
15304          "Usage: dahdi show channel <chan num>\n"
15305          "  Detailed information about a given channel\n";
15306       return NULL;
15307    case CLI_GENERATE:
15308       return NULL;
15309    }
15310 
15311    if (a->argc != 4)
15312       return CLI_SHOWUSAGE;
15313 
15314    channel = atoi(a->argv[3]);
15315 
15316    ast_mutex_lock(&iflock);
15317    for (tmp = iflist; tmp; tmp = tmp->next) {
15318       if (tmp->channel == channel) {
15319          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15320          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15321          ast_cli(a->fd, "Span: %d\n", tmp->span);
15322          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15323          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15324          ast_cli(a->fd, "Context: %s\n", tmp->context);
15325          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15326          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15327 #if defined(HAVE_PRI)
15328 #if defined(HAVE_PRI_SUBADDR)
15329          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15330 #endif   /* defined(HAVE_PRI_SUBADDR) */
15331 #endif   /* defined(HAVE_PRI) */
15332          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15333          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15334          if (tmp->vars) {
15335             struct ast_variable *v;
15336             ast_cli(a->fd, "Variables:\n");
15337             for (v = tmp->vars ; v ; v = v->next)
15338                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15339          }
15340          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15341          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15342          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15343          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15344          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15345          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)" : "");
15346          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)" : "");
15347          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)" : "");
15348          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15349          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15350          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15351          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15352          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15353          if (tmp->busydetect) {
15354 #if defined(BUSYDETECT_TONEONLY)
15355             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15356 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15357             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15358 #endif
15359 #ifdef BUSYDETECT_DEBUG
15360             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15361 #endif
15362             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15363             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15364          }
15365          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15366          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15367          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15368          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15369          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15370          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15371          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15372          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15373          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15374          ast_cli(a->fd, "Echo Cancellation:\n");
15375 
15376          if (tmp->echocancel.head.tap_length) {
15377             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15378             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15379                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15380             }
15381             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15382          } else {
15383             ast_cli(a->fd, "\tnone\n");
15384          }
15385          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15386          if (tmp->master)
15387             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15388          for (x = 0; x < MAX_SLAVES; x++) {
15389             if (tmp->slaves[x])
15390                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15391          }
15392 #ifdef HAVE_OPENR2
15393          if (tmp->mfcr2) {
15394             char calldir[OR2_MAX_PATH];
15395             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15396             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15397             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15398             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15399             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15400             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15401             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15402             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15403             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15404             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15405             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15406 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15407             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15408 #endif
15409             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15410             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15411             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15412             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15413             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15414             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15415             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15416             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15417             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15418             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15419             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15420             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15421          }
15422 #endif
15423 #if defined(HAVE_SS7)
15424          if (tmp->ss7) {
15425             struct sig_ss7_chan *chan = tmp->sig_pvt;
15426 
15427             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15428          }
15429 #endif   /* defined(HAVE_SS7) */
15430 #ifdef HAVE_PRI
15431          if (tmp->pri) {
15432             struct sig_pri_chan *chan = tmp->sig_pvt;
15433 
15434             ast_cli(a->fd, "PRI Flags: ");
15435             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15436                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15437             }
15438             if (chan->call)
15439                ast_cli(a->fd, "Call ");
15440             if (chan->allocated) {
15441                ast_cli(a->fd, "Allocated ");
15442             }
15443             ast_cli(a->fd, "\n");
15444             if (tmp->logicalspan)
15445                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15446             else
15447                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15448          }
15449 #endif
15450          memset(&ci, 0, sizeof(ci));
15451          ps.channo = tmp->channel;
15452          if (tmp->subs[SUB_REAL].dfd > -1) {
15453             memset(&ci, 0, sizeof(ci));
15454             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15455                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15456             }
15457             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15458                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15459             }
15460             memset(&ps, 0, sizeof(ps));
15461             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15462                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15463             } else {
15464                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15465             }
15466          }
15467          ast_mutex_unlock(&iflock);
15468          return CLI_SUCCESS;
15469       }
15470    }
15471    ast_mutex_unlock(&iflock);
15472 
15473    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15474    return CLI_FAILURE;
15475 }
15476 
15477 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15478 {
15479    int i, j;
15480    switch (cmd) {
15481    case CLI_INIT:
15482       e->command = "dahdi show cadences";
15483       e->usage =
15484          "Usage: dahdi show cadences\n"
15485          "       Shows all cadences currently defined\n";
15486       return NULL;
15487    case CLI_GENERATE:
15488       return NULL;
15489    }
15490    for (i = 0; i < num_cadence; i++) {
15491       char output[1024];
15492       char tmp[16], tmp2[64];
15493       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15494       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15495 
15496       for (j = 0; j < 16; j++) {
15497          if (cadences[i].ringcadence[j] == 0)
15498             break;
15499          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15500          if (cidrings[i] * 2 - 1 == j)
15501             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15502          else
15503             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15504          if (j != 0)
15505             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15506          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15507       }
15508       ast_cli(a->fd,"%s\n",output);
15509    }
15510    return CLI_SUCCESS;
15511 }
15512 
15513 /* Based on irqmiss.c */
15514 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15515 {
15516    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15517    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15518    int span;
15519    int res;
15520    char alarmstr[50];
15521 
15522    int ctl;
15523    struct dahdi_spaninfo s;
15524 
15525    switch (cmd) {
15526    case CLI_INIT:
15527       e->command = "dahdi show status";
15528       e->usage =
15529          "Usage: dahdi show status\n"
15530          "       Shows a list of DAHDI cards with status\n";
15531       return NULL;
15532    case CLI_GENERATE:
15533       return NULL;
15534    }
15535    ctl = open("/dev/dahdi/ctl", O_RDWR);
15536    if (ctl < 0) {
15537       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15538       return CLI_FAILURE;
15539    }
15540    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15541 
15542    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15543       s.spanno = span;
15544       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15545       if (res) {
15546          continue;
15547       }
15548       alarmstr[0] = '\0';
15549       if (s.alarms > 0) {
15550          if (s.alarms & DAHDI_ALARM_BLUE)
15551             strcat(alarmstr, "BLU/");
15552          if (s.alarms & DAHDI_ALARM_YELLOW)
15553             strcat(alarmstr, "YEL/");
15554          if (s.alarms & DAHDI_ALARM_RED)
15555             strcat(alarmstr, "RED/");
15556          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15557             strcat(alarmstr, "LB/");
15558          if (s.alarms & DAHDI_ALARM_RECOVER)
15559             strcat(alarmstr, "REC/");
15560          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15561             strcat(alarmstr, "NOP/");
15562          if (!strlen(alarmstr))
15563             strcat(alarmstr, "UUU/");
15564          if (strlen(alarmstr)) {
15565             /* Strip trailing / */
15566             alarmstr[strlen(alarmstr) - 1] = '\0';
15567          }
15568       } else {
15569          if (s.numchans)
15570             strcpy(alarmstr, "OK");
15571          else
15572             strcpy(alarmstr, "UNCONFIGURED");
15573       }
15574 
15575       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15576          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15577          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15578          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15579          "CAS",
15580          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15581          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15582          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15583          "Unk",
15584          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15585             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15586             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15587          lbostr[s.lbo]
15588          );
15589    }
15590    close(ctl);
15591 
15592    return CLI_SUCCESS;
15593 #undef FORMAT
15594 #undef FORMAT2
15595 }
15596 
15597 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15598 {
15599    int pseudo_fd = -1;
15600    struct dahdi_versioninfo vi;
15601 
15602    switch (cmd) {
15603    case CLI_INIT:
15604       e->command = "dahdi show version";
15605       e->usage =
15606          "Usage: dahdi show version\n"
15607          "       Shows the DAHDI version in use\n";
15608       return NULL;
15609    case CLI_GENERATE:
15610       return NULL;
15611    }
15612    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15613       ast_cli(a->fd, "Failed to open control file to get version.\n");
15614       return CLI_SUCCESS;
15615    }
15616 
15617    strcpy(vi.version, "Unknown");
15618    strcpy(vi.echo_canceller, "Unknown");
15619 
15620    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15621       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15622    else
15623       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15624 
15625    close(pseudo_fd);
15626 
15627    return CLI_SUCCESS;
15628 }
15629 
15630 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15631 {
15632    int channel;
15633    int gain;
15634    int tx;
15635    struct dahdi_hwgain hwgain;
15636    struct dahdi_pvt *tmp = NULL;
15637 
15638    switch (cmd) {
15639    case CLI_INIT:
15640       e->command = "dahdi set hwgain";
15641       e->usage =
15642          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15643          "  Sets the hardware gain on a a given channel, overriding the\n"
15644          "   value provided at module loadtime, whether the channel is in\n"
15645          "   use or not.  Changes take effect immediately.\n"
15646          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15647          "   <chan num> is the channel number relative to the device\n"
15648          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15649       return NULL;
15650    case CLI_GENERATE:
15651       return NULL;
15652    }
15653 
15654    if (a->argc != 6)
15655       return CLI_SHOWUSAGE;
15656 
15657    if (!strcasecmp("rx", a->argv[3]))
15658       tx = 0; /* rx */
15659    else if (!strcasecmp("tx", a->argv[3]))
15660       tx = 1; /* tx */
15661    else
15662       return CLI_SHOWUSAGE;
15663 
15664    channel = atoi(a->argv[4]);
15665    gain = atof(a->argv[5])*10.0;
15666 
15667    ast_mutex_lock(&iflock);
15668 
15669    for (tmp = iflist; tmp; tmp = tmp->next) {
15670 
15671       if (tmp->channel != channel)
15672          continue;
15673 
15674       if (tmp->subs[SUB_REAL].dfd == -1)
15675          break;
15676 
15677       hwgain.newgain = gain;
15678       hwgain.tx = tx;
15679       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15680          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15681          ast_mutex_unlock(&iflock);
15682          return CLI_FAILURE;
15683       }
15684       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15685          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15686       break;
15687    }
15688 
15689    ast_mutex_unlock(&iflock);
15690 
15691    if (tmp)
15692       return CLI_SUCCESS;
15693 
15694    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15695    return CLI_FAILURE;
15696 
15697 }
15698 
15699 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15700 {
15701    int channel;
15702    float gain;
15703    int tx;
15704    int res;
15705    struct dahdi_pvt *tmp = NULL;
15706 
15707    switch (cmd) {
15708    case CLI_INIT:
15709       e->command = "dahdi set swgain";
15710       e->usage =
15711          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15712          "  Sets the software gain on a a given channel, overriding the\n"
15713          "   value provided at module loadtime, whether the channel is in\n"
15714          "   use or not.  Changes take effect immediately.\n"
15715          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15716          "   <chan num> is the channel number relative to the device\n"
15717          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15718       return NULL;
15719    case CLI_GENERATE:
15720       return NULL;
15721    }
15722 
15723    if (a->argc != 6)
15724       return CLI_SHOWUSAGE;
15725 
15726    if (!strcasecmp("rx", a->argv[3]))
15727       tx = 0; /* rx */
15728    else if (!strcasecmp("tx", a->argv[3]))
15729       tx = 1; /* tx */
15730    else
15731       return CLI_SHOWUSAGE;
15732 
15733    channel = atoi(a->argv[4]);
15734    gain = atof(a->argv[5]);
15735 
15736    ast_mutex_lock(&iflock);
15737    for (tmp = iflist; tmp; tmp = tmp->next) {
15738 
15739       if (tmp->channel != channel)
15740          continue;
15741 
15742       if (tmp->subs[SUB_REAL].dfd == -1)
15743          break;
15744 
15745       if (tx)
15746          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15747       else
15748          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15749 
15750       if (res) {
15751          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15752          ast_mutex_unlock(&iflock);
15753          return CLI_FAILURE;
15754       }
15755 
15756       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15757          tx ? "tx" : "rx", gain, channel);
15758       break;
15759    }
15760    ast_mutex_unlock(&iflock);
15761 
15762    if (tmp)
15763       return CLI_SUCCESS;
15764 
15765    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15766    return CLI_FAILURE;
15767 
15768 }
15769 
15770 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15771 {
15772    int channel;
15773    int on;
15774    struct dahdi_pvt *dahdi_chan = NULL;
15775 
15776    switch (cmd) {
15777    case CLI_INIT:
15778       e->command = "dahdi set dnd";
15779       e->usage =
15780          "Usage: dahdi set dnd <chan#> <on|off>\n"
15781          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15782          "  Changes take effect immediately.\n"
15783          "  <chan num> is the channel number\n"
15784          "  <on|off> Enable or disable DND mode?\n"
15785          ;
15786       return NULL;
15787    case CLI_GENERATE:
15788       return NULL;
15789    }
15790 
15791    if (a->argc != 5)
15792       return CLI_SHOWUSAGE;
15793 
15794    if ((channel = atoi(a->argv[3])) <= 0) {
15795       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15796       return CLI_SHOWUSAGE;
15797    }
15798 
15799    if (ast_true(a->argv[4]))
15800       on = 1;
15801    else if (ast_false(a->argv[4]))
15802       on = 0;
15803    else {
15804       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15805       return CLI_SHOWUSAGE;
15806    }
15807 
15808    ast_mutex_lock(&iflock);
15809    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15810       if (dahdi_chan->channel != channel)
15811          continue;
15812 
15813       /* Found the channel. Actually set it */
15814       dahdi_dnd(dahdi_chan, on);
15815       break;
15816    }
15817    ast_mutex_unlock(&iflock);
15818 
15819    if (!dahdi_chan) {
15820       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15821       return CLI_FAILURE;
15822    }
15823 
15824    return CLI_SUCCESS;
15825 }
15826 
15827 static struct ast_cli_entry dahdi_cli[] = {
15828    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15829    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15830    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15831    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15832    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15833    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15834    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15835    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15836    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15837    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15838 };
15839 
15840 #define TRANSFER  0
15841 #define HANGUP    1
15842 
15843 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15844 {
15845    if (p) {
15846       switch (mode) {
15847       case TRANSFER:
15848          p->fake_event = DAHDI_EVENT_WINKFLASH;
15849          break;
15850       case HANGUP:
15851          p->fake_event = DAHDI_EVENT_ONHOOK;
15852          break;
15853       default:
15854          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15855       }
15856    }
15857    return 0;
15858 }
15859 static struct dahdi_pvt *find_channel(int channel)
15860 {
15861    struct dahdi_pvt *p;
15862 
15863    ast_mutex_lock(&iflock);
15864    for (p = iflist; p; p = p->next) {
15865       if (p->channel == channel) {
15866          break;
15867       }
15868    }
15869    ast_mutex_unlock(&iflock);
15870    return p;
15871 }
15872 
15873 /*!
15874  * \internal
15875  * \brief Get private struct using given numeric channel string.
15876  *
15877  * \param channel Numeric channel number string get private struct.
15878  *
15879  * \retval pvt on success.
15880  * \retval NULL on error.
15881  */
15882 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15883 {
15884    int chan_num;
15885 
15886    if (sscanf(channel, "%30d", &chan_num) != 1) {
15887       /* Not numeric string. */
15888       return NULL;
15889    }
15890 
15891    return find_channel(chan_num);
15892 }
15893 
15894 static int action_dahdidndon(struct mansession *s, const struct message *m)
15895 {
15896    struct dahdi_pvt *p;
15897    const char *channel = astman_get_header(m, "DAHDIChannel");
15898 
15899    if (ast_strlen_zero(channel)) {
15900       astman_send_error(s, m, "No channel specified");
15901       return 0;
15902    }
15903    p = find_channel_from_str(channel);
15904    if (!p) {
15905       astman_send_error(s, m, "No such channel");
15906       return 0;
15907    }
15908    dahdi_dnd(p, 1);
15909    astman_send_ack(s, m, "DND Enabled");
15910    return 0;
15911 }
15912 
15913 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15914 {
15915    struct dahdi_pvt *p;
15916    const char *channel = astman_get_header(m, "DAHDIChannel");
15917 
15918    if (ast_strlen_zero(channel)) {
15919       astman_send_error(s, m, "No channel specified");
15920       return 0;
15921    }
15922    p = find_channel_from_str(channel);
15923    if (!p) {
15924       astman_send_error(s, m, "No such channel");
15925       return 0;
15926    }
15927    dahdi_dnd(p, 0);
15928    astman_send_ack(s, m, "DND Disabled");
15929    return 0;
15930 }
15931 
15932 static int action_transfer(struct mansession *s, const struct message *m)
15933 {
15934    struct dahdi_pvt *p;
15935    const char *channel = astman_get_header(m, "DAHDIChannel");
15936 
15937    if (ast_strlen_zero(channel)) {
15938       astman_send_error(s, m, "No channel specified");
15939       return 0;
15940    }
15941    p = find_channel_from_str(channel);
15942    if (!p) {
15943       astman_send_error(s, m, "No such channel");
15944       return 0;
15945    }
15946    if (!analog_lib_handles(p->sig, 0, 0)) {
15947       astman_send_error(s, m, "Channel signaling is not analog");
15948       return 0;
15949    }
15950    dahdi_fake_event(p,TRANSFER);
15951    astman_send_ack(s, m, "DAHDITransfer");
15952    return 0;
15953 }
15954 
15955 static int action_transferhangup(struct mansession *s, const struct message *m)
15956 {
15957    struct dahdi_pvt *p;
15958    const char *channel = astman_get_header(m, "DAHDIChannel");
15959 
15960    if (ast_strlen_zero(channel)) {
15961       astman_send_error(s, m, "No channel specified");
15962       return 0;
15963    }
15964    p = find_channel_from_str(channel);
15965    if (!p) {
15966       astman_send_error(s, m, "No such channel");
15967       return 0;
15968    }
15969    if (!analog_lib_handles(p->sig, 0, 0)) {
15970       astman_send_error(s, m, "Channel signaling is not analog");
15971       return 0;
15972    }
15973    dahdi_fake_event(p,HANGUP);
15974    astman_send_ack(s, m, "DAHDIHangup");
15975    return 0;
15976 }
15977 
15978 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15979 {
15980    struct dahdi_pvt *p;
15981    const char *channel = astman_get_header(m, "DAHDIChannel");
15982    const char *number = astman_get_header(m, "Number");
15983    int i;
15984 
15985    if (ast_strlen_zero(channel)) {
15986       astman_send_error(s, m, "No channel specified");
15987       return 0;
15988    }
15989    if (ast_strlen_zero(number)) {
15990       astman_send_error(s, m, "No number specified");
15991       return 0;
15992    }
15993    p = find_channel_from_str(channel);
15994    if (!p) {
15995       astman_send_error(s, m, "No such channel");
15996       return 0;
15997    }
15998    if (!p->owner) {
15999       astman_send_error(s, m, "Channel does not have it's owner");
16000       return 0;
16001    }
16002    for (i = 0; i < strlen(number); i++) {
16003       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16004       dahdi_queue_frame(p, &f);
16005    }
16006    astman_send_ack(s, m, "DAHDIDialOffhook");
16007    return 0;
16008 }
16009 
16010 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16011 {
16012    struct dahdi_pvt *tmp = NULL;
16013    const char *id = astman_get_header(m, "ActionID");
16014    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16015    char idText[256] = "";
16016    int channels = 0;
16017    int dahdichanquery;
16018 
16019    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16020       /* Not numeric string. */
16021       dahdichanquery = -1;
16022    }
16023 
16024    astman_send_ack(s, m, "DAHDI channel status will follow");
16025    if (!ast_strlen_zero(id))
16026       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16027 
16028    ast_mutex_lock(&iflock);
16029 
16030    for (tmp = iflist; tmp; tmp = tmp->next) {
16031       if (tmp->channel > 0) {
16032          int alm;
16033 
16034          /* If a specific channel is queried for, only deliver status for that channel */
16035          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16036             continue;
16037 
16038          alm = get_alarms(tmp);
16039          channels++;
16040          if (tmp->owner) {
16041             /* Add data if we have a current call */
16042             astman_append(s,
16043                "Event: DAHDIShowChannels\r\n"
16044                "DAHDIChannel: %d\r\n"
16045                "Channel: %s\r\n"
16046                "Uniqueid: %s\r\n"
16047                "AccountCode: %s\r\n"
16048                "Signalling: %s\r\n"
16049                "SignallingCode: %d\r\n"
16050                "Context: %s\r\n"
16051                "DND: %s\r\n"
16052                "Alarm: %s\r\n"
16053                "%s"
16054                "\r\n",
16055                tmp->channel,
16056                tmp->owner->name,
16057                tmp->owner->uniqueid,
16058                tmp->owner->accountcode,
16059                sig2str(tmp->sig),
16060                tmp->sig,
16061                tmp->context,
16062                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16063                alarm2str(alm), idText);
16064          } else {
16065             astman_append(s,
16066                "Event: DAHDIShowChannels\r\n"
16067                "DAHDIChannel: %d\r\n"
16068                "Signalling: %s\r\n"
16069                "SignallingCode: %d\r\n"
16070                "Context: %s\r\n"
16071                "DND: %s\r\n"
16072                "Alarm: %s\r\n"
16073                "%s"
16074                "\r\n",
16075                tmp->channel, sig2str(tmp->sig), tmp->sig,
16076                tmp->context,
16077                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16078                alarm2str(alm), idText);
16079          }
16080       }
16081    }
16082 
16083    ast_mutex_unlock(&iflock);
16084 
16085    astman_append(s,
16086       "Event: DAHDIShowChannelsComplete\r\n"
16087       "%s"
16088       "Items: %d\r\n"
16089       "\r\n",
16090       idText,
16091       channels);
16092    return 0;
16093 }
16094 
16095 #if defined(HAVE_SS7)
16096 static int linkset_addsigchan(int sigchan)
16097 {
16098    struct dahdi_ss7 *link;
16099    int res;
16100    int curfd;
16101    struct dahdi_params params;
16102    struct dahdi_bufferinfo bi;
16103    struct dahdi_spaninfo si;
16104 
16105    if (sigchan < 0) {
16106       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16107       return -1;
16108    }
16109    if (cur_ss7type < 0) {
16110       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16111       return -1;
16112    }
16113    if (cur_pointcode < 0) {
16114       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16115       return -1;
16116    }
16117    if (cur_adjpointcode < 0) {
16118       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16119       return -1;
16120    }
16121    if (cur_defaultdpc < 0) {
16122       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16123       return -1;
16124    }
16125    if (cur_networkindicator < 0) {
16126       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16127       return -1;
16128    }
16129    link = ss7_resolve_linkset(cur_linkset);
16130    if (!link) {
16131       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16132       return -1;
16133    }
16134    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16135       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16136       return -1;
16137    }
16138 
16139    curfd = link->ss7.numsigchans;
16140 
16141    /* Open signaling channel */
16142    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16143    if (link->ss7.fds[curfd] < 0) {
16144       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16145          strerror(errno));
16146       return -1;
16147    }
16148    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16149       dahdi_close_ss7_fd(link, curfd);
16150       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16151          strerror(errno));
16152       return -1;
16153    }
16154 
16155    /* Get signaling channel parameters */
16156    memset(&params, 0, sizeof(params));
16157    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16158    if (res) {
16159       dahdi_close_ss7_fd(link, curfd);
16160       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16161          strerror(errno));
16162       return -1;
16163    }
16164    if (params.sigtype != DAHDI_SIG_HDLCFCS
16165       && params.sigtype != DAHDI_SIG_HARDHDLC
16166       && params.sigtype != DAHDI_SIG_MTP2) {
16167       dahdi_close_ss7_fd(link, curfd);
16168       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16169       return -1;
16170    }
16171 
16172    /* Set signaling channel buffer policy. */
16173    memset(&bi, 0, sizeof(bi));
16174    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16175    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16176    bi.numbufs = 32;
16177    bi.bufsize = 512;
16178    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16179       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16180          sigchan, strerror(errno));
16181       dahdi_close_ss7_fd(link, curfd);
16182       return -1;
16183    }
16184 
16185    /* Get current signaling channel alarm status. */
16186    memset(&si, 0, sizeof(si));
16187    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16188    if (res) {
16189       dahdi_close_ss7_fd(link, curfd);
16190       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16191          strerror(errno));
16192    }
16193 
16194    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16195       (params.sigtype == DAHDI_SIG_MTP2)
16196          ? SS7_TRANSPORT_DAHDIMTP2
16197          : SS7_TRANSPORT_DAHDIDCHAN,
16198       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16199    if (res) {
16200       dahdi_close_ss7_fd(link, curfd);
16201       return -1;
16202    }
16203 
16204    ++link->ss7.numsigchans;
16205 
16206    return 0;
16207 }
16208 #endif   /* defined(HAVE_SS7) */
16209 
16210 #if defined(HAVE_SS7)
16211 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16212 {
16213    int span;
16214    switch (cmd) {
16215    case CLI_INIT:
16216       e->command = "ss7 set debug {on|off} linkset";
16217       e->usage =
16218          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16219          "       Enables debugging on a given SS7 linkset\n";
16220       return NULL;
16221    case CLI_GENERATE:
16222       return NULL;
16223    }
16224    if (a->argc < 6)
16225       return CLI_SHOWUSAGE;
16226    span = atoi(a->argv[5]);
16227    if ((span < 1) || (span > NUM_SPANS)) {
16228       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16229       return CLI_SUCCESS;
16230    }
16231    if (!linksets[span-1].ss7.ss7) {
16232       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16233    } else {
16234       if (!strcasecmp(a->argv[3], "on")) {
16235          linksets[span - 1].ss7.debug = 1;
16236          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16237          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16238       } else {
16239          linksets[span - 1].ss7.debug = 0;
16240          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16241          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16242       }
16243    }
16244 
16245    return CLI_SUCCESS;
16246 }
16247 #endif   /* defined(HAVE_SS7) */
16248 
16249 #if defined(HAVE_SS7)
16250 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16251 {
16252    int linkset, cic;
16253    int blocked = -1, i;
16254    switch (cmd) {
16255    case CLI_INIT:
16256       e->command = "ss7 block cic";
16257       e->usage =
16258          "Usage: ss7 block cic <linkset> <CIC>\n"
16259          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16260       return NULL;
16261    case CLI_GENERATE:
16262       return NULL;
16263    }
16264    if (a->argc == 5)
16265       linkset = atoi(a->argv[3]);
16266    else
16267       return CLI_SHOWUSAGE;
16268 
16269    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16270       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16271       return CLI_SUCCESS;
16272    }
16273 
16274    if (!linksets[linkset-1].ss7.ss7) {
16275       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16276       return CLI_SUCCESS;
16277    }
16278 
16279    cic = atoi(a->argv[4]);
16280 
16281    if (cic < 1) {
16282       ast_cli(a->fd, "Invalid CIC specified!\n");
16283       return CLI_SUCCESS;
16284    }
16285 
16286    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16287       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16288          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16289          if (!blocked) {
16290             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16291             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16292             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16293          }
16294       }
16295    }
16296 
16297    if (blocked < 0) {
16298       ast_cli(a->fd, "Invalid CIC specified!\n");
16299       return CLI_SUCCESS;
16300    }
16301 
16302    if (!blocked)
16303       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16304    else
16305       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16306 
16307    /* Break poll on the linkset so it sends our messages */
16308    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16309 
16310    return CLI_SUCCESS;
16311 }
16312 #endif   /* defined(HAVE_SS7) */
16313 
16314 #if defined(HAVE_SS7)
16315 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16316 {
16317    int linkset;
16318    int i;
16319    switch (cmd) {
16320    case CLI_INIT:
16321       e->command = "ss7 block linkset";
16322       e->usage =
16323          "Usage: ss7 block linkset <linkset number>\n"
16324          "       Sends a remote blocking request for all CICs on the given linkset\n";
16325       return NULL;
16326    case CLI_GENERATE:
16327       return NULL;
16328    }
16329    if (a->argc == 4)
16330       linkset = atoi(a->argv[3]);
16331    else
16332       return CLI_SHOWUSAGE;
16333 
16334    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16335       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16336       return CLI_SUCCESS;
16337    }
16338 
16339    if (!linksets[linkset-1].ss7.ss7) {
16340       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16341       return CLI_SUCCESS;
16342    }
16343 
16344    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16345       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16346       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16347       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16348       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16349    }
16350 
16351    /* Break poll on the linkset so it sends our messages */
16352    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16353 
16354    return CLI_SUCCESS;
16355 }
16356 #endif   /* defined(HAVE_SS7) */
16357 
16358 #if defined(HAVE_SS7)
16359 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16360 {
16361    int linkset, cic;
16362    int i, blocked = -1;
16363    switch (cmd) {
16364    case CLI_INIT:
16365       e->command = "ss7 unblock cic";
16366       e->usage =
16367          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16368          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16369       return NULL;
16370    case CLI_GENERATE:
16371       return NULL;
16372    }
16373 
16374    if (a->argc == 5)
16375       linkset = atoi(a->argv[3]);
16376    else
16377       return CLI_SHOWUSAGE;
16378 
16379    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16380       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16381       return CLI_SUCCESS;
16382    }
16383 
16384    if (!linksets[linkset-1].ss7.ss7) {
16385       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16386       return CLI_SUCCESS;
16387    }
16388 
16389    cic = atoi(a->argv[4]);
16390 
16391    if (cic < 1) {
16392       ast_cli(a->fd, "Invalid CIC specified!\n");
16393       return CLI_SUCCESS;
16394    }
16395 
16396    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16397       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16398          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16399          if (blocked) {
16400             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16401             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16402             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16403          }
16404       }
16405    }
16406 
16407    if (blocked > 0)
16408       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16409 
16410    /* Break poll on the linkset so it sends our messages */
16411    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16412 
16413    return CLI_SUCCESS;
16414 }
16415 #endif   /* defined(HAVE_SS7) */
16416 
16417 #if defined(HAVE_SS7)
16418 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16419 {
16420    int linkset;
16421    int i;
16422    switch (cmd) {
16423    case CLI_INIT:
16424       e->command = "ss7 unblock linkset";
16425       e->usage =
16426          "Usage: ss7 unblock linkset <linkset number>\n"
16427          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16428       return NULL;
16429    case CLI_GENERATE:
16430       return NULL;
16431    }
16432 
16433    if (a->argc == 4)
16434       linkset = atoi(a->argv[3]);
16435    else
16436       return CLI_SHOWUSAGE;
16437 
16438    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16439       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16440       return CLI_SUCCESS;
16441    }
16442 
16443    if (!linksets[linkset-1].ss7.ss7) {
16444       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16445       return CLI_SUCCESS;
16446    }
16447 
16448    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16449       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16450       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16451       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16452       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16453    }
16454 
16455    /* Break poll on the linkset so it sends our messages */
16456    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16457 
16458    return CLI_SUCCESS;
16459 }
16460 #endif   /* defined(HAVE_SS7) */
16461 
16462 #if defined(HAVE_SS7)
16463 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16464 {
16465    int linkset;
16466    struct sig_ss7_linkset *ss7;
16467    switch (cmd) {
16468    case CLI_INIT:
16469       e->command = "ss7 show linkset";
16470       e->usage =
16471          "Usage: ss7 show linkset <span>\n"
16472          "       Shows the status of an SS7 linkset.\n";
16473       return NULL;
16474    case CLI_GENERATE:
16475       return NULL;
16476    }
16477 
16478    if (a->argc < 4)
16479       return CLI_SHOWUSAGE;
16480    linkset = atoi(a->argv[3]);
16481    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16482       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16483       return CLI_SUCCESS;
16484    }
16485    ss7 = &linksets[linkset - 1].ss7;
16486    if (!ss7->ss7) {
16487       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16488       return CLI_SUCCESS;
16489    }
16490 
16491    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16492 
16493    return CLI_SUCCESS;
16494 }
16495 #endif   /* defined(HAVE_SS7) */
16496 
16497 #if defined(HAVE_SS7)
16498 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16499 {
16500    int linkset;
16501 
16502    switch (cmd) {
16503    case CLI_INIT:
16504       e->command = "ss7 show channels";
16505       e->usage =
16506          "Usage: ss7 show channels\n"
16507          "       Displays SS7 channel information at a glance.\n";
16508       return NULL;
16509    case CLI_GENERATE:
16510       return NULL;
16511    }
16512 
16513    if (a->argc != 3)
16514       return CLI_SHOWUSAGE;
16515 
16516    sig_ss7_cli_show_channels_header(a->fd);
16517    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16518       if (linksets[linkset].ss7.ss7) {
16519          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16520       }
16521    }
16522    return CLI_SUCCESS;
16523 }
16524 #endif   /* defined(HAVE_SS7) */
16525 
16526 #if defined(HAVE_SS7)
16527 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16528 {
16529    switch (cmd) {
16530    case CLI_INIT:
16531       e->command = "ss7 show version";
16532       e->usage =
16533          "Usage: ss7 show version\n"
16534          "  Show the libss7 version\n";
16535       return NULL;
16536    case CLI_GENERATE:
16537       return NULL;
16538    }
16539 
16540    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16541 
16542    return CLI_SUCCESS;
16543 }
16544 #endif   /* defined(HAVE_SS7) */
16545 
16546 #if defined(HAVE_SS7)
16547 static struct ast_cli_entry dahdi_ss7_cli[] = {
16548    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16549    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16550    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16551    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16552    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16553    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16554    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16555    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16556 };
16557 #endif   /* defined(HAVE_SS7) */
16558 
16559 #if defined(HAVE_PRI)
16560 #if defined(HAVE_PRI_CCSS)
16561 /*!
16562  * \internal
16563  * \brief CC agent initialization.
16564  * \since 1.8
16565  *
16566  * \param agent CC core agent control.
16567  * \param chan Original channel the agent will attempt to recall.
16568  *
16569  * \details
16570  * This callback is called when the CC core is initialized.  Agents should allocate
16571  * any private data necessary for the call and assign it to the private_data
16572  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16573  * specific agent type, they should be set in this function as well.
16574  *
16575  * \retval 0 on success.
16576  * \retval -1 on error.
16577  */
16578 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16579 {
16580    struct dahdi_pvt *pvt;
16581    struct sig_pri_chan *pvt_chan;
16582    int res;
16583 
16584    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16585 
16586    pvt = chan->tech_pvt;
16587    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16588       pvt_chan = pvt->sig_pvt;
16589    } else {
16590       pvt_chan = NULL;
16591    }
16592    if (!pvt_chan) {
16593       return -1;
16594    }
16595 
16596    ast_module_ref(ast_module_info->self);
16597 
16598    res = sig_pri_cc_agent_init(agent, pvt_chan);
16599    if (res) {
16600       ast_module_unref(ast_module_info->self);
16601    }
16602    return res;
16603 }
16604 #endif   /* defined(HAVE_PRI_CCSS) */
16605 #endif   /* defined(HAVE_PRI) */
16606 
16607 #if defined(HAVE_PRI)
16608 #if defined(HAVE_PRI_CCSS)
16609 /*!
16610  * \internal
16611  * \brief Destroy private data on the agent.
16612  * \since 1.8
16613  *
16614  * \param agent CC core agent control.
16615  *
16616  * \details
16617  * The core will call this function upon completion
16618  * or failure of CC.
16619  *
16620  * \return Nothing
16621  */
16622 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16623 {
16624    sig_pri_cc_agent_destructor(agent);
16625 
16626    ast_module_unref(ast_module_info->self);
16627 }
16628 #endif   /* defined(HAVE_PRI_CCSS) */
16629 #endif   /* defined(HAVE_PRI) */
16630 
16631 #if defined(HAVE_PRI)
16632 #if defined(HAVE_PRI_CCSS)
16633 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16634    .type = dahdi_pri_cc_type,
16635    .init = dahdi_pri_cc_agent_init,
16636    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16637    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16638    .respond = sig_pri_cc_agent_req_rsp,
16639    .status_request = sig_pri_cc_agent_status_req,
16640    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16641    .party_b_free = sig_pri_cc_agent_party_b_free,
16642    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16643    .callee_available = sig_pri_cc_agent_callee_available,
16644    .destructor = dahdi_pri_cc_agent_destructor,
16645 };
16646 #endif   /* defined(HAVE_PRI_CCSS) */
16647 #endif   /* defined(HAVE_PRI) */
16648 
16649 #if defined(HAVE_PRI)
16650 #if defined(HAVE_PRI_CCSS)
16651 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16652    .type = dahdi_pri_cc_type,
16653    .request_cc = sig_pri_cc_monitor_req_cc,
16654    .suspend = sig_pri_cc_monitor_suspend,
16655    .unsuspend = sig_pri_cc_monitor_unsuspend,
16656    .status_response = sig_pri_cc_monitor_status_rsp,
16657    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16658    .destructor = sig_pri_cc_monitor_destructor,
16659 };
16660 #endif   /* defined(HAVE_PRI_CCSS) */
16661 #endif   /* defined(HAVE_PRI) */
16662 
16663 static int __unload_module(void)
16664 {
16665    struct dahdi_pvt *p;
16666 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16667    int i, j;
16668 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16669 
16670 #ifdef HAVE_PRI
16671    for (i = 0; i < NUM_SPANS; i++) {
16672       if (pris[i].pri.master != AST_PTHREADT_NULL)
16673          pthread_cancel(pris[i].pri.master);
16674    }
16675    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16676    ast_unregister_application(dahdi_send_keypad_facility_app);
16677 #ifdef HAVE_PRI_PROG_W_CAUSE
16678    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16679 #endif
16680 #endif
16681 #if defined(HAVE_SS7)
16682    for (i = 0; i < NUM_SPANS; i++) {
16683       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16684          pthread_cancel(linksets[i].ss7.master);
16685       }
16686    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16687 #endif   /* defined(HAVE_SS7) */
16688 #if defined(HAVE_OPENR2)
16689    dahdi_r2_destroy_links();
16690    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16691    ast_unregister_application(dahdi_accept_r2_call_app);
16692 #endif
16693 
16694    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16695    ast_manager_unregister("DAHDIDialOffhook");
16696    ast_manager_unregister("DAHDIHangup");
16697    ast_manager_unregister("DAHDITransfer");
16698    ast_manager_unregister("DAHDIDNDoff");
16699    ast_manager_unregister("DAHDIDNDon");
16700    ast_manager_unregister("DAHDIShowChannels");
16701    ast_manager_unregister("DAHDIRestart");
16702    ast_data_unregister(NULL);
16703    ast_channel_unregister(&dahdi_tech);
16704 
16705    /* Hangup all interfaces if they have an owner */
16706    ast_mutex_lock(&iflock);
16707    for (p = iflist; p; p = p->next) {
16708       if (p->owner)
16709          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16710    }
16711    ast_mutex_unlock(&iflock);
16712 
16713    ast_mutex_lock(&monlock);
16714    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16715       pthread_cancel(monitor_thread);
16716       pthread_kill(monitor_thread, SIGURG);
16717       pthread_join(monitor_thread, NULL);
16718    }
16719    monitor_thread = AST_PTHREADT_STOP;
16720    ast_mutex_unlock(&monlock);
16721 
16722    destroy_all_channels();
16723 
16724 #if defined(HAVE_PRI)
16725    for (i = 0; i < NUM_SPANS; i++) {
16726       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16727          pthread_join(pris[i].pri.master, NULL);
16728       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16729          dahdi_close_pri_fd(&(pris[i]), j);
16730       }
16731       sig_pri_stop_pri(&pris[i].pri);
16732    }
16733 #if defined(HAVE_PRI_CCSS)
16734    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16735    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16736 #endif   /* defined(HAVE_PRI_CCSS) */
16737    sig_pri_unload();
16738 #endif
16739 
16740 #if defined(HAVE_SS7)
16741    for (i = 0; i < NUM_SPANS; i++) {
16742       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16743          pthread_join(linksets[i].ss7.master, NULL);
16744       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16745          dahdi_close_ss7_fd(&(linksets[i]), j);
16746       }
16747    }
16748 #endif   /* defined(HAVE_SS7) */
16749    ast_cond_destroy(&ss_thread_complete);
16750    return 0;
16751 }
16752 
16753 static int unload_module(void)
16754 {
16755 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16756    int y;
16757 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16758 #ifdef HAVE_PRI
16759    for (y = 0; y < NUM_SPANS; y++)
16760       ast_mutex_destroy(&pris[y].pri.lock);
16761 #endif
16762 #if defined(HAVE_SS7)
16763    for (y = 0; y < NUM_SPANS; y++)
16764       ast_mutex_destroy(&linksets[y].ss7.lock);
16765 #endif   /* defined(HAVE_SS7) */
16766    return __unload_module();
16767 }
16768 
16769 static void string_replace(char *str, int char1, int char2)
16770 {
16771    for (; *str; str++) {
16772       if (*str == char1) {
16773          *str = char2;
16774       }
16775    }
16776 }
16777 
16778 static char *parse_spanchan(char *chanstr, char **subdir)
16779 {
16780    char *p;
16781 
16782    if ((p = strrchr(chanstr, '!')) == NULL) {
16783       *subdir = NULL;
16784       return chanstr;
16785    }
16786    *p++ = '\0';
16787    string_replace(chanstr, '!', '/');
16788    *subdir = chanstr;
16789    return p;
16790 }
16791 
16792 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16793 {
16794    char *c, *chan;
16795    char *subdir;
16796    int x, start, finish;
16797    struct dahdi_pvt *tmp;
16798 
16799    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16800       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16801       return -1;
16802    }
16803 
16804    c = ast_strdupa(value);
16805    c = parse_spanchan(c, &subdir);
16806 
16807    while ((chan = strsep(&c, ","))) {
16808       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16809          /* Range */
16810       } else if (sscanf(chan, "%30d", &start)) {
16811          /* Just one */
16812          finish = start;
16813       } else if (!strcasecmp(chan, "pseudo")) {
16814          finish = start = CHAN_PSEUDO;
16815          if (found_pseudo)
16816             *found_pseudo = 1;
16817       } else {
16818          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16819          return -1;
16820       }
16821       if (finish < start) {
16822          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16823          x = finish;
16824          finish = start;
16825          start = x;
16826       }
16827 
16828       for (x = start; x <= finish; x++) {
16829          char fn[PATH_MAX];
16830          int real_channel = x;
16831 
16832          if (!ast_strlen_zero(subdir)) {
16833             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16834             if (real_channel < 0) {
16835                if (conf->ignore_failed_channels) {
16836                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16837                         subdir, x, real_channel);
16838                   continue;
16839                } else {
16840                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16841                         subdir, x, real_channel);
16842                   return -1;
16843                }
16844             }
16845          }
16846          tmp = mkintf(real_channel, conf, reload);
16847 
16848          if (tmp) {
16849             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16850          } else {
16851             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16852                   (reload == 1) ? "reconfigure" : "register", value);
16853             return -1;
16854          }
16855       }
16856    }
16857 
16858    return 0;
16859 }
16860 
16861 /** The length of the parameters list of 'dahdichan'.
16862  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16863 #define MAX_CHANLIST_LEN 80
16864 
16865 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16866 {
16867    char *parse = ast_strdupa(data);
16868    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16869    unsigned int param_count;
16870    unsigned int x;
16871 
16872    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16873       return;
16874 
16875    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16876 
16877    /* first parameter is tap length, process it here */
16878 
16879    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16880 
16881    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16882       confp->chan.echocancel.head.tap_length = x;
16883    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16884       confp->chan.echocancel.head.tap_length = 128;
16885 
16886    /* now process any remaining parameters */
16887 
16888    for (x = 1; x < param_count; x++) {
16889       struct {
16890          char *name;
16891          char *value;
16892       } param;
16893 
16894       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16895          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16896          continue;
16897       }
16898 
16899       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16900          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16901          continue;
16902       }
16903 
16904       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16905 
16906       if (param.value) {
16907          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16908             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16909             continue;
16910          }
16911       }
16912       confp->chan.echocancel.head.param_count++;
16913    }
16914 }
16915 
16916 /*! process_dahdi() - ignore keyword 'channel' and similar */
16917 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16918 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16919 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16920 
16921 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16922 {
16923    struct dahdi_pvt *tmp;
16924    int y;
16925    int found_pseudo = 0;
16926    struct ast_variable *dahdichan = NULL;
16927 
16928    for (; v; v = v->next) {
16929       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16930          continue;
16931 
16932       /* Create the interface list */
16933       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16934          if (options & PROC_DAHDI_OPT_NOCHAN) {
16935             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16936             continue;
16937          }
16938          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16939             if (confp->ignore_failed_channels) {
16940                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16941                continue;
16942             } else {
16943                return -1;
16944             }
16945          }
16946          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16947       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16948          confp->ignore_failed_channels = ast_true(v->value);
16949       } else if (!strcasecmp(v->name, "buffers")) {
16950          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16951             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16952             confp->chan.buf_no = numbufs;
16953             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16954          }
16955       } else if (!strcasecmp(v->name, "faxbuffers")) {
16956          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16957             confp->chan.usefaxbuffers = 1;
16958          }
16959       } else if (!strcasecmp(v->name, "dahdichan")) {
16960          /* Only process the last dahdichan value. */
16961          dahdichan = v;
16962       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16963          usedistinctiveringdetection = ast_true(v->value);
16964       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16965          distinctiveringaftercid = ast_true(v->value);
16966       } else if (!strcasecmp(v->name, "dring1context")) {
16967          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16968       } else if (!strcasecmp(v->name, "dring2context")) {
16969          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16970       } else if (!strcasecmp(v->name, "dring3context")) {
16971          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16972       } else if (!strcasecmp(v->name, "dring1range")) {
16973          confp->chan.drings.ringnum[0].range = atoi(v->value);
16974       } else if (!strcasecmp(v->name, "dring2range")) {
16975          confp->chan.drings.ringnum[1].range = atoi(v->value);
16976       } else if (!strcasecmp(v->name, "dring3range")) {
16977          confp->chan.drings.ringnum[2].range = atoi(v->value);
16978       } else if (!strcasecmp(v->name, "dring1")) {
16979          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]);
16980       } else if (!strcasecmp(v->name, "dring2")) {
16981          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]);
16982       } else if (!strcasecmp(v->name, "dring3")) {
16983          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]);
16984       } else if (!strcasecmp(v->name, "usecallerid")) {
16985          confp->chan.use_callerid = ast_true(v->value);
16986       } else if (!strcasecmp(v->name, "cidsignalling")) {
16987          if (!strcasecmp(v->value, "bell"))
16988             confp->chan.cid_signalling = CID_SIG_BELL;
16989          else if (!strcasecmp(v->value, "v23"))
16990             confp->chan.cid_signalling = CID_SIG_V23;
16991          else if (!strcasecmp(v->value, "dtmf"))
16992             confp->chan.cid_signalling = CID_SIG_DTMF;
16993          else if (!strcasecmp(v->value, "smdi"))
16994             confp->chan.cid_signalling = CID_SIG_SMDI;
16995          else if (!strcasecmp(v->value, "v23_jp"))
16996             confp->chan.cid_signalling = CID_SIG_V23_JP;
16997          else if (ast_true(v->value))
16998             confp->chan.cid_signalling = CID_SIG_BELL;
16999       } else if (!strcasecmp(v->name, "cidstart")) {
17000          if (!strcasecmp(v->value, "ring"))
17001             confp->chan.cid_start = CID_START_RING;
17002          else if (!strcasecmp(v->value, "polarity_in"))
17003             confp->chan.cid_start = CID_START_POLARITY_IN;
17004          else if (!strcasecmp(v->value, "polarity"))
17005             confp->chan.cid_start = CID_START_POLARITY;
17006          else if (!strcasecmp(v->value, "dtmf"))
17007             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17008          else if (ast_true(v->value))
17009             confp->chan.cid_start = CID_START_RING;
17010       } else if (!strcasecmp(v->name, "threewaycalling")) {
17011          confp->chan.threewaycalling = ast_true(v->value);
17012       } else if (!strcasecmp(v->name, "cancallforward")) {
17013          confp->chan.cancallforward = ast_true(v->value);
17014       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17015          if (ast_true(v->value))
17016             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17017          else
17018             confp->chan.dtmfrelax = 0;
17019       } else if (!strcasecmp(v->name, "mailbox")) {
17020          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17021       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17022          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17023             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17024          }
17025       } else if (!strcasecmp(v->name, "adsi")) {
17026          confp->chan.adsi = ast_true(v->value);
17027       } else if (!strcasecmp(v->name, "usesmdi")) {
17028          confp->chan.use_smdi = ast_true(v->value);
17029       } else if (!strcasecmp(v->name, "smdiport")) {
17030          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17031       } else if (!strcasecmp(v->name, "transfer")) {
17032          confp->chan.transfer = ast_true(v->value);
17033       } else if (!strcasecmp(v->name, "canpark")) {
17034          confp->chan.canpark = ast_true(v->value);
17035       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17036          confp->chan.echocanbridged = ast_true(v->value);
17037       } else if (!strcasecmp(v->name, "busydetect")) {
17038          confp->chan.busydetect = ast_true(v->value);
17039       } else if (!strcasecmp(v->name, "busycount")) {
17040          confp->chan.busycount = atoi(v->value);
17041       } else if (!strcasecmp(v->name, "busypattern")) {
17042          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17043             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17044          }
17045       } else if (!strcasecmp(v->name, "callprogress")) {
17046          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17047          if (ast_true(v->value))
17048             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17049       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17050          confp->chan.waitfordialtone = atoi(v->value);
17051       } else if (!strcasecmp(v->name, "faxdetect")) {
17052          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17053          if (!strcasecmp(v->value, "incoming")) {
17054             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17055          } else if (!strcasecmp(v->value, "outgoing")) {
17056             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17057          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17058             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17059       } else if (!strcasecmp(v->name, "echocancel")) {
17060          process_echocancel(confp, v->value, v->lineno);
17061       } else if (!strcasecmp(v->name, "echotraining")) {
17062          if (sscanf(v->value, "%30d", &y) == 1) {
17063             if ((y < 10) || (y > 4000)) {
17064                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17065             } else {
17066                confp->chan.echotraining = y;
17067             }
17068          } else if (ast_true(v->value)) {
17069             confp->chan.echotraining = 400;
17070          } else
17071             confp->chan.echotraining = 0;
17072       } else if (!strcasecmp(v->name, "hidecallerid")) {
17073          confp->chan.hidecallerid = ast_true(v->value);
17074       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17075          confp->chan.hidecalleridname = ast_true(v->value);
17076       } else if (!strcasecmp(v->name, "pulsedial")) {
17077          confp->chan.pulse = ast_true(v->value);
17078       } else if (!strcasecmp(v->name, "callreturn")) {
17079          confp->chan.callreturn = ast_true(v->value);
17080       } else if (!strcasecmp(v->name, "callwaiting")) {
17081          confp->chan.callwaiting = ast_true(v->value);
17082       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17083          confp->chan.callwaitingcallerid = ast_true(v->value);
17084       } else if (!strcasecmp(v->name, "context")) {
17085          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17086       } else if (!strcasecmp(v->name, "language")) {
17087          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17088       } else if (!strcasecmp(v->name, "progzone")) {
17089          ast_copy_string(progzone, v->value, sizeof(progzone));
17090       } else if (!strcasecmp(v->name, "mohinterpret")
17091          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17092          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17093       } else if (!strcasecmp(v->name, "mohsuggest")) {
17094          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17095       } else if (!strcasecmp(v->name, "parkinglot")) {
17096          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17097       } else if (!strcasecmp(v->name, "stripmsd")) {
17098          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17099          confp->chan.stripmsd = atoi(v->value);
17100       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17101          numbufs = atoi(v->value);
17102       } else if (!strcasecmp(v->name, "group")) {
17103          confp->chan.group = ast_get_group(v->value);
17104       } else if (!strcasecmp(v->name, "callgroup")) {
17105          if (!strcasecmp(v->value, "none"))
17106             confp->chan.callgroup = 0;
17107          else
17108             confp->chan.callgroup = ast_get_group(v->value);
17109       } else if (!strcasecmp(v->name, "pickupgroup")) {
17110          if (!strcasecmp(v->value, "none"))
17111             confp->chan.pickupgroup = 0;
17112          else
17113             confp->chan.pickupgroup = ast_get_group(v->value);
17114       } else if (!strcasecmp(v->name, "setvar")) {
17115          char *varname = ast_strdupa(v->value), *varval = NULL;
17116          struct ast_variable *tmpvar;
17117          if (varname && (varval = strchr(varname, '='))) {
17118             *varval++ = '\0';
17119             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17120                tmpvar->next = confp->chan.vars;
17121                confp->chan.vars = tmpvar;
17122             }
17123          }
17124       } else if (!strcasecmp(v->name, "immediate")) {
17125          confp->chan.immediate = ast_true(v->value);
17126       } else if (!strcasecmp(v->name, "transfertobusy")) {
17127          confp->chan.transfertobusy = ast_true(v->value);
17128       } else if (!strcasecmp(v->name, "mwimonitor")) {
17129          confp->chan.mwimonitor_neon = 0;
17130          confp->chan.mwimonitor_fsk = 0;
17131          confp->chan.mwimonitor_rpas = 0;
17132          if (strcasestr(v->value, "fsk")) {
17133             confp->chan.mwimonitor_fsk = 1;
17134          }
17135          if (strcasestr(v->value, "rpas")) {
17136             confp->chan.mwimonitor_rpas = 1;
17137          }
17138          if (strcasestr(v->value, "neon")) {
17139             confp->chan.mwimonitor_neon = 1;
17140          }
17141          /* If set to true or yes, assume that simple fsk is desired */
17142          if (ast_true(v->value)) {
17143             confp->chan.mwimonitor_fsk = 1;
17144          }
17145       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17146          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17147             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17148          }
17149       } else if (!strcasecmp(v->name, "rxgain")) {
17150          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17151             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17152          }
17153       } else if (!strcasecmp(v->name, "txgain")) {
17154          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17155             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17156          }
17157       } else if (!strcasecmp(v->name, "txdrc")) {
17158          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17159             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17160          }
17161       } else if (!strcasecmp(v->name, "rxdrc")) {
17162          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17163             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17164          }
17165       } else if (!strcasecmp(v->name, "tonezone")) {
17166          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17167             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17168          }
17169       } else if (!strcasecmp(v->name, "callerid")) {
17170          if (!strcasecmp(v->value, "asreceived")) {
17171             confp->chan.cid_num[0] = '\0';
17172             confp->chan.cid_name[0] = '\0';
17173          } else {
17174             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17175          }
17176       } else if (!strcasecmp(v->name, "fullname")) {
17177          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17178       } else if (!strcasecmp(v->name, "cid_number")) {
17179          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17180       } else if (!strcasecmp(v->name, "cid_tag")) {
17181          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17182       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17183          confp->chan.dahditrcallerid = ast_true(v->value);
17184       } else if (!strcasecmp(v->name, "restrictcid")) {
17185          confp->chan.restrictcid = ast_true(v->value);
17186       } else if (!strcasecmp(v->name, "usecallingpres")) {
17187          confp->chan.use_callingpres = ast_true(v->value);
17188       } else if (!strcasecmp(v->name, "accountcode")) {
17189          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17190       } else if (!strcasecmp(v->name, "amaflags")) {
17191          y = ast_cdr_amaflags2int(v->value);
17192          if (y < 0)
17193             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17194          else
17195             confp->chan.amaflags = y;
17196       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17197          confp->chan.polarityonanswerdelay = atoi(v->value);
17198       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17199          confp->chan.answeronpolarityswitch = ast_true(v->value);
17200       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17201          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17202       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17203          confp->chan.sendcalleridafter = atoi(v->value);
17204       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17205          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17206       } else if (ast_cc_is_config_param(v->name)) {
17207          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17208       } else if (!strcasecmp(v->name, "mwisendtype")) {
17209 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17210          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17211             mwisend_rpas = 1;
17212          } else {
17213             mwisend_rpas = 0;
17214          }
17215 #else
17216          /* Default is fsk, to turn it off you must specify nofsk */
17217          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17218          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17219             confp->chan.mwisend_fsk = 0;
17220          } else {             /* Default FSK */
17221             confp->chan.mwisend_fsk = 1;
17222          }
17223          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17224             confp->chan.mwisend_rpas = 1;
17225          } else {
17226             confp->chan.mwisend_rpas = 0;
17227          }
17228          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17229             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17230          }
17231          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17232             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17233          }
17234          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17235             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17236          }
17237 #endif
17238       } else if (reload != 1) {
17239           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17240             int orig_radio = confp->chan.radio;
17241             int orig_outsigmod = confp->chan.outsigmod;
17242             int orig_auto = confp->is_sig_auto;
17243 
17244             confp->chan.radio = 0;
17245             confp->chan.outsigmod = -1;
17246             confp->is_sig_auto = 0;
17247             if (!strcasecmp(v->value, "em")) {
17248                confp->chan.sig = SIG_EM;
17249             } else if (!strcasecmp(v->value, "em_e1")) {
17250                confp->chan.sig = SIG_EM_E1;
17251             } else if (!strcasecmp(v->value, "em_w")) {
17252                confp->chan.sig = SIG_EMWINK;
17253             } else if (!strcasecmp(v->value, "fxs_ls")) {
17254                confp->chan.sig = SIG_FXSLS;
17255             } else if (!strcasecmp(v->value, "fxs_gs")) {
17256                confp->chan.sig = SIG_FXSGS;
17257             } else if (!strcasecmp(v->value, "fxs_ks")) {
17258                confp->chan.sig = SIG_FXSKS;
17259             } else if (!strcasecmp(v->value, "fxo_ls")) {
17260                confp->chan.sig = SIG_FXOLS;
17261             } else if (!strcasecmp(v->value, "fxo_gs")) {
17262                confp->chan.sig = SIG_FXOGS;
17263             } else if (!strcasecmp(v->value, "fxo_ks")) {
17264                confp->chan.sig = SIG_FXOKS;
17265             } else if (!strcasecmp(v->value, "fxs_rx")) {
17266                confp->chan.sig = SIG_FXSKS;
17267                confp->chan.radio = 1;
17268             } else if (!strcasecmp(v->value, "fxo_rx")) {
17269                confp->chan.sig = SIG_FXOLS;
17270                confp->chan.radio = 1;
17271             } else if (!strcasecmp(v->value, "fxs_tx")) {
17272                confp->chan.sig = SIG_FXSLS;
17273                confp->chan.radio = 1;
17274             } else if (!strcasecmp(v->value, "fxo_tx")) {
17275                confp->chan.sig = SIG_FXOGS;
17276                confp->chan.radio = 1;
17277             } else if (!strcasecmp(v->value, "em_rx")) {
17278                confp->chan.sig = SIG_EM;
17279                confp->chan.radio = 1;
17280             } else if (!strcasecmp(v->value, "em_tx")) {
17281                confp->chan.sig = SIG_EM;
17282                confp->chan.radio = 1;
17283             } else if (!strcasecmp(v->value, "em_rxtx")) {
17284                confp->chan.sig = SIG_EM;
17285                confp->chan.radio = 2;
17286             } else if (!strcasecmp(v->value, "em_txrx")) {
17287                confp->chan.sig = SIG_EM;
17288                confp->chan.radio = 2;
17289             } else if (!strcasecmp(v->value, "sf")) {
17290                confp->chan.sig = SIG_SF;
17291             } else if (!strcasecmp(v->value, "sf_w")) {
17292                confp->chan.sig = SIG_SFWINK;
17293             } else if (!strcasecmp(v->value, "sf_featd")) {
17294                confp->chan.sig = SIG_FEATD;
17295             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17296                confp->chan.sig = SIG_FEATDMF;
17297             } else if (!strcasecmp(v->value, "sf_featb")) {
17298                confp->chan.sig = SIG_SF_FEATB;
17299             } else if (!strcasecmp(v->value, "sf")) {
17300                confp->chan.sig = SIG_SF;
17301             } else if (!strcasecmp(v->value, "sf_rx")) {
17302                confp->chan.sig = SIG_SF;
17303                confp->chan.radio = 1;
17304             } else if (!strcasecmp(v->value, "sf_tx")) {
17305                confp->chan.sig = SIG_SF;
17306                confp->chan.radio = 1;
17307             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17308                confp->chan.sig = SIG_SF;
17309                confp->chan.radio = 2;
17310             } else if (!strcasecmp(v->value, "sf_txrx")) {
17311                confp->chan.sig = SIG_SF;
17312                confp->chan.radio = 2;
17313             } else if (!strcasecmp(v->value, "featd")) {
17314                confp->chan.sig = SIG_FEATD;
17315             } else if (!strcasecmp(v->value, "featdmf")) {
17316                confp->chan.sig = SIG_FEATDMF;
17317             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17318                confp->chan.sig = SIG_FEATDMF_TA;
17319             } else if (!strcasecmp(v->value, "e911")) {
17320                confp->chan.sig = SIG_E911;
17321             } else if (!strcasecmp(v->value, "fgccama")) {
17322                confp->chan.sig = SIG_FGC_CAMA;
17323             } else if (!strcasecmp(v->value, "fgccamamf")) {
17324                confp->chan.sig = SIG_FGC_CAMAMF;
17325             } else if (!strcasecmp(v->value, "featb")) {
17326                confp->chan.sig = SIG_FEATB;
17327 #ifdef HAVE_PRI
17328             } else if (!strcasecmp(v->value, "pri_net")) {
17329                confp->chan.sig = SIG_PRI;
17330                confp->pri.pri.nodetype = PRI_NETWORK;
17331             } else if (!strcasecmp(v->value, "pri_cpe")) {
17332                confp->chan.sig = SIG_PRI;
17333                confp->pri.pri.nodetype = PRI_CPE;
17334             } else if (!strcasecmp(v->value, "bri_cpe")) {
17335                confp->chan.sig = SIG_BRI;
17336                confp->pri.pri.nodetype = PRI_CPE;
17337             } else if (!strcasecmp(v->value, "bri_net")) {
17338                confp->chan.sig = SIG_BRI;
17339                confp->pri.pri.nodetype = PRI_NETWORK;
17340             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17341                confp->chan.sig = SIG_BRI_PTMP;
17342                confp->pri.pri.nodetype = PRI_CPE;
17343             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17344 #if defined(HAVE_PRI_CALL_HOLD)
17345                confp->chan.sig = SIG_BRI_PTMP;
17346                confp->pri.pri.nodetype = PRI_NETWORK;
17347 #else
17348                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17349 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17350 #endif
17351 #if defined(HAVE_SS7)
17352             } else if (!strcasecmp(v->value, "ss7")) {
17353                confp->chan.sig = SIG_SS7;
17354 #endif   /* defined(HAVE_SS7) */
17355 #ifdef HAVE_OPENR2
17356             } else if (!strcasecmp(v->value, "mfcr2")) {
17357                confp->chan.sig = SIG_MFCR2;
17358 #endif
17359             } else if (!strcasecmp(v->value, "auto")) {
17360                confp->is_sig_auto = 1;
17361             } else {
17362                confp->chan.outsigmod = orig_outsigmod;
17363                confp->chan.radio = orig_radio;
17364                confp->is_sig_auto = orig_auto;
17365                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17366             }
17367           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17368             if (!strcasecmp(v->value, "em")) {
17369                confp->chan.outsigmod = SIG_EM;
17370             } else if (!strcasecmp(v->value, "em_e1")) {
17371                confp->chan.outsigmod = SIG_EM_E1;
17372             } else if (!strcasecmp(v->value, "em_w")) {
17373                confp->chan.outsigmod = SIG_EMWINK;
17374             } else if (!strcasecmp(v->value, "sf")) {
17375                confp->chan.outsigmod = SIG_SF;
17376             } else if (!strcasecmp(v->value, "sf_w")) {
17377                confp->chan.outsigmod = SIG_SFWINK;
17378             } else if (!strcasecmp(v->value, "sf_featd")) {
17379                confp->chan.outsigmod = SIG_FEATD;
17380             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17381                confp->chan.outsigmod = SIG_FEATDMF;
17382             } else if (!strcasecmp(v->value, "sf_featb")) {
17383                confp->chan.outsigmod = SIG_SF_FEATB;
17384             } else if (!strcasecmp(v->value, "sf")) {
17385                confp->chan.outsigmod = SIG_SF;
17386             } else if (!strcasecmp(v->value, "featd")) {
17387                confp->chan.outsigmod = SIG_FEATD;
17388             } else if (!strcasecmp(v->value, "featdmf")) {
17389                confp->chan.outsigmod = SIG_FEATDMF;
17390             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17391                confp->chan.outsigmod = SIG_FEATDMF_TA;
17392             } else if (!strcasecmp(v->value, "e911")) {
17393                confp->chan.outsigmod = SIG_E911;
17394             } else if (!strcasecmp(v->value, "fgccama")) {
17395                confp->chan.outsigmod = SIG_FGC_CAMA;
17396             } else if (!strcasecmp(v->value, "fgccamamf")) {
17397                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17398             } else if (!strcasecmp(v->value, "featb")) {
17399                confp->chan.outsigmod = SIG_FEATB;
17400             } else {
17401                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17402             }
17403 #ifdef HAVE_PRI
17404          } else if (!strcasecmp(v->name, "pridialplan")) {
17405             if (!strcasecmp(v->value, "national")) {
17406                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17407             } else if (!strcasecmp(v->value, "unknown")) {
17408                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17409             } else if (!strcasecmp(v->value, "private")) {
17410                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17411             } else if (!strcasecmp(v->value, "international")) {
17412                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17413             } else if (!strcasecmp(v->value, "local")) {
17414                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17415             } else if (!strcasecmp(v->value, "dynamic")) {
17416                confp->pri.pri.dialplan = -1;
17417             } else if (!strcasecmp(v->value, "redundant")) {
17418                confp->pri.pri.dialplan = -2;
17419             } else {
17420                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17421             }
17422          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17423             if (!strcasecmp(v->value, "national")) {
17424                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17425             } else if (!strcasecmp(v->value, "unknown")) {
17426                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17427             } else if (!strcasecmp(v->value, "private")) {
17428                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17429             } else if (!strcasecmp(v->value, "international")) {
17430                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17431             } else if (!strcasecmp(v->value, "local")) {
17432                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17433             } else if (!strcasecmp(v->value, "dynamic")) {
17434                confp->pri.pri.localdialplan = -1;
17435             } else if (!strcasecmp(v->value, "redundant")) {
17436                confp->pri.pri.localdialplan = -2;
17437             } else {
17438                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17439             }
17440          } else if (!strcasecmp(v->name, "switchtype")) {
17441             if (!strcasecmp(v->value, "national"))
17442                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17443             else if (!strcasecmp(v->value, "ni1"))
17444                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17445             else if (!strcasecmp(v->value, "dms100"))
17446                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17447             else if (!strcasecmp(v->value, "4ess"))
17448                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17449             else if (!strcasecmp(v->value, "5ess"))
17450                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17451             else if (!strcasecmp(v->value, "euroisdn"))
17452                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17453             else if (!strcasecmp(v->value, "qsig"))
17454                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17455             else {
17456                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17457                return -1;
17458             }
17459          } else if (!strcasecmp(v->name, "msn")) {
17460             ast_copy_string(confp->pri.pri.msn_list, v->value,
17461                sizeof(confp->pri.pri.msn_list));
17462          } else if (!strcasecmp(v->name, "nsf")) {
17463             if (!strcasecmp(v->value, "sdn"))
17464                confp->pri.pri.nsf = PRI_NSF_SDN;
17465             else if (!strcasecmp(v->value, "megacom"))
17466                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17467             else if (!strcasecmp(v->value, "tollfreemegacom"))
17468                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17469             else if (!strcasecmp(v->value, "accunet"))
17470                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17471             else if (!strcasecmp(v->value, "none"))
17472                confp->pri.pri.nsf = PRI_NSF_NONE;
17473             else {
17474                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17475                confp->pri.pri.nsf = PRI_NSF_NONE;
17476             }
17477          } else if (!strcasecmp(v->name, "priindication")) {
17478             if (!strcasecmp(v->value, "outofband"))
17479                confp->chan.priindication_oob = 1;
17480             else if (!strcasecmp(v->value, "inband"))
17481                confp->chan.priindication_oob = 0;
17482             else
17483                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17484                   v->value, v->lineno);
17485          } else if (!strcasecmp(v->name, "priexclusive")) {
17486             confp->chan.priexclusive = ast_true(v->value);
17487          } else if (!strcasecmp(v->name, "internationalprefix")) {
17488             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17489          } else if (!strcasecmp(v->name, "nationalprefix")) {
17490             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17491          } else if (!strcasecmp(v->name, "localprefix")) {
17492             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17493          } else if (!strcasecmp(v->name, "privateprefix")) {
17494             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17495          } else if (!strcasecmp(v->name, "unknownprefix")) {
17496             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17497          } else if (!strcasecmp(v->name, "resetinterval")) {
17498             if (!strcasecmp(v->value, "never"))
17499                confp->pri.pri.resetinterval = -1;
17500             else if (atoi(v->value) >= 60)
17501                confp->pri.pri.resetinterval = atoi(v->value);
17502             else
17503                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17504                   v->value, v->lineno);
17505          } else if (!strcasecmp(v->name, "minunused")) {
17506             confp->pri.pri.minunused = atoi(v->value);
17507          } else if (!strcasecmp(v->name, "minidle")) {
17508             confp->pri.pri.minidle = atoi(v->value);
17509          } else if (!strcasecmp(v->name, "idleext")) {
17510             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17511          } else if (!strcasecmp(v->name, "idledial")) {
17512             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17513          } else if (!strcasecmp(v->name, "overlapdial")) {
17514             if (ast_true(v->value)) {
17515                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17516             } else if (!strcasecmp(v->value, "incoming")) {
17517                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17518             } else if (!strcasecmp(v->value, "outgoing")) {
17519                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17520             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17521                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17522             } else {
17523                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17524             }
17525 #ifdef HAVE_PRI_PROG_W_CAUSE
17526          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17527             if (!strcasecmp(v->value, "logical")) {
17528                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17529             } else if (!strcasecmp(v->value, "physical")) {
17530                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17531             } else {
17532                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17533             }
17534 #endif
17535          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17536             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17537 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17538          } else if (!strcasecmp(v->name, "service_message_support")) {
17539             /* assuming switchtype for this channel group has been configured already */
17540             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17541                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17542                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17543                confp->pri.pri.enable_service_message_support = 1;
17544             } else {
17545                confp->pri.pri.enable_service_message_support = 0;
17546             }
17547 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17548 #ifdef HAVE_PRI_INBANDDISCONNECT
17549          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17550             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17551 #endif
17552          } else if (!strcasecmp(v->name, "pritimer")) {
17553 #ifdef PRI_GETSET_TIMERS
17554             char tmp[20];
17555             char *timerc;
17556             char *c;
17557             int timer;
17558             int timeridx;
17559 
17560             ast_copy_string(tmp, v->value, sizeof(tmp));
17561             c = tmp;
17562             timerc = strsep(&c, ",");
17563             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17564                timeridx = pri_timer2idx(timerc);
17565                timer = atoi(c);
17566                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17567                   ast_log(LOG_WARNING,
17568                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17569                      v->lineno);
17570                } else if (!timer) {
17571                   ast_log(LOG_WARNING,
17572                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17573                      c, timerc, v->lineno);
17574                } else {
17575                   confp->pri.pri.pritimers[timeridx] = timer;
17576                }
17577             } else {
17578                ast_log(LOG_WARNING,
17579                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17580                   v->value, v->lineno);
17581             }
17582 #endif /* PRI_GETSET_TIMERS */
17583          } else if (!strcasecmp(v->name, "facilityenable")) {
17584             confp->pri.pri.facilityenable = ast_true(v->value);
17585 #if defined(HAVE_PRI_AOC_EVENTS)
17586          } else if (!strcasecmp(v->name, "aoc_enable")) {
17587             confp->pri.pri.aoc_passthrough_flag = 0;
17588             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17589                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17590             }
17591             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17592                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17593             }
17594             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17595                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17596             }
17597          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17598             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17599 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17600 #if defined(HAVE_PRI_CALL_HOLD)
17601          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17602             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17603 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17604 #if defined(HAVE_PRI_CCSS)
17605          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17606             if (!strcasecmp(v->value, "global")) {
17607                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17608             } else if (!strcasecmp(v->value, "specific")) {
17609                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17610             } else {
17611                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17612             }
17613          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17614             if (!strcasecmp(v->value, "release")) {
17615                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17616             } else if (!strcasecmp(v->value, "retain")) {
17617                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17618             } else if (!strcasecmp(v->value, "do_not_care")) {
17619                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17620             } else {
17621                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17622             }
17623          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17624             if (!strcasecmp(v->value, "release")) {
17625                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17626             } else if (!strcasecmp(v->value, "retain")) {
17627                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17628             } else {
17629                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17630             }
17631 #endif   /* defined(HAVE_PRI_CCSS) */
17632 #if defined(HAVE_PRI_CALL_WAITING)
17633          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17634             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17635             if (confp->pri.pri.max_call_waiting_calls < 0) {
17636                /* Negative values are not allowed. */
17637                confp->pri.pri.max_call_waiting_calls = 0;
17638             }
17639          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17640             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17641 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17642 #if defined(HAVE_PRI_MWI)
17643          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17644             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17645                sizeof(confp->pri.pri.mwi_mailboxes));
17646 #endif   /* defined(HAVE_PRI_MWI) */
17647          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17648             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17649          } else if (!strcasecmp(v->name, "layer1_presence")) {
17650             if (!strcasecmp(v->value, "required")) {
17651                confp->pri.pri.layer1_ignored = 0;
17652             } else if (!strcasecmp(v->value, "ignore")) {
17653                confp->pri.pri.layer1_ignored = 1;
17654             } else {
17655                /* Default */
17656                confp->pri.pri.layer1_ignored = 0;
17657             }
17658 #if defined(HAVE_PRI_L2_PERSISTENCE)
17659          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17660             if (!strcasecmp(v->value, "keep_up")) {
17661                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17662             } else if (!strcasecmp(v->value, "leave_down")) {
17663                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17664             } else {
17665                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17666             }
17667 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17668 #endif /* HAVE_PRI */
17669 #if defined(HAVE_SS7)
17670          } else if (!strcasecmp(v->name, "ss7type")) {
17671             if (!strcasecmp(v->value, "itu")) {
17672                cur_ss7type = SS7_ITU;
17673             } else if (!strcasecmp(v->value, "ansi")) {
17674                cur_ss7type = SS7_ANSI;
17675             } else
17676                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17677          } else if (!strcasecmp(v->name, "linkset")) {
17678             cur_linkset = atoi(v->value);
17679          } else if (!strcasecmp(v->name, "pointcode")) {
17680             cur_pointcode = parse_pointcode(v->value);
17681          } else if (!strcasecmp(v->name, "adjpointcode")) {
17682             cur_adjpointcode = parse_pointcode(v->value);
17683          } else if (!strcasecmp(v->name, "defaultdpc")) {
17684             cur_defaultdpc = parse_pointcode(v->value);
17685          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17686             cur_cicbeginswith = atoi(v->value);
17687          } else if (!strcasecmp(v->name, "networkindicator")) {
17688             if (!strcasecmp(v->value, "national"))
17689                cur_networkindicator = SS7_NI_NAT;
17690             else if (!strcasecmp(v->value, "national_spare"))
17691                cur_networkindicator = SS7_NI_NAT_SPARE;
17692             else if (!strcasecmp(v->value, "international"))
17693                cur_networkindicator = SS7_NI_INT;
17694             else if (!strcasecmp(v->value, "international_spare"))
17695                cur_networkindicator = SS7_NI_INT_SPARE;
17696             else
17697                cur_networkindicator = -1;
17698          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17699             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17700          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17701             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17702          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17703             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17704          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17705             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17706          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17707             if (!strcasecmp(v->value, "national")) {
17708                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17709             } else if (!strcasecmp(v->value, "international")) {
17710                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17711             } else if (!strcasecmp(v->value, "subscriber")) {
17712                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17713             } else if (!strcasecmp(v->value, "unknown")) {
17714                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17715             } else if (!strcasecmp(v->value, "dynamic")) {
17716                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17717             } else {
17718                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17719             }
17720          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17721             if (!strcasecmp(v->value, "national")) {
17722                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17723             } else if (!strcasecmp(v->value, "international")) {
17724                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17725             } else if (!strcasecmp(v->value, "subscriber")) {
17726                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17727             } else if (!strcasecmp(v->value, "unknown")) {
17728                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17729             } else if (!strcasecmp(v->value, "dynamic")) {
17730                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17731             } else {
17732                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17733             }
17734          } else if (!strcasecmp(v->name, "sigchan")) {
17735             int sigchan, res;
17736             sigchan = atoi(v->value);
17737             res = linkset_addsigchan(sigchan);
17738             if (res < 0)
17739                return -1;
17740 
17741          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17742             struct dahdi_ss7 *link;
17743             link = ss7_resolve_linkset(cur_linkset);
17744             if (!link) {
17745                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17746                return -1;
17747             }
17748             if (ast_true(v->value))
17749                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17750 #endif   /* defined(HAVE_SS7) */
17751 #ifdef HAVE_OPENR2
17752          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17753             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17754             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);
17755          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17756             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17757          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17758             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17759             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17760                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17761                confp->mfcr2.variant = OR2_VAR_ITU;
17762             }
17763          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17764             confp->mfcr2.mfback_timeout = atoi(v->value);
17765             if (!confp->mfcr2.mfback_timeout) {
17766                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17767                confp->mfcr2.mfback_timeout = -1;
17768             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17769                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17770             }
17771          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17772             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17773             if (confp->mfcr2.metering_pulse_timeout > 500) {
17774                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17775             }
17776          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17777             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17778          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17779             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17780          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17781             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17782          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17783             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17784          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17785             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17786          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17787             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17788          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17789             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17790 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17791          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17792             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17793 #endif
17794          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17795             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17796          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17797             confp->mfcr2.max_ani = atoi(v->value);
17798             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17799                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17800             }
17801          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17802             confp->mfcr2.max_dnis = atoi(v->value);
17803             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17804                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17805             }
17806          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17807             confp->mfcr2.category = openr2_proto_get_category(v->value);
17808             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17809                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17810                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17811                      v->value, v->lineno);
17812             }
17813          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17814             openr2_log_level_t tmplevel;
17815             char *clevel;
17816             char *logval = ast_strdupa(v->value);
17817             while (logval) {
17818                clevel = strsep(&logval,",");
17819                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17820                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17821                   continue;
17822                }
17823                confp->mfcr2.loglevel |= tmplevel;
17824             }
17825 #endif /* HAVE_OPENR2 */
17826          } else if (!strcasecmp(v->name, "cadence")) {
17827             /* setup to scan our argument */
17828             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17829             int i;
17830             struct dahdi_ring_cadence new_cadence;
17831             int cid_location = -1;
17832             int firstcadencepos = 0;
17833             char original_args[80];
17834             int cadence_is_ok = 1;
17835 
17836             ast_copy_string(original_args, v->value, sizeof(original_args));
17837             /* 16 cadences allowed (8 pairs) */
17838             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]);
17839 
17840             /* Cadence must be even (on/off) */
17841             if (element_count % 2 == 1) {
17842                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17843                cadence_is_ok = 0;
17844             }
17845 
17846             /* Ring cadences cannot be negative */
17847             for (i = 0; i < element_count; i++) {
17848                if (c[i] == 0) {
17849                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17850                   cadence_is_ok = 0;
17851                   break;
17852                } else if (c[i] < 0) {
17853                   if (i % 2 == 1) {
17854                      /* Silence duration, negative possibly okay */
17855                      if (cid_location == -1) {
17856                         cid_location = i;
17857                         c[i] *= -1;
17858                      } else {
17859                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17860                         cadence_is_ok = 0;
17861                         break;
17862                      }
17863                   } else {
17864                      if (firstcadencepos == 0) {
17865                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17866                                  /* duration will be passed negative to the DAHDI driver */
17867                      } else {
17868                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17869                         cadence_is_ok = 0;
17870                         break;
17871                      }
17872                   }
17873                }
17874             }
17875 
17876             /* Substitute our scanned cadence */
17877             for (i = 0; i < 16; i++) {
17878                new_cadence.ringcadence[i] = c[i];
17879             }
17880 
17881             if (cadence_is_ok) {
17882                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17883                if (element_count < 2) {
17884                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17885                } else {
17886                   if (cid_location == -1) {
17887                      /* user didn't say; default to first pause */
17888                      cid_location = 1;
17889                   } else {
17890                      /* convert element_index to cidrings value */
17891                      cid_location = (cid_location + 1) / 2;
17892                   }
17893                   /* ---we like their cadence; try to install it--- */
17894                   if (!user_has_defined_cadences++)
17895                      /* this is the first user-defined cadence; clear the default user cadences */
17896                      num_cadence = 0;
17897                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17898                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17899                   else {
17900                      cadences[num_cadence] = new_cadence;
17901                      cidrings[num_cadence++] = cid_location;
17902                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17903                   }
17904                }
17905             }
17906          } else if (!strcasecmp(v->name, "ringtimeout")) {
17907             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17908          } else if (!strcasecmp(v->name, "prewink")) {
17909             confp->timing.prewinktime = atoi(v->value);
17910          } else if (!strcasecmp(v->name, "preflash")) {
17911             confp->timing.preflashtime = atoi(v->value);
17912          } else if (!strcasecmp(v->name, "wink")) {
17913             confp->timing.winktime = atoi(v->value);
17914          } else if (!strcasecmp(v->name, "flash")) {
17915             confp->timing.flashtime = atoi(v->value);
17916          } else if (!strcasecmp(v->name, "start")) {
17917             confp->timing.starttime = atoi(v->value);
17918          } else if (!strcasecmp(v->name, "rxwink")) {
17919             confp->timing.rxwinktime = atoi(v->value);
17920          } else if (!strcasecmp(v->name, "rxflash")) {
17921             confp->timing.rxflashtime = atoi(v->value);
17922          } else if (!strcasecmp(v->name, "debounce")) {
17923             confp->timing.debouncetime = atoi(v->value);
17924          } else if (!strcasecmp(v->name, "toneduration")) {
17925             int toneduration;
17926             int ctlfd;
17927             int res;
17928             struct dahdi_dialparams dps;
17929 
17930             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17931             if (ctlfd == -1) {
17932                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17933                return -1;
17934             }
17935 
17936             toneduration = atoi(v->value);
17937             if (toneduration > -1) {
17938                memset(&dps, 0, sizeof(dps));
17939 
17940                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17941                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17942                if (res < 0) {
17943                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17944                   close(ctlfd);
17945                   return -1;
17946                }
17947             }
17948             close(ctlfd);
17949          } else if (!strcasecmp(v->name, "defaultcic")) {
17950             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17951          } else if (!strcasecmp(v->name, "defaultozz")) {
17952             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17953          } else if (!strcasecmp(v->name, "mwilevel")) {
17954             mwilevel = atoi(v->value);
17955          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17956             dtmfcid_level = atoi(v->value);
17957          } else if (!strcasecmp(v->name, "reportalarms")) {
17958             if (!strcasecmp(v->value, "all"))
17959                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17960             if (!strcasecmp(v->value, "none"))
17961                report_alarms = 0;
17962             else if (!strcasecmp(v->value, "channels"))
17963                report_alarms = REPORT_CHANNEL_ALARMS;
17964             else if (!strcasecmp(v->value, "spans"))
17965                report_alarms = REPORT_SPAN_ALARMS;
17966           }
17967       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17968          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17969    }
17970 
17971    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
17972    if (confp->chan.vars) {
17973       ast_variables_destroy(confp->chan.vars);
17974       confp->chan.vars = NULL;
17975    }
17976 
17977    if (dahdichan) {
17978       /* Process the deferred dahdichan value. */
17979       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17980          &found_pseudo)) {
17981          if (confp->ignore_failed_channels) {
17982             ast_log(LOG_WARNING,
17983                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17984                dahdichan->value);
17985          } else {
17986             return -1;
17987          }
17988       }
17989    }
17990 
17991    /* mark the first channels of each DAHDI span to watch for their span alarms */
17992    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17993       if (!tmp->destroy && tmp->span != y) {
17994          tmp->manages_span_alarms = 1;
17995          y = tmp->span; 
17996       } else {
17997          tmp->manages_span_alarms = 0;
17998       }
17999    }
18000 
18001    /*< \todo why check for the pseudo in the per-channel section.
18002     * Any actual use for manual setup of the pseudo channel? */
18003    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18004       /* use the default configuration for a channel, so
18005          that any settings from real configured channels
18006          don't "leak" into the pseudo channel config
18007       */
18008       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18009 
18010       if (conf.chan.cc_params) {
18011          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18012       } else {
18013          tmp = NULL;
18014       }
18015       if (tmp) {
18016          ast_verb(3, "Automatically generated pseudo channel\n");
18017       } else {
18018          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18019       }
18020       ast_cc_config_params_destroy(conf.chan.cc_params);
18021    }
18022    return 0;
18023 }
18024 
18025 /*!
18026  * \internal
18027  * \brief Deep copy struct dahdi_chan_conf.
18028  * \since 1.8
18029  *
18030  * \param dest Destination.
18031  * \param src Source.
18032  *
18033  * \return Nothing
18034  */
18035 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18036 {
18037    struct ast_cc_config_params *cc_params;
18038 
18039    cc_params = dest->chan.cc_params;
18040    *dest = *src;
18041    dest->chan.cc_params = cc_params;
18042    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18043 }
18044 
18045 /*!
18046  * \internal
18047  * \brief Setup DAHDI channel driver.
18048  *
18049  * \param reload enum: load_module(0), reload(1), restart(2).
18050  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18051  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18052  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18053  *
18054  * \retval 0 on success.
18055  * \retval -1 on error.
18056  */
18057 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18058 {
18059    struct ast_config *cfg;
18060    struct ast_config *ucfg;
18061    struct ast_variable *v;
18062    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18063    const char *chans;
18064    const char *cat;
18065    int res;
18066 
18067 #ifdef HAVE_PRI
18068    char *c;
18069    int spanno;
18070    int i;
18071    int logicalspan;
18072    int trunkgroup;
18073    int dchannels[SIG_PRI_NUM_DCHANS];
18074 #endif
18075    int have_cfg_now;
18076    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18077 
18078    cfg = ast_config_load(config, config_flags);
18079    have_cfg_now = !!cfg;
18080    if (!cfg) {
18081       /* Error if we have no config file */
18082       if (had_cfg_before) {
18083          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18084          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18085       }
18086       cfg = ast_config_new();/* Dummy config */
18087       if (!cfg) {
18088          return 0;
18089       }
18090       ucfg = ast_config_load("users.conf", config_flags);
18091       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18092          ast_config_destroy(cfg);
18093          return 0;
18094       }
18095       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18096          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18097          ast_config_destroy(cfg);
18098          return 0;
18099       }
18100    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18101       ucfg = ast_config_load("users.conf", config_flags);
18102       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18103          return 0;
18104       }
18105       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18106          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18107          return 0;
18108       }
18109       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18110       cfg = ast_config_load(config, config_flags);
18111       have_cfg_now = !!cfg;
18112       if (!cfg) {
18113          if (had_cfg_before) {
18114             /* We should have been able to load the config. */
18115             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18116             ast_config_destroy(ucfg);
18117             return 0;
18118          }
18119          cfg = ast_config_new();/* Dummy config */
18120          if (!cfg) {
18121             ast_config_destroy(ucfg);
18122             return 0;
18123          }
18124       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18125          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18126          ast_config_destroy(ucfg);
18127          return 0;
18128       }
18129    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18130       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18131       return 0;
18132    } else {
18133       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18134       ucfg = ast_config_load("users.conf", config_flags);
18135       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18136          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18137          ast_config_destroy(cfg);
18138          return 0;
18139       }
18140    }
18141    had_cfg_before = have_cfg_now;
18142 
18143    /* It's a little silly to lock it, but we might as well just to be sure */
18144    ast_mutex_lock(&iflock);
18145 #ifdef HAVE_PRI
18146    if (reload != 1) {
18147       /* Process trunkgroups first */
18148       v = ast_variable_browse(cfg, "trunkgroups");
18149       while (v) {
18150          if (!strcasecmp(v->name, "trunkgroup")) {
18151             trunkgroup = atoi(v->value);
18152             if (trunkgroup > 0) {
18153                if ((c = strchr(v->value, ','))) {
18154                   i = 0;
18155                   memset(dchannels, 0, sizeof(dchannels));
18156                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18157                      dchannels[i] = atoi(c + 1);
18158                      if (dchannels[i] < 0) {
18159                         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);
18160                      } else
18161                         i++;
18162                      c = strchr(c + 1, ',');
18163                   }
18164                   if (i) {
18165                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18166                         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);
18167                   } else
18168                         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");
18169                   } else
18170                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18171                } else
18172                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18173             } else
18174                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18175          } else if (!strcasecmp(v->name, "spanmap")) {
18176             spanno = atoi(v->value);
18177             if (spanno > 0) {
18178                if ((c = strchr(v->value, ','))) {
18179                   trunkgroup = atoi(c + 1);
18180                   if (trunkgroup > 0) {
18181                      if ((c = strchr(c + 1, ',')))
18182                         logicalspan = atoi(c + 1);
18183                      else
18184                         logicalspan = 0;
18185                      if (logicalspan >= 0) {
18186                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18187                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18188                      } else
18189                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18190                      } else
18191                         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);
18192                   } else
18193                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18194                } else
18195                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18196             } else
18197                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18198          } else {
18199             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18200          }
18201          v = v->next;
18202       }
18203    }
18204 #endif
18205 
18206    /* Copy the default jb config over global_jbconf */
18207    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18208 
18209    mwimonitornotify[0] = '\0';
18210 
18211    v = ast_variable_browse(cfg, "channels");
18212    if ((res = process_dahdi(base_conf,
18213       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18214       v, reload, 0))) {
18215       ast_mutex_unlock(&iflock);
18216       ast_config_destroy(cfg);
18217       if (ucfg) {
18218          ast_config_destroy(ucfg);
18219       }
18220       return res;
18221    }
18222 
18223    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18224    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18225       /* [channels] and [trunkgroups] are used. Let's also reserve
18226        * [globals] and [general] for future use
18227        */
18228       if (!strcasecmp(cat, "general") ||
18229          !strcasecmp(cat, "trunkgroups") ||
18230          !strcasecmp(cat, "globals") ||
18231          !strcasecmp(cat, "channels")) {
18232          continue;
18233       }
18234 
18235       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18236       if (ast_strlen_zero(chans)) {
18237          /* Section is useless without a dahdichan value present. */
18238          continue;
18239       }
18240 
18241       /* Copy base_conf to conf. */
18242       deep_copy_dahdi_chan_conf(conf, base_conf);
18243 
18244       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18245          ast_mutex_unlock(&iflock);
18246          ast_config_destroy(cfg);
18247          if (ucfg) {
18248             ast_config_destroy(ucfg);
18249          }
18250          return res;
18251       }
18252    }
18253 
18254    ast_config_destroy(cfg);
18255 
18256    if (ucfg) {
18257       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18258       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18259       process_dahdi(base_conf,
18260          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18261          ast_variable_browse(ucfg, "general"), 1, 0);
18262 
18263       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18264          if (!strcasecmp(cat, "general")) {
18265             continue;
18266          }
18267 
18268          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18269          if (ast_strlen_zero(chans)) {
18270             /* Section is useless without a dahdichan value present. */
18271             continue;
18272          }
18273 
18274          /* Copy base_conf to conf. */
18275          deep_copy_dahdi_chan_conf(conf, base_conf);
18276 
18277          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18278             ast_config_destroy(ucfg);
18279             ast_mutex_unlock(&iflock);
18280             return res;
18281          }
18282       }
18283       ast_config_destroy(ucfg);
18284    }
18285    ast_mutex_unlock(&iflock);
18286 
18287 #ifdef HAVE_PRI
18288    if (reload != 1) {
18289       int x;
18290       for (x = 0; x < NUM_SPANS; x++) {
18291          if (pris[x].pri.pvts[0]) {
18292             prepare_pri(pris + x);
18293             if (sig_pri_start_pri(&pris[x].pri)) {
18294                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18295                return -1;
18296             } else
18297                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18298          }
18299       }
18300    }
18301 #endif
18302 #if defined(HAVE_SS7)
18303    if (reload != 1) {
18304       int x;
18305       for (x = 0; x < NUM_SPANS; x++) {
18306          if (linksets[x].ss7.ss7) {
18307             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18308             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18309                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18310                return -1;
18311             } else
18312                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18313          }
18314       }
18315    }
18316 #endif   /* defined(HAVE_SS7) */
18317 #ifdef HAVE_OPENR2
18318    if (reload != 1) {
18319       int x;
18320       for (x = 0; x < r2links_count; x++) {
18321          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18322             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18323             return -1;
18324          } else {
18325             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18326          }
18327       }
18328    }
18329 #endif
18330    /* And start the monitor for the first time */
18331    restart_monitor();
18332    return 0;
18333 }
18334 
18335 /*!
18336  * \internal
18337  * \brief Setup DAHDI channel driver.
18338  *
18339  * \param reload enum: load_module(0), reload(1), restart(2).
18340  *
18341  * \retval 0 on success.
18342  * \retval -1 on error.
18343  */
18344 static int setup_dahdi(int reload)
18345 {
18346    int res;
18347    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18348    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18349    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18350 
18351    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18352       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18353    } else {
18354       res = -1;
18355    }
18356    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18357    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18358    ast_cc_config_params_destroy(conf.chan.cc_params);
18359 
18360    return res;
18361 }
18362 
18363 /*!
18364  * \internal
18365  * \brief Callback used to generate the dahdi status tree.
18366  * \param[in] search The search pattern tree.
18367  * \retval NULL on error.
18368  * \retval non-NULL The generated tree.
18369  */
18370 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18371       struct ast_data *data_root)
18372 {
18373    int ctl, res, span;
18374    struct ast_data *data_span, *data_alarms;
18375    struct dahdi_spaninfo s;
18376 
18377    ctl = open("/dev/dahdi/ctl", O_RDWR);
18378    if (ctl < 0) {
18379       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18380       return -1;
18381    }
18382    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18383       s.spanno = span;
18384       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18385       if (res) {
18386          continue;
18387       }
18388 
18389       data_span = ast_data_add_node(data_root, "span");
18390       if (!data_span) {
18391          continue;
18392       }
18393       ast_data_add_str(data_span, "description", s.desc);
18394 
18395       /* insert the alarms status */
18396       data_alarms = ast_data_add_node(data_span, "alarms");
18397       if (!data_alarms) {
18398          continue;
18399       }
18400 
18401       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18402       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18403       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18404       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18405       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18406       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18407 
18408       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18409       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18410       ast_data_add_int(data_span, "crc4", s.crc4count);
18411       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18412                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18413                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18414                      "CAS");
18415       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18416                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18417                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18418                      "Unknown");
18419       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18420                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18421                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18422       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18423 
18424       /* if this span doesn't match remove it. */
18425       if (!ast_data_search_match(search, data_span)) {
18426          ast_data_remove_node(data_root, data_span);
18427       }
18428    }
18429    close(ctl);
18430 
18431    return 0;
18432 }
18433 
18434 /*!
18435  * \internal
18436  * \brief Callback used to generate the dahdi channels tree.
18437  * \param[in] search The search pattern tree.
18438  * \retval NULL on error.
18439  * \retval non-NULL The generated tree.
18440  */
18441 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18442       struct ast_data *data_root)
18443 {
18444    struct dahdi_pvt *tmp;
18445    struct ast_data *data_channel;
18446 
18447    ast_mutex_lock(&iflock);
18448    for (tmp = iflist; tmp; tmp = tmp->next) {
18449       data_channel = ast_data_add_node(data_root, "channel");
18450       if (!data_channel) {
18451          continue;
18452       }
18453 
18454       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18455 
18456       /* if this channel doesn't match remove it. */
18457       if (!ast_data_search_match(search, data_channel)) {
18458          ast_data_remove_node(data_root, data_channel);
18459       }
18460    }
18461    ast_mutex_unlock(&iflock);
18462 
18463    return 0;
18464 }
18465 
18466 /*!
18467  * \internal
18468  * \brief Callback used to generate the dahdi channels tree.
18469  * \param[in] search The search pattern tree.
18470  * \retval NULL on error.
18471  * \retval non-NULL The generated tree.
18472  */
18473 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18474       struct ast_data *data_root)
18475 {
18476    int pseudo_fd = -1;
18477    struct dahdi_versioninfo vi = {
18478       .version = "Unknown",
18479       .echo_canceller = "Unknown"
18480    };
18481 
18482    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18483       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18484       return -1;
18485    }
18486 
18487    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18488       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18489    }
18490 
18491    close(pseudo_fd);
18492 
18493    ast_data_add_str(data_root, "value", vi.version);
18494    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18495 
18496    return 0;
18497 }
18498 
18499 static const struct ast_data_handler dahdi_status_data_provider = {
18500    .version = AST_DATA_HANDLER_VERSION,
18501    .get = dahdi_status_data_provider_get
18502 };
18503 
18504 static const struct ast_data_handler dahdi_channels_data_provider = {
18505    .version = AST_DATA_HANDLER_VERSION,
18506    .get = dahdi_channels_data_provider_get
18507 };
18508 
18509 static const struct ast_data_handler dahdi_version_data_provider = {
18510    .version = AST_DATA_HANDLER_VERSION,
18511    .get = dahdi_version_data_provider_get
18512 };
18513 
18514 static const struct ast_data_entry dahdi_data_providers[] = {
18515    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18516    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18517    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18518 };
18519 
18520 static int load_module(void)
18521 {
18522    int res;
18523 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18524    int y;
18525 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18526 
18527 #ifdef HAVE_PRI
18528    memset(pris, 0, sizeof(pris));
18529    for (y = 0; y < NUM_SPANS; y++) {
18530       sig_pri_init_pri(&pris[y].pri);
18531    }
18532    pri_set_error(dahdi_pri_error);
18533    pri_set_message(dahdi_pri_message);
18534    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18535 #ifdef HAVE_PRI_PROG_W_CAUSE
18536    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18537 #endif
18538 #if defined(HAVE_PRI_CCSS)
18539    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18540       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18541       __unload_module();
18542       return AST_MODULE_LOAD_FAILURE;
18543    }
18544 #endif   /* defined(HAVE_PRI_CCSS) */
18545    if (sig_pri_load(
18546 #if defined(HAVE_PRI_CCSS)
18547       dahdi_pri_cc_type
18548 #else
18549       NULL
18550 #endif   /* defined(HAVE_PRI_CCSS) */
18551       )) {
18552       __unload_module();
18553       return AST_MODULE_LOAD_FAILURE;
18554    }
18555 #endif
18556 #if defined(HAVE_SS7)
18557    memset(linksets, 0, sizeof(linksets));
18558    for (y = 0; y < NUM_SPANS; y++) {
18559       sig_ss7_init_linkset(&linksets[y].ss7);
18560    }
18561    ss7_set_error(dahdi_ss7_error);
18562    ss7_set_message(dahdi_ss7_message);
18563 #endif   /* defined(HAVE_SS7) */
18564    res = setup_dahdi(0);
18565    /* Make sure we can register our DAHDI channel type */
18566    if (res)
18567       return AST_MODULE_LOAD_DECLINE;
18568    if (ast_channel_register(&dahdi_tech)) {
18569       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18570       __unload_module();
18571       return AST_MODULE_LOAD_FAILURE;
18572    }
18573 #ifdef HAVE_PRI
18574    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18575 #endif
18576 #if defined(HAVE_SS7)
18577    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18578 #endif   /* defined(HAVE_SS7) */
18579 #ifdef HAVE_OPENR2
18580    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18581    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18582 #endif
18583 
18584    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18585    /* register all the data providers */
18586    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18587    memset(round_robin, 0, sizeof(round_robin));
18588    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18589    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18590    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18591    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18592    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18593    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18594    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18595 
18596    ast_cond_init(&ss_thread_complete, NULL);
18597 
18598    return res;
18599 }
18600 
18601 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18602 {
18603 #define  END_SILENCE_LEN 400
18604 #define  HEADER_MS 50
18605 #define  TRAILER_MS 5
18606 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18607 #define  ASCII_BYTES_PER_CHAR 80
18608 
18609    unsigned char *buf,*mybuf;
18610    struct dahdi_pvt *p = c->tech_pvt;
18611    struct pollfd fds[1];
18612    int size,res,fd,len,x;
18613    int bytes=0;
18614    /* Initial carrier (imaginary) */
18615    float cr = 1.0;
18616    float ci = 0.0;
18617    float scont = 0.0;
18618    int idx;
18619 
18620    idx = dahdi_get_index(c, p, 0);
18621    if (idx < 0) {
18622       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18623       return -1;
18624    }
18625    if (!text[0]) return(0); /* if nothing to send, don't */
18626    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18627    if (p->mate)
18628       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18629    else
18630       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18631    if (!buf)
18632       return -1;
18633    mybuf = buf;
18634    if (p->mate) {
18635       int codec = AST_LAW(p);
18636       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18637          PUT_CLID_MARKMS;
18638       }
18639       /* Put actual message */
18640       for (x = 0; text[x]; x++) {
18641          PUT_CLID(text[x]);
18642       }
18643       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18644          PUT_CLID_MARKMS;
18645       }
18646       len = bytes;
18647       buf = mybuf;
18648    } else {
18649       len = tdd_generate(p->tdd, buf, text);
18650       if (len < 1) {
18651          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18652          ast_free(mybuf);
18653          return -1;
18654       }
18655    }
18656    memset(buf + len, 0x7f, END_SILENCE_LEN);
18657    len += END_SILENCE_LEN;
18658    fd = p->subs[idx].dfd;
18659    while (len) {
18660       if (ast_check_hangup(c)) {
18661          ast_free(mybuf);
18662          return -1;
18663       }
18664       size = len;
18665       if (size > READ_SIZE)
18666          size = READ_SIZE;
18667       fds[0].fd = fd;
18668       fds[0].events = POLLOUT | POLLPRI;
18669       fds[0].revents = 0;
18670       res = poll(fds, 1, -1);
18671       if (!res) {
18672          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18673          continue;
18674       }
18675       /* if got exception */
18676       if (fds[0].revents & POLLPRI) {
18677          ast_free(mybuf);
18678          return -1;
18679       }
18680       if (!(fds[0].revents & POLLOUT)) {
18681          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18682          continue;
18683       }
18684       res = write(fd, buf, size);
18685       if (res != size) {
18686          if (res == -1) {
18687             ast_free(mybuf);
18688             return -1;
18689          }
18690          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18691          break;
18692       }
18693       len -= size;
18694       buf += size;
18695    }
18696    ast_free(mybuf);
18697    return(0);
18698 }
18699 
18700 
18701 static int reload(void)
18702 {
18703    int res = 0;
18704 
18705    res = setup_dahdi(1);
18706    if (res) {
18707       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18708       return -1;
18709    }
18710    return 0;
18711 }
18712 
18713 /* This is a workaround so that menuselect displays a proper description
18714  * AST_MODULE_INFO(, , "DAHDI Telephony"
18715  */
18716 
18717 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18718    .load = load_module,
18719    .unload = unload_module,
18720    .reload = reload,
18721    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18722       .nonoptreq = "res_smdi",
18723    );